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 <ka...@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 <ka...@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