From c55cb36a6ad00996b5efb33c0c5357fc5fa9919c Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Mon, 6 May 2024 20:57:29 +0200 Subject: [PATCH] Fortran: improve attribute conflict checking [PR93635] gcc/fortran/ChangeLog: PR fortran/93635 * symbol.cc (gfc_check_conflict): Move some attribute conflict checks that depend on the selected version of the Fortran standard so that error reporting gets more consistent. gcc/testsuite/ChangeLog: PR fortran/93635 * gfortran.dg/pr93635.f90: New test. --- gcc/fortran/symbol.cc | 30 ++++++++++++--------------- gcc/testsuite/gfortran.dg/pr93635.f90 | 19 +++++++++++++++++ 2 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/pr93635.f90 diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc index 8f7deac1d1e..ed17291c53e 100644 --- a/gcc/fortran/symbol.cc +++ b/gcc/fortran/symbol.cc @@ -459,22 +459,6 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where) if (where == NULL) where = &gfc_current_locus; - if (attr->pointer && attr->intent != INTENT_UNKNOWN) - { - a1 = pointer; - a2 = intent; - standard = GFC_STD_F2003; - goto conflict_std; - } - - if (attr->in_namelist && (attr->allocatable || attr->pointer)) - { - a1 = in_namelist; - a2 = attr->allocatable ? allocatable : pointer; - standard = GFC_STD_F2003; - goto conflict_std; - } - /* Check for attributes not allowed in a BLOCK DATA. */ if (gfc_current_state () == COMP_BLOCK_DATA) { @@ -579,10 +563,12 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where) return false; conf (allocatable, pointer); + + /* Moving these checks past the function/subroutine conflict check may + cause trouble with minor variations of testcase pr87907.f90. */ conf_std (allocatable, dummy, GFC_STD_F2003); conf_std (allocatable, function, GFC_STD_F2003); conf_std (allocatable, result, GFC_STD_F2003); - conf_std (elemental, recursive, GFC_STD_F2018); conf (in_common, dummy); conf (in_common, allocatable); @@ -911,6 +897,16 @@ gfc_check_conflict (symbol_attribute *attr, const char *name, locus *where) break; } + /* Conflict checks depending on the selected version of the Fortran + standard are preferably applied after standard-independent ones, so + that one gets more consistent error reporting and recovery. */ + if (attr->pointer && attr->intent != INTENT_UNKNOWN) + conf_std (pointer, intent, GFC_STD_F2003); + + conf_std (in_namelist, allocatable, GFC_STD_F2003); + conf_std (in_namelist, pointer, GFC_STD_F2003); + conf_std (elemental, recursive, GFC_STD_F2018); + return true; conflict: diff --git a/gcc/testsuite/gfortran.dg/pr93635.f90 b/gcc/testsuite/gfortran.dg/pr93635.f90 new file mode 100644 index 00000000000..4ef33fecf2b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr93635.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! PR fortran/93635 +! +! Test that some attribute conflicts are properly diagnosed + +program p + implicit none + character(len=:),allocatable :: r,s + namelist /args/ r,s + equivalence(r,s) ! { dg-error "EQUIVALENCE attribute conflicts with ALLOCATABLE" } + allocate(character(len=1024) :: r) +end + +subroutine sub (p, q) + implicit none + real, pointer, intent(inout) :: p(:), q(:) + namelist /nml/ p,q + equivalence(p,q) ! { dg-error "EQUIVALENCE attribute conflicts with DUMMY" } +end -- 2.35.3