https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93635

kargl at gcc dot gnu.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2020-02-09
                 CC|                            |kargl at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #1 from kargl at gcc dot gnu.org ---
The problem is in symbol.c (gfc_check_conflict).  This check

   if (attr->in_namelist && (attr->allocatable || attr->pointer))
     {
       a1 = in_namelist;
       a2 = attr->allocatable ? allocatable : pointer;
       standard = GFC_STD_F2003;
       goto conflict_std;
     }

jumps to conflict_std, where an error may or may not be issued.
In either case, gfc_check_conflict returns without any futher
checking of other attributes.  There are four cases with the 
conflict_std jump.  This patch removes these jumps.  It causes
a regression with pr87907.f90 where a correct error is emitted,
which is then followed by bunch of run-on errors.  Removing the
of pr87907.f90 that leads to the run-on errors, then results in
a correct error message followed by an ICE.  Likely, the bug 
fix for pr87907.f90 needs to be re-evaluated.  Fortuantely, I 
use neither namelist nor equivalence, so have no skin in the 
game.  Someone else can complete the fix.

Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c        (revision 280157)
+++ gcc/fortran/symbol.c        (working copy)
@@ -394,18 +395,35 @@ gfc_check_function_type (gfc_namespace *ns)

 /******************** Symbol attribute stuff *********************/

+/* Older standard produced conflicts for some attributes that are now
+   allowed in newer standards.  Check for the conflict and issue an
+   error depending on the standard in play.  */
+
+static bool
+conflict_std (int standard, const char *a1, const char *a2, const char *name,
+             locus *where)
+{
+  if (name == NULL)
+    {
+      return gfc_notify_std (standard, "%s attribute conflicts "
+                             "with %s attribute at %L", a1, a2,
+                             where);
+    }
+  else
+    {
+      return gfc_notify_std (standard, "%s attribute conflicts "
+                            "with %s attribute in %qs at %L",
+                             a1, a2, name, where);
+    }
+}
+
+
+
 /* This is a generic conflict-checker.  We do this to avoid having a
    single conflict in two places.  */

 #define conf(a, b) if (attr->a && attr->b) { a1 = a; a2 = b; goto conflict; }
 #define conf2(a) if (attr->a) { a2 = a; goto conflict; }
-#define conf_std(a, b, std) if (attr->a && attr->b)\
-                              {\
-                                a1 = a;\
-                                a2 = b;\
-                                standard = std;\
-                                goto conflict_std;\
-                              }

 bool
 gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where)
@@ -438,7 +456,7 @@ gfc_check_conflict (symbol_attribute *attr, const char
                                                "OACC DECLARE DEVICE_RESIDENT";

   const char *a1, *a2;
-  int standard;
+  bool standard;

   if (attr->artificial)
     return true;
@@ -450,16 +468,18 @@ gfc_check_conflict (symbol_attribute *attr, const char
     {
       a1 = pointer;
       a2 = intent;
-      standard = GFC_STD_F2003;
-      goto conflict_std;
+      standard = conflict_std (GFC_STD_F2003, a1, a2, name, where);
+      if (!standard)
+         return standard;
     }

   if (attr->in_namelist && (attr->allocatable || attr->pointer))
     {
       a1 = in_namelist;
       a2 = attr->allocatable ? allocatable : pointer;
-      standard = GFC_STD_F2003;
-      goto conflict_std;
+      standard = conflict_std (GFC_STD_F2003, a1, a2, name, where);
+      if (!standard)
+         return standard;
     }

   /* Check for attributes not allowed in a BLOCK DATA.  */
@@ -566,9 +586,31 @@ gfc_check_conflict (symbol_attribute *attr, const char
     return false;

   conf (allocatable, pointer);
-  conf_std (allocatable, dummy, GFC_STD_F2003);
-  conf_std (allocatable, function, GFC_STD_F2003);
-  conf_std (allocatable, result, GFC_STD_F2003);
+  if (attr->allocatable && attr->dummy)
+    {
+      a1 = allocatable;
+      a2 = dummy;
+      standard = conflict_std (GFC_STD_F2003, a1, a2, name, where);
+      if (!standard)
+         return standard;
+    }
+  if (attr->allocatable && attr->function)
+    {
+      a1 = allocatable;
+      a2 = function;
+      standard = conflict_std (GFC_STD_F2003, a1, a2, name, where);
+      if (!standard)
+         return standard;
+    }
+  if (attr->allocatable && attr->result)
+    {
+      a1 = allocatable;
+      a2 = result;
+      standard = conflict_std (GFC_STD_F2003, a1, a2, name, where);
+      if (!standard)
+         return standard;
+    }
+
   conf (elemental, recursive);

   conf (in_common, dummy);
@@ -908,25 +950,10 @@ conflict:
               a1, a2, name, where);

   return false;
-
-conflict_std:
-  if (name == NULL)
-    {
-      return gfc_notify_std (standard, "%s attribute conflicts "
-                             "with %s attribute at %L", a1, a2,
-                             where);
-    }
-  else
-    {
-      return gfc_notify_std (standard, "%s attribute conflicts "
-                            "with %s attribute in %qs at %L",
-                             a1, a2, name, where);
-    }
 }

 #undef conf
 #undef conf2
-#undef conf_std


 /* Mark a symbol as referenced.  */

Reply via email to