This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
[PATCH] PR fortran/58027,60993 -- BOZ in array constructor initialization expression
- From: Steve Kargl <sgk at troutmask dot apl dot washington dot edu>
- To: fortran at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Date: Sun, 15 Nov 2015 18:22:41 -0800
- Subject: [PATCH] PR fortran/58027,60993 -- BOZ in array constructor initialization expression
- Authentication-results: sourceware.org; auth=none
First, thanks to Dominiq for prodding me into looking at PR 58027.
This was a fun ICE to track down!
Most users have no idea what the Fortran standard requires for
the parsing of a BOZ. Consider the line of code
integer, parameter :: i(1) = (/ z'ff800000' /)
The naive user wants to assign a BOZ interpreted as a 32-bit entity
to i(1) in an array constructor. Ignoring the fact that a BOZ
can't be used here, the BOZ is converted to an integer with the
widest decimal exponential range. On all(?) targets this is at
least a 64-bit integer (known as INTEGER(8)). To do the assignment
gfortan inserts a __convert_i8_i4(), but it does so after any
checking for an initialization expression. So, when gfortran
finally gets around to calling gfc_conv_array_initializer() to
translates into tree-ssa form, gfc_conv_array_initializer() is not
expecting a function and dies with an ICE.
The fix is affected by calling gfc_check_init_expr() under
appropriate conditions. Because the __convert_* functions
are sort of psuedo-intrinsic procedures, a check for an intrinsic
procedure needs to be circumvented.
Anyway, the patch has been built and tested on i386-*-freebsd
and x86_64-*-freebsd. OK to commit?
2015-11-15 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/58027
PR fortran/60993
* expr.c (gfc_check_init_expr): Prevent a redundant check when a
__convert_* function was inserted into an array constructor.
(gfc_check_assign_symbol): Check for an initialization expression
when a __convert_* was inserted.
2015-11-15 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/58027
PR fortran/60993
* gfortran.dg/pr58027.f90: New test.
--
Steve
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (revision 230397)
+++ gcc/fortran/expr.c (working copy)
@@ -2471,7 +2471,8 @@ gfc_check_init_expr (gfc_expr *e)
t = false;
{
- gfc_intrinsic_sym* isym;
+ bool conversion;
+ gfc_intrinsic_sym* isym = NULL;
gfc_symbol* sym = e->symtree->n.sym;
/* Simplify here the intrinsics from the IEEE_ARITHMETIC and
@@ -2490,8 +2491,14 @@ gfc_check_init_expr (gfc_expr *e)
}
}
- if (!gfc_is_intrinsic (sym, 0, e->where)
- || (m = gfc_intrinsic_func_interface (e, 0)) != MATCH_YES)
+ /* If a conversion function, e.g., __convert_i8_i4, was inserted
+ into an array constructor, we need to skip the error check here.
+ Conversion errors are caught below in scalarize_intrinsic_call. */
+ conversion = e->value.function.isym
+ && (e->value.function.isym->conversion == 1);
+
+ if (!conversion && (!gfc_is_intrinsic (sym, 0, e->where)
+ || (m = gfc_intrinsic_func_interface (e, 0)) != MATCH_YES))
{
gfc_error ("Function %qs in initialization expression at %L "
"must be an intrinsic function",
@@ -2518,7 +2525,7 @@ gfc_check_init_expr (gfc_expr *e)
array argument. */
isym = gfc_find_function (e->symtree->n.sym->name);
if (isym && isym->elemental
- && (t = scalarize_intrinsic_call(e)))
+ && (t = scalarize_intrinsic_call (e)))
break;
}
@@ -3844,7 +3851,17 @@ gfc_check_assign_symbol (gfc_symbol *sym
if (pointer || proc_pointer)
r = gfc_check_pointer_assign (&lvalue, rvalue);
else
- r = gfc_check_assign (&lvalue, rvalue, 1);
+ {
+ /* If a conversion function, e.g., __convert_i8_i4, was inserted
+ into an array constructor, we should check if it can be reduced
+ as an initialization expression. */
+ if (rvalue->expr_type == EXPR_FUNCTION
+ && rvalue->value.function.isym
+ && (rvalue->value.function.isym->conversion == 1))
+ gfc_check_init_expr (rvalue);
+
+ r = gfc_check_assign (&lvalue, rvalue, 1);
+ }
free (lvalue.symtree);
free (lvalue.ref);
Index: gcc/testsuite/gfortran.dg/pr58027.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr58027.f90 (nonexistent)
+++ gcc/testsuite/gfortran.dg/pr58027.f90 (working copy)
@@ -0,0 +1,5 @@
+! { dg-do compile }
+! PR fortran/58027
+integer, parameter :: i(1)=(/z'ff800000'/) ! { dg-error "overflow converting" }
+print *, isclass
+end