switch (op1->ts.type)
{
case BT_INTEGER:
+ case BT_UNSIGNED:
rc = mpz_cmp (op1->value.integer, op2->value.integer);
break;
gcc_fallthrough ();
/* Numeric binary */
case INTRINSIC_POWER:
- if (flag_unsigned)
+ if (flag_unsigned && op == INTRINSIC_POWER)
{
if (op1->ts.type == BT_UNSIGNED || op2->ts.type == BT_UNSIGNED)
goto runtime;
return result;
}
+/* Convert real to unsigned. */
+
+gfc_expr *
+gfc_real2uint (gfc_expr *src, int kind)
+{
+ gfc_expr *result;
+ arith rc;
+ bool did_warn = false;
+ int k;
+
+ if (src->ts.type != BT_REAL)
+ return NULL;
+
+ result = gfc_get_constant_expr (BT_UNSIGNED, kind, &src->where);
+
+ gfc_mpfr_to_mpz (result->value.integer, src->value.real, &src->where);
+ if ((rc = gfc_check_unsigned_range (result->value.integer, kind)) != ARITH_OK)
+ {
+ arith_error (rc, &src->ts, &result->ts, &src->where);
+ gfc_free_expr (result);
+ return NULL;
+ }
+
+ k = gfc_validate_kind (BT_UNSIGNED, kind, false);
+ mpz_and (result->value.integer, result->value.integer,
+ gfc_unsigned_kinds[k].huge);
+
+ /* If there was a fractional part, warn about this. */
+
+ if (warn_conversion)
+ {
+ mpfr_t f;
+ mpfr_init (f);
+ mpfr_frac (f, src->value.real, GFC_RND_MODE);
+ if (mpfr_cmp_si (f, 0) != 0)
+ {
+ gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
+ "from %qs to %qs at %L", gfc_typename (&src->ts),
+ gfc_typename (&result->ts), &src->where);
+ did_warn = true;
+ }
+ mpfr_clear (f);
+ }
+ if (!did_warn && warn_conversion_extra)
+ {
+ gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+ "at %L", gfc_typename (&src->ts),
+ gfc_typename (&result->ts), &src->where);
+ }
+
+ return result;
+}
/* Convert real to real. */
return result;
}
+/* Convert complex to integer. */
+
+gfc_expr *
+gfc_complex2uint (gfc_expr *src, int kind)
+{
+ gfc_expr *result;
+ arith rc;
+ bool did_warn = false;
+ int k;
+
+ if (src->ts.type != BT_COMPLEX)
+ return NULL;
+
+ result = gfc_get_constant_expr (BT_UNSIGNED, kind, &src->where);
+
+ gfc_mpfr_to_mpz (result->value.integer, mpc_realref (src->value.complex),
+ &src->where);
+
+ if ((rc = gfc_check_unsigned_range (result->value.integer, kind)) != ARITH_OK)
+ {
+ arith_error (rc, &src->ts, &result->ts, &src->where);
+ gfc_free_expr (result);
+ return NULL;
+ }
+
+ k = gfc_validate_kind (BT_UNSIGNED, kind, false);
+ mpz_and (result->value.integer, result->value.integer,
+ gfc_unsigned_kinds[k].huge);
+
+ if (warn_conversion || warn_conversion_extra)
+ {
+ int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+
+ /* See if we discarded an imaginary part. */
+ if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
+ {
+ gfc_warning_now (w, "Non-zero imaginary part discarded "
+ "in conversion from %qs to %qs at %L",
+ gfc_typename(&src->ts), gfc_typename (&result->ts),
+ &src->where);
+ did_warn = true;
+ }
+
+ else {
+ mpfr_t f;
+
+ mpfr_init (f);
+ mpfr_frac (f, src->value.real, GFC_RND_MODE);
+ if (mpfr_cmp_si (f, 0) != 0)
+ {
+ gfc_warning_now (w, "Change of value in conversion from "
+ "%qs to %qs at %L", gfc_typename (&src->ts),
+ gfc_typename (&result->ts), &src->where);
+ did_warn = true;
+ }
+ mpfr_clear (f);
+ }
+
+ if (!did_warn && warn_conversion_extra)
+ {
+ gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+ "at %L", gfc_typename (&src->ts),
+ gfc_typename (&result->ts), &src->where);
+ }
+ }
+
+ return result;
+}
+
/* Convert complex to real. */
return result;
}
+/* Convert logical to unsigned. */
+
+gfc_expr *
+gfc_log2uint (gfc_expr *src, int kind)
+{
+ gfc_expr *result;
+
+ if (src->ts.type != BT_LOGICAL)
+ return NULL;
+
+ result = gfc_get_constant_expr (BT_UNSIGNED, kind, &src->where);
+ mpz_set_si (result->value.integer, src->value.logical);
+
+ return result;
+}
+
/* Convert integer to logical. */
return result;
}
+/* Convert unsigned to logical. */
+
+gfc_expr *
+gfc_uint2log (gfc_expr *src, int kind)
+{
+ gfc_expr *result;
+
+ if (src->ts.type != BT_UNSIGNED)
+ return NULL;
+
+ result = gfc_get_constant_expr (BT_LOGICAL, kind, &src->where);
+ result->value.logical = (mpz_cmp_si (src->value.integer, 0) != 0);
+
+ return result;
+}
+
/* Convert character to character. We only use wide strings internally,
so we only set the kind. */
gfc_expr *gfc_uint2real (gfc_expr *, int);
gfc_expr *gfc_uint2complex (gfc_expr *, int);
gfc_expr *gfc_real2int (gfc_expr *, int);
+gfc_expr *gfc_real2uint (gfc_expr *, int);
gfc_expr *gfc_real2real (gfc_expr *, int);
gfc_expr *gfc_real2complex (gfc_expr *, int);
gfc_expr *gfc_complex2int (gfc_expr *, int);
+gfc_expr *gfc_complex2uint (gfc_expr *, int);
gfc_expr *gfc_complex2real (gfc_expr *, int);
gfc_expr *gfc_complex2complex (gfc_expr *, int);
gfc_expr *gfc_log2log (gfc_expr *, int);
gfc_expr *gfc_log2int (gfc_expr *, int);
+gfc_expr *gfc_log2uint (gfc_expr *, int);
gfc_expr *gfc_int2log (gfc_expr *, int);
+gfc_expr *gfc_uint2log (gfc_expr *, int);
gfc_expr *gfc_hollerith2int (gfc_expr *, int);
gfc_expr *gfc_hollerith2real (gfc_expr *, int);
gfc_expr *gfc_hollerith2complex (gfc_expr *, int);
return true;
}
+/* Same as above for UNSIGNED, but much simpler because
+ of wraparound. */
+bool
+gfc_boz2uint (gfc_expr *x, int kind)
+{
+ int k;
+ if (!is_boz_constant(x))
+ return false;
+ mpz_init (x->value.integer);
+ mpz_set_str (x->value.integer, x->boz.str, x->boz.rdx);
+ k = gfc_validate_kind (BT_UNSIGNED, kind, false);
+ if (mpz_cmp (x->value.integer, gfc_unsigned_kinds[k].huge) > 0)
+ {
+ gfc_warning (0, _("BOZ contstant truncated at %L"), &x->where);
+ mpz_and (x->value.integer, x->value.integer, gfc_unsigned_kinds[k].huge);
+ }
+
+ /* Clear boz info. */
+ x->boz.rdx = 0;
+ x->boz.len = 0;
+ free (x->boz.str);
+
+ return true;
+}
/* Make sure an expression is a scalar. */
static bool
return true;
}
+bool
+gfc_check_uint (gfc_expr *x, gfc_expr *kind)
+{
+
+ if (!flag_unsigned)
+ {
+ gfc_error ("UINT intrinsic only valid with %<-funsigned%> at %L",
+ &x->where);
+ return false;
+ }
+
+ /* BOZ is dealt within simplify_uint*. */
+ if (x->ts.type == BT_BOZ)
+ return true;
+
+ if (!numeric_check (x, 0))
+ return false;
+
+ if (!kind_check (kind, 1, BT_INTEGER))
+ return false;
+
+ return true;
+}
bool
gfc_check_intconv (gfc_expr *x)
/* Add this at the end, so maybe the module format
remains compatible. */
- GFC_ISYM_SU_KIND
-
+ GFC_ISYM_SU_KIND,
+ GFC_ISYM_UINT,
};
enum init_local_logical
bool gfc_calculate_transfer_sizes (gfc_expr*, gfc_expr*, gfc_expr*,
size_t*, size_t*, size_t*);
bool gfc_boz2int (gfc_expr *, int);
+bool gfc_boz2uint (gfc_expr *, int);
bool gfc_boz2real (gfc_expr *, int);
bool gfc_invalid_boz (const char *, locus *);
bool gfc_invalid_null_arg (gfc_expr *);
make_generic ("long", GFC_ISYM_LONG, GFC_STD_GNU);
+ add_sym_2 ("uint", GFC_ISYM_UINT, CLASS_ELEMENTAL, ACTUAL_NO, BT_UNSIGNED, di, GFC_STD_GNU,
+ gfc_check_uint, gfc_simplify_uint, gfc_resolve_uint,
+ a, BT_REAL, dr, REQUIRED, kind, BT_INTEGER, di, OPTIONAL);
+
+ make_generic ("uint", GFC_ISYM_UINT, GFC_STD_GNU);
+
add_sym_2 ("ior", GFC_ISYM_IOR, CLASS_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di,
GFC_STD_F95,
gfc_check_iand_ieor_ior, gfc_simplify_ior, gfc_resolve_ior,
bool gfc_check_index (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
bool gfc_check_int (gfc_expr *, gfc_expr *);
bool gfc_check_intconv (gfc_expr *);
+bool gfc_check_uint (gfc_expr *, gfc_expr *);
bool gfc_check_irand (gfc_expr *);
bool gfc_check_is_contiguous (gfc_expr *);
bool gfc_check_isatty (gfc_expr *);
gfc_expr *gfc_simplify_image_status (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_index (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_int (gfc_expr *, gfc_expr *);
+gfc_expr *gfc_simplify_uint (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_int2 (gfc_expr *);
gfc_expr *gfc_simplify_int8 (gfc_expr *);
gfc_expr *gfc_simplify_long (gfc_expr *);
void gfc_resolve_iany (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
void gfc_resolve_idnint (gfc_expr *, gfc_expr *);
void gfc_resolve_int (gfc_expr *, gfc_expr *, gfc_expr *);
+void gfc_resolve_uint (gfc_expr *, gfc_expr*, gfc_expr *);
void gfc_resolve_int2 (gfc_expr *, gfc_expr *);
void gfc_resolve_int8 (gfc_expr *, gfc_expr *);
void gfc_resolve_long (gfc_expr *, gfc_expr *);
gfc_type_abi_kind (&a->ts));
}
+void
+gfc_resolve_uint (gfc_expr *f, gfc_expr *a, gfc_expr *kind)
+{
+ f->ts.type = BT_UNSIGNED;
+ f->ts.kind = (kind == NULL)
+ ? gfc_default_integer_kind : mpz_get_si (kind->value.integer);
+ f->value.function.name
+ = gfc_get_string ("__uint_%d_%c%d", f->ts.kind,
+ gfc_type_letter (a->ts.type),
+ gfc_type_abi_kind (&a->ts));
+}
+
void
gfc_resolve_int2 (gfc_expr *f, gfc_expr *a)
return range_check (result, "INDEX");
}
-
static gfc_expr *
simplify_intconv (gfc_expr *e, int kind, const char *name)
{
return range_check (result, "IDINT");
}
+gfc_expr *
+gfc_simplify_uint (gfc_expr *e, gfc_expr *k)
+{
+ gfc_expr *result = NULL;
+ int kind;
+
+ kind = get_kind (BT_INTEGER, k, "INT", gfc_default_integer_kind);
+ if (kind == -1)
+ return &gfc_bad_expr;
+
+ /* Convert BOZ to integer, and return without range checking. */
+ if (e->ts.type == BT_BOZ)
+ {
+ if (!gfc_boz2int (e, kind))
+ return NULL;
+ result = gfc_copy_expr (e);
+ return result;
+ }
+
+ if (e->expr_type != EXPR_CONSTANT)
+ return NULL;
+
+ result = gfc_convert_constant (e, BT_UNSIGNED, kind);
+
+ if (result == &gfc_bad_expr)
+ return &gfc_bad_expr;
+
+ return range_check (result, "UINT");
+}
+
gfc_expr *
gfc_simplify_ior (gfc_expr *x, gfc_expr *y)
case BT_COMPLEX:
f = gfc_uint2complex;
break;
+ case BT_LOGICAL:
+ f = gfc_uint2log;
+ break;
default:
goto oops;
}
case BT_INTEGER:
f = gfc_real2int;
break;
+ case BT_UNSIGNED:
+ f = gfc_real2uint;
+ break;
case BT_REAL:
f = gfc_real2real;
break;
case BT_INTEGER:
f = gfc_complex2int;
break;
+ case BT_UNSIGNED:
+ f = gfc_complex2uint;
+ break;
case BT_REAL:
f = gfc_complex2real;
break;
case BT_INTEGER:
f = gfc_log2int;
break;
+ case BT_UNSIGNED:
+ f = gfc_log2uint;
+ break;
case BT_LOGICAL:
f = gfc_log2log;
break;
f = gfc_hollerith2int;
break;
+ /* Hollerith is for legacy code, we do not currently support
+ converting this to UNSIGNED. */
+ case BT_UNSIGNED:
+ goto oops;
+
case BT_REAL:
f = gfc_hollerith2real;
break;
f = gfc_character2int;
break;
+ case BT_UNSIGNED:
+ goto oops;
+
case BT_REAL:
f = gfc_character2real;
break;
case GFC_ISYM_INT2:
case GFC_ISYM_INT8:
case GFC_ISYM_LONG:
+ case GFC_ISYM_UINT:
gfc_conv_intrinsic_int (se, expr, RND_TRUNC);
break;
u = 1u
v = 42u
if (u + v /= 43u) then
- stop 1
+ error stop 1
end if
- if (u1 /= 1 .or. u2 /= 2 .or. u4 /= 4 .or. u8 /= 8) stop 2
+ if (u1 /= 1 .or. u2 /= 2 .or. u4 /= 4 .or. u8 /= 8) error stop 2
end program memain
write (10,*) uw,-1
rewind 10
read (10,*) ur,vr
- if (ur /= 10u .or. vr /= 4294967295u) stop 1
+ if (ur /= 10u .or. vr /= 4294967295u) error stop 1
rewind 10
write (10,*) 17179869184u_8
rewind 10
read (10,*) u8
- if (u8 /= 17179869184u_8) stop 2
+ if (u8 /= 17179869184u_8) error stop 2
end program main
write (10,'(I4)') -1
rewind 10
read (10,'(I4)') u
- if (u /= 1u) stop 1
+ if (u /= 1u) error stop 1
read (10,'(I4)') u
- if (u /= 4294967295u) stop 2
+ if (u /= 4294967295u) error stop 2
end program main
rewind 10
do i=1,n_int
read (10,*) vi
- if (vi /= ires(i)) stop 1
+ if (vi /= ires(i)) error stop 1
end do
rewind 10
rewind 10
do i=1,n_int
read (10,*) vi
- if (vi /= ires(i)) stop 2
+ if (vi /= ires(i)) error stop 2
end do
rewind 10
rewind 10
do i=1, n_real
read (10, *) vr
- if (vr /= rres(i)) stop 3
+ if (vr /= rres(i)) error stop 3
end do
rewind 10
rewind 10
do i=1, n_real
read (10, *) vr
- if (vr /= rres(i)) stop 4
+ if (vr /= rres(i)) error stop 4
end do
rewind 10
rewind 10
do i=1,n_real
read (10, *) vc
- if (real(vc) /= rres(i)) stop 5
- if (aimag(vc) /= rres(i)) stop 6
+ if (real(vc) /= rres(i)) error stop 5
+ if (aimag(vc) /= rres(i)) error stop 6
end do
end program main
--- /dev/null
+! { dg-do run }
+! { dg-options "-funsigned" }
+! Test the uint intrinsic.
+program main
+ implicit none
+ integer :: i
+ real :: r
+ complex :: c
+ if (1u /= uint(1)) error stop 1
+ if (2u /= uint(2.0)) error stop 2
+ if (3u /= uint((3.2,0.))) error stop 3
+
+ i = 4
+ if (uint(i) /= 4u) error stop 4
+ r = 5.2
+ if (uint(r) /= 5u) error stop 5
+ c = (6.2,-1.2)
+ if (uint(c) /= 6u) error stop 6
+end program main