The problem here is that one gets two symbols - one inside the block and one outside and they do not really agree whether one has a function or a variable – which later gives an ICE. As sym->module was "(intrinsic)" and FL_VARIABLE, one was running into an assert.

The problem is that when resolving the expression with "max", gfortran detects that it got an intrinsic function and resolves the expression/function call (in this case to a constant). However, the information that "max" was regarded as intrinsic procedure never ends up in the symbol itself, only in the expression.

My first idea was to call gfc_resolve_intrinsic, which does a lot of nice things like setting the attributes, warning that the type is ignored with intrinsic procedures (-Wsurprsing, only) etc. However, that gives a bunch of ICE. Even a more Spartan attr setting had similar issues – hence, I moved it below the simplification, in the hope it would work there. Well, gfc_resolve_intrinsic still gave tons of errors and ICEs, but what I now have works. (I think it also works w/o the FL_UNKNOWN condition, but, in any case, I am not sure which variant is better)

The settings I use with this patch seem to work and I have the hope that it covers all valid/invalid code correctly (fingers crossed).

Build and regtested on x86-64-gnu-linux.
OK for the trunk?

Tobias

PS: I added 'sym' as after simplifcation, expr->symtree->n.sym might no longer exist; getting rid of 'name' was only a cleanup as sym->name is a tad clearer and avoids another variable.

PPS: I ended up fixing this PR as Martin CC'ed me – after finding that my commit caused the ICE; well, that one was in 2014 (!), somewhat unrelated, and before that commit the code was rejected… With a lot of good (evil?) will, one can still call it a regression ;-)

	gcc/fortran/
	PR fortran/92754
	* intrinsic.c (gfc_intrinsic_func_interface): Set
	sym's flavor, intrinsic and function attribute if
	unset.

	gcc/testsuite/
	PR fortran/92754
	gfortran.dg/intrinsic_9.f90: New.

diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 572967f5d4e..76b53bb7117 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4839,9 +4839,9 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym* isym,
 match
 gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 {
+  gfc_symbol *sym;
   gfc_intrinsic_sym *isym, *specific;
   gfc_actual_arglist *actual;
-  const char *name;
   int flag;
 
   if (expr->value.function.isym != NULL)
@@ -4857,15 +4857,15 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
       flag |= (actual->expr->ts.type != BT_INTEGER
 	       && actual->expr->ts.type != BT_CHARACTER);
 
-  name = expr->symtree->n.sym->name;
+  sym = expr->symtree->n.sym;
 
-  if (expr->symtree->n.sym->intmod_sym_id)
+  if (sym->intmod_sym_id)
     {
-      gfc_isym_id id = gfc_isym_id_by_intmod_sym (expr->symtree->n.sym);
+      gfc_isym_id id = gfc_isym_id_by_intmod_sym (sym);
       isym = specific = gfc_intrinsic_function_by_id (id);
     }
   else
-    isym = specific = gfc_find_function (name);
+    isym = specific = gfc_find_function (sym->name);
 
   if (isym == NULL)
     {
@@ -4879,7 +4879,7 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
        || isym->id == GFC_ISYM_SNGL || isym->id == GFC_ISYM_DFLOAT)
       && gfc_init_expr_flag
       && !gfc_notify_std (GFC_STD_F2003, "Function %qs as initialization "
-			  "expression at %L", name, &expr->where))
+			  "expression at %L", sym->name, &expr->where))
     {
       if (!error_flag)
 	gfc_pop_suppress_errors ();
@@ -4898,7 +4898,7 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 	  && id != GFC_ISYM_TRANSFER && id != GFC_ISYM_TRIM
 	  && !gfc_notify_std (GFC_STD_F2003, "Transformational function %qs "
 			      "at %L is invalid in an initialization "
-			      "expression", name, &expr->where))
+			      "expression", sym->name, &expr->where))
 	{
 	  if (!error_flag)
 	    gfc_pop_suppress_errors ();
@@ -4956,9 +4956,6 @@ gfc_intrinsic_func_interface (gfc_expr *expr, int error_flag)
 
 got_specific:
   expr->value.function.isym = specific;
-  if (!expr->symtree->n.sym->module)
-    gfc_intrinsic_symbol (expr->symtree->n.sym);
-
   if (!error_flag)
     gfc_pop_suppress_errors ();
 
@@ -4980,6 +4977,16 @@ got_specific:
 			  "character arguments at %L", &expr->where))
     return MATCH_ERROR;
 
+  if (sym->attr.flavor == FL_UNKNOWN)
+    {
+      sym->attr.function = 1;
+      sym->attr.intrinsic = 1;
+      sym->attr.flavor = FL_PROCEDURE;
+    }
+
+  if (!sym->module)
+    gfc_intrinsic_symbol (sym);
+
   return MATCH_YES;
 }
 
diff --git a/gcc/testsuite/gfortran.dg/intrinsic_9.f90 b/gcc/testsuite/gfortran.dg/intrinsic_9.f90
new file mode 100644
index 00000000000..43959ad85df
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/intrinsic_9.f90
@@ -0,0 +1,15 @@
+! { dg-do run }
+!
+! PR fortran/92754
+!
+! Contributed by G. Steinmetz
+!
+
+program p
+   integer :: max
+   block
+      character :: x = max('a','b')
+      !print *, x
+      if (x /= 'b') stop 1
+   end block
+end

Reply via email to