https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93635
--- Comment #2 from Steve Kargl <sgk at troutmask dot apl.washington.edu> --- On Sun, Feb 09, 2020 at 06:39:31PM +0000, kargl at gcc dot gnu.org wrote: > > Fortuantely, I > use neither namelist nor equivalence, so have no skin in the > game. Someone else can complete the fix. > Here's a patch that fixes the issue and cures the ICE in the old testcase. Whoever commit patch needs to convert the example code here into a testcase. 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. */ @@ -4039,6 +4066,31 @@ gfc_free_namespace (gfc_namespace *ns) ns->refs--; if (ns->refs > 0) return; + + /* If an error occurred while parsing a submodule, the namespace is freed. + However, gfortran reaches a ref count of -1. Note, gfc_state_stack does + not indicate that gfortran was parsing a submodule. */ + if (ns->refs == -1) + { + gcc_assert (ns->sym_root == NULL); + gcc_assert (ns->uop_root == NULL); + gcc_assert (ns->common_root == NULL); + gcc_assert (ns->omp_udr_root == NULL); + gcc_assert (ns->tb_sym_root == NULL); + gcc_assert (ns->tb_uop_root == NULL); + gcc_assert (ns->finalizers == NULL); + gcc_assert (ns->omp_declare_simd == NULL); + gcc_assert (ns->cl_list == NULL); + gcc_assert (ns->st_labels == NULL); + gcc_assert (ns->entries == NULL); + gcc_assert (ns->equiv == NULL); + gcc_assert (ns->equiv_lists == NULL); + gcc_assert (ns->use_stmts == NULL); + gcc_assert (ns->data == NULL); + gcc_assert (ns->contained == NULL); + free (ns); + return; + } gcc_assert (ns->refs == 0); Index: gcc/testsuite/gfortran.dg/pr87907.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr87907.f90 (revision 280157) +++ gcc/testsuite/gfortran.dg/pr87907.f90 (working copy) @@ -12,12 +12,6 @@ end submodule(m) m2 contains - subroutine g(x) ! { dg-error "mismatch in argument" } + subroutine g(x) ! { dg-error " attribute conflicts with" } end -end - -program p - use m ! { dg-error "has a type" } - integer :: x = 3 - call g(x) ! { dg-error "which is not consistent with" } end