gfc_typespec ts;
ts.kind = result->ts.kind;
ts.type = BT_REAL;
- gfc_convert_boz (x, &ts);
+ if (!gfc_convert_boz (x, &ts))
+ return &gfc_bad_expr;
mpfr_set (result->value.complex.r, x->value.real, GFC_RND_MODE);
}
gfc_typespec ts;
ts.kind = result->ts.kind;
ts.type = BT_REAL;
- gfc_convert_boz (y, &ts);
+ if (!gfc_convert_boz (y, &ts))
+ return &gfc_bad_expr;
mpfr_set (result->value.complex.i, y->value.real, GFC_RND_MODE);
}
ts.type = BT_REAL;
ts.kind = gfc_default_double_kind;
result = gfc_copy_expr (e);
- gfc_convert_boz (result, &ts);
+ if (!gfc_convert_boz (result, &ts))
+ return &gfc_bad_expr;
}
return range_check (result, "DBLE");
ts.kind = gfc_default_real_kind;
result = gfc_copy_expr (a);
- gfc_convert_boz (result, &ts);
+ if (!gfc_convert_boz (result, &ts))
+ return &gfc_bad_expr;
}
else
result = gfc_int2real (a, gfc_default_real_kind);
ts.type = BT_REAL;
ts.kind = kind;
result = gfc_copy_expr (e);
- gfc_convert_boz (result, &ts);
+ if (!gfc_convert_boz (result, &ts))
+ return &gfc_bad_expr;
}
return range_check (result, "REAL");
}
return len;
}
-void
+
+/* Transfer the bitpattern of a (integer) BOZ to real or complex variables.
+ When successful, no BOZ or nothing to do, true is returned. */
+
+bool
gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
{
- size_t buffer_size;
+ size_t buffer_size, boz_bit_size, ts_bit_size;
+ int index;
unsigned char *buffer;
if (!expr->is_boz)
- return;
+ return true;
gcc_assert (expr->expr_type == EXPR_CONSTANT
&& expr->ts.type == BT_INTEGER);
/* Don't convert BOZ to logical, character, derived etc. */
if (ts->type == BT_REAL)
- buffer_size = size_float (ts->kind);
+ {
+ buffer_size = size_float (ts->kind);
+ ts_bit_size = buffer_size * 8;
+ }
else if (ts->type == BT_COMPLEX)
- buffer_size = size_complex (ts->kind);
+ {
+ buffer_size = size_complex (ts->kind);
+ ts_bit_size = buffer_size * 8 / 2;
+ }
else
- return;
+ return true;
+
+ /* Convert BOZ to the smallest possible integer kind. */
+ boz_bit_size = mpz_sizeinbase (expr->value.integer, 2);
+ if (boz_bit_size > ts_bit_size)
+ {
+ gfc_error_now ("BOZ constant at %L is too large (%ld vs %ld bits)",
+ &expr->where, (long) boz_bit_size, (long) ts_bit_size);
+ return false;
+ }
+
+ for (index = 0; gfc_integer_kinds[index].kind != 0; ++index)
+ {
+ if ((unsigned) gfc_integer_kinds[index].bit_size >= ts_bit_size)
+ break;
+ }
+
+ expr->ts.kind = gfc_integer_kinds[index].kind;
buffer_size = MAX (buffer_size, size_integer (expr->ts.kind));
buffer = (unsigned char*)alloca (buffer_size);
expr->is_boz = 0;
expr->ts.type = ts->type;
expr->ts.kind = ts->kind;
+
+ return true;
}
complex :: z1 = cmplx(b'10101',-4.0)
complex :: z2 = cmplx(5.0, o'01245')
-if (r2c /= 13107.0) stop '1'
-if (rc /= 1.83668190E-41) stop '2'
-if (dc /= 0.30102999566398120) stop '3'
-if (real(z1c) /= 2.94272678E-44 .or. aimag(z1c) /= -4.0) stop '4'
-if (real(z2c) /= 5.0 .or. aimag(z2c) /= 9.48679060E-43) stop '5'
-
-if (r2 /= 13107.0) stop '1'
-if (r /= 1.83668190E-41) stop '2'
-if (d /= 0.30102999566398120) stop '3'
-if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) stop '5'
+if (r2c /= 13107.0) call abort()
+if (rc /= 1.83668190E-41) call abort()
+if (dc /= 0.30102999566398120) call abort()
+if (real(z1c) /= 2.94272678E-44 .or. aimag(z1c) /= -4.0) call abort()
+if (real(z2c) /= 5.0 .or. aimag(z2c) /= 9.48679060E-43) call abort()
+
+if (r2 /= 13107.0) call abort()
+if (r /= 1.83668190E-41) call abort()
+if (d /= 0.30102999566398120) call abort()
+if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) call abort()
r2 = dble(int(z'3333'))
r = real(z'3333')
z1 = cmplx(b'10101',-4.0)
z2 = cmplx(5.0, o'01245')
-if (r2 /= 13107.0) stop '1'
-if (r /= 1.83668190E-41) stop '2'
-if (d /= 0.30102999566398120) stop '3'
-if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) stop '5'
+if (r2 /= 13107.0) call abort()
+if (r /= 1.83668190E-41) call abort()
+if (d /= 0.30102999566398120) call abort()
+if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) call abort()
call test4()
call test8()
complex :: z1 = cmplx(b'10101',-4.0, kind=4)
complex :: z2 = cmplx(5.0, o'01245', kind=4)
-if (r2c /= 13107.0) stop '1'
-if (rc /= 1.83668190E-41) stop '2'
-if (real(z1c) /= 2.94272678E-44 .or. aimag(z1c) /= -4.0) stop '4'
-if (real(z2c) /= 5.0 .or. aimag(z2c) /= 9.48679060E-43) stop '5'
+if (r2c /= 13107.0) call abort()
+if (rc /= 1.83668190E-41) call abort()
+if (real(z1c) /= 2.94272678E-44 .or. aimag(z1c) /= -4.0) call abort()
+if (real(z2c) /= 5.0 .or. aimag(z2c) /= 9.48679060E-43) call abort()
-if (r2 /= 13107.0) stop '1'
-if (r /= 1.83668190E-41) stop '2'
-if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) stop '5'
+if (r2 /= 13107.0) call abort()
+if (r /= 1.83668190E-41) call abort()
+if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) call abort()
r2 = real(int(z'3333'), kind=4)
r = real(z'3333', kind=4)
z1 = cmplx(b'10101',-4.0, kind=4)
z2 = cmplx(5.0, o'01245', kind=4)
-if (r2 /= 13107.0) stop '1'
-if (r /= 1.83668190E-41) stop '2'
-if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) stop '5'
+if (r2 /= 13107.0) call abort()
+if (r /= 1.83668190E-41) call abort()
+if (real(z1) /= 2.94272678E-44 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 9.48679060E-43) call abort()
end subroutine test4
subroutine test8
real(8),parameter :: r2c = real(int(z'FFFFFF3333', kind=8), kind=8)
-real(8),parameter :: rc = real(z'AAAAAAAAAAAAAAAAFFFFFFF3333', kind=8)
+real(8),parameter :: rc = real(z'AAAAAFFFFFFF3333', kind=8)
complex(8),parameter :: z1c = cmplx(b'11111011111111111111111111111111111111111111111111111111110101',-4.0, kind=8)
-complex(8),parameter :: z2c = cmplx(5.0, o'444444444442222222222233301245', kind=8)
+complex(8),parameter :: z2c = cmplx(5.0, o'442222222222233301245', kind=8)
real(8) :: r2 = real(int(z'FFFFFF3333',kind=8),kind=8)
-real(8) :: r = real(z'AAAAAAAAAAAAAAAAFFFFFFF3333', kind=8)
+real(8) :: r = real(z'AAAAAFFFFFFF3333', kind=8)
complex(8) :: z1 = cmplx(b'11111011111111111111111111111111111111111111111111111111110101',-4.0, kind=8)
-complex(8) :: z2 = cmplx(5.0, o'444444444442222222222233301245', kind=8)
+complex(8) :: z2 = cmplx(5.0, o'442222222222233301245', kind=8)
-if (r2c /= 1099511575347.0d0) stop '1'
-if (rc /= -3.72356884822177915d-103) stop '2'
-if (real(z1c) /= 3.05175781249999627d-5 .or. aimag(z1c) /= -4.0) stop '4'
-if (real(z2c) /= 5.0 .or. aimag(z2c) /= 3.98227593015308981d41) stop '5'
+if (r2c /= 1099511575347.0d0) call abort()
+if (rc /= -3.72356884822177915d-103) call abort()
+if (real(z1c) /= 3.05175781249999627d-5 .or. aimag(z1c) /= -4.0) call abort()
+if (real(z2c) /= 5.0 .or. aimag(z2c) /= 3.98227593015308981d41) call abort()
-if (r2 /= 1099511575347.0d0) stop '1'
-if (r /= -3.72356884822177915d-103) stop '2'
-if (real(z1) /= 3.05175781249999627d-5 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 3.98227593015308981d41) stop '5'
+if (r2 /= 1099511575347.0d0) call abort()
+if (r /= -3.72356884822177915d-103) call abort()
+if (real(z1) /= 3.05175781249999627d-5 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 3.98227593015308981d41) call abort()
r2 = real(int(z'FFFFFF3333',kind=8),kind=8)
-r = real(z'AAAAAAAAAAAAAAAAFFFFFFF3333', kind=8)
+r = real(z'AAAAAFFFFFFF3333', kind=8)
z1 = cmplx(b'11111011111111111111111111111111111111111111111111111111110101',-4.0, kind=8)
-z2 = cmplx(5.0, o'444444444442222222222233301245', kind=8)
+z2 = cmplx(5.0, o'442222222222233301245', kind=8)
-if (r2 /= 1099511575347.0d0) stop '1'
-if (r /= -3.72356884822177915d-103) stop '2'
-if (real(z1) /= 3.05175781249999627d-5 .or. aimag(z1) /= -4.0) stop '4'
-if (real(z2) /= 5.0 .or. aimag(z2) /= 3.98227593015308981d41) stop '5'
+if (r2 /= 1099511575347.0d0) call abort()
+if (r /= -3.72356884822177915d-103) call abort()
+if (real(z1) /= 3.05175781249999627d-5 .or. aimag(z1) /= -4.0) call abort()
+if (real(z2) /= 5.0 .or. aimag(z2) /= 3.98227593015308981d41) call abort()
end subroutine test8