This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR fortran/58027,60993 -- BOZ in array constructor initialization expression


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]