Fortran: Fix ICE caused by missing error for untyped symbol [PR103258]

Message ID 77c049b9-998c-ad9a-d3ff-8593b581e1f6@codesourcery.com
State New
Headers
Series Fortran: Fix ICE caused by missing error for untyped symbol [PR103258] |

Commit Message

Sandra Loosemore Jan. 5, 2022, 3:21 a.m. UTC
  This patch fixes an ICE that appeared after I checked in my patch for 
PR101337 back in November, which made the resolve phase try harder to 
check all operands/arguments for errors instead of giving up after the 
first one, but it's actually a bug that existed before that and was only 
revealed by that earlier patch.

The problem is that the parse phase is doing early resolution to try to 
constant-fold a character length expression.  It's throwing away the 
error(s) if it fails, but in the test case for this issue it was leaving 
behind some state indicating that the error had already been diagnosed 
so it wasn't getting caught again during the "real" resolution phase either.

Every bit of code touched by this seems kind of hacky to me -- the 
different mechanisms for suppressing/ignoring errors, the magic bit in 
the symbol attributes, the part that tries to constant-fold an 
expression that might not actually be a constant, etc.  But, this is the 
least hacky fix I could come up with.  :-P  It fixes the test case from 
the issue and does not cause any regressions elsewhere in the gfortran 
testsuite.

OK to check in?

-Sandra
  

Comments

Paul Richard Thomas Jan. 5, 2022, 12:44 p.m. UTC | #1
Hi Sandra,

That's a good shout to query suppress_errors. The patch is OK by me.

Thanks

Paul


On Wed, 5 Jan 2022 at 03:21, Sandra Loosemore <sandra@codesourcery.com>
wrote:

> This patch fixes an ICE that appeared after I checked in my patch for
> PR101337 back in November, which made the resolve phase try harder to
> check all operands/arguments for errors instead of giving up after the
> first one, but it's actually a bug that existed before that and was only
> revealed by that earlier patch.
>
> The problem is that the parse phase is doing early resolution to try to
> constant-fold a character length expression.  It's throwing away the
> error(s) if it fails, but in the test case for this issue it was leaving
> behind some state indicating that the error had already been diagnosed
> so it wasn't getting caught again during the "real" resolution phase
> either.
>
> Every bit of code touched by this seems kind of hacky to me -- the
> different mechanisms for suppressing/ignoring errors, the magic bit in
> the symbol attributes, the part that tries to constant-fold an
> expression that might not actually be a constant, etc.  But, this is the
> least hacky fix I could come up with.  :-P  It fixes the test case from
> the issue and does not cause any regressions elsewhere in the gfortran
> testsuite.
>
> OK to check in?
>
> -Sandra
>
  

Patch

commit ea7deef7dad4239435374884713a187ae8faa4eb
Author: Sandra Loosemore <sandra@codesourcery.com>
Date:   Tue Jan 4 18:18:13 2022 -0800

    Fortran: Fix ICE caused by missing error for untyped symbol [PR103258]
    
    The bit on a symbol to mark that it had already been diagnosed as
    lacking a type was getting set even when the error was suppressed or
    discarded, specifically when doing early resolution on a character
    length expression to see if it can be constant-folded.  Explicitly
    suppress errors before doing that, then check whether they are
    suppressed before setting the bit.
    
    2022-01-04  Sandra Loosemore  <sandra@codesourcery.com>
    
    	PR fortran/103258
    
    	gcc/fortran/
    	* decl.c (gfc_match_char_spec): Suppress errors around call
    	to gfc_reduce_init_expr.
    	* error.c (gfc_query_suppress_errors): New.
    	* gfortran.h (gfc_query_suppress_errors): Declare.
    	* symbol.c (gfc_set_default_type): Check gfc_query_suppress_errors.
    
    	gcc/testsuite/
    	* gfortran.dg/pr103258.f90: New.

diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 4e510cc..c846923 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -3609,7 +3609,9 @@  done:
 	  gfc_current_ns = gfc_get_namespace (NULL, 0);
 
 	  e = gfc_copy_expr (len);
+	  gfc_push_suppress_errors ();
 	  gfc_reduce_init_expr (e);
+	  gfc_pop_suppress_errors ();
 	  if (e->expr_type == EXPR_CONSTANT)
 	    {
 	      gfc_replace_expr (len, e);
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index be2eb93..e95c083 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -83,6 +83,15 @@  gfc_pop_suppress_errors (void)
 }
 
 
+/* Query whether errors are suppressed.  */
+
+bool
+gfc_query_suppress_errors (void)
+{
+  return suppress_errors > 0;
+}
+
+
 /* Determine terminal width (for trimming source lines in output).  */
 
 static int
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index d01a9dc..3b791a4 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1083,6 +1083,7 @@  typedef struct
 
 void gfc_push_suppress_errors (void);
 void gfc_pop_suppress_errors (void);
+bool gfc_query_suppress_errors (void);
 
 
 /* Character length structures hold the expression that gives the
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 0385595..1a4b022 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -299,7 +299,7 @@  gfc_set_default_type (gfc_symbol *sym, int error_flag, gfc_namespace *ns)
 
   if (ts->type == BT_UNKNOWN)
     {
-      if (error_flag && !sym->attr.untyped)
+      if (error_flag && !sym->attr.untyped && !gfc_query_suppress_errors ())
 	{
 	  const char *guessed = lookup_symbol_fuzzy (sym->name, sym);
 	  if (guessed)
diff --git a/gcc/testsuite/gfortran.dg/pr103258.f90 b/gcc/testsuite/gfortran.dg/pr103258.f90
new file mode 100644
index 0000000..4521fcd
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103258.f90
@@ -0,0 +1,14 @@ 
+! { dg-do compile}
+! { dg-additional-options "-Wno-pedantic" }
+!
+! Test from PR103258.  This used to ICE due to incorrectly marking the
+! no-implicit-type error for n and m in the character length expression
+! as already diagnosed during early resolution, when in fact errors are
+! ignored in that parsing context.  We now expect the errors to be diagnosed
+! at the point of the first use of each symbol.
+
+subroutine s(n) ! { dg-error "Symbol 'n' .*has no IMPLICIT type" }
+implicit none
+character(n+m) :: c ! { dg-error "Symbol 'm' .*has no IMPLICIT type" }
+entry e(m)
+end