From: Jerry DeLisle Date: Tue, 18 Nov 2025 02:55:03 +0000 (-0800) Subject: fortran: Enforce spec statement ordering [PR32365] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7db49bf4be2e5ec2d13b53963d33172c4a347b83;p=thirdparty%2Fgcc.git fortran: Enforce spec statement ordering [PR32365] PR fortran/32365 gcc/fortran/ChangeLog: * parse.cc (parse_executable): Reject declaration/OpenMP specification statements seen after executable code unconditionally, keeping the legacy DATA diagnostic as a warning. gcc/testsuite/ChangeLog: * gfortran.dg/common_22.f90: Update. * gfortran.dg/common_24.f: Update. * gfortran.dg/goacc/routine-1.f90: Update. * gfortran.dg/goacc/routine-2.f90: Update. * gfortran.dg/gomp/declare-variant-17.f90: Update. * gfortran.dg/gomp/interop-1.f90: Update. * gfortran.dg/gomp/order-2.f90: Update. * gfortran.dg/gomp/pr78026.f03: Update. * gfortran.dg/gomp/requires-4.f90: Update. * gfortran.dg/gomp/requires-6.f90: Update. * gfortran.dg/pr61669.f90: Update. * gfortran.dg/spec_statement_in_exec.f90: New test exercises data/common/namelist/OpenMP directives with -fopenmp. Signed-off-by: Christopher Albert --- diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index 19139ccb955..e4d65200f3a 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -7132,6 +7132,15 @@ loop: accept_statement (st); goto done; + /* Specification statements cannot appear after executable statements. */ + case_decl: + case_omp_decl: + gfc_error ("%s statement at %C cannot appear after executable statements", + gfc_ascii_statement (st)); + reject_statement (); + st = next_statement (); + continue; + default: break; } diff --git a/gcc/testsuite/gfortran.dg/common_22.f90 b/gcc/testsuite/gfortran.dg/common_22.f90 index e2254099d72..f92319b8076 100644 --- a/gcc/testsuite/gfortran.dg/common_22.f90 +++ b/gcc/testsuite/gfortran.dg/common_22.f90 @@ -7,18 +7,18 @@ ! Contributed by Bud Davis CALL RCCFL (NVE,IR,NU3,VE (1,1,1,I)) - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } ! the PR only contained the two above. ! success is no segfaults or infinite loops. ! let's check some combinations CALL ABC (INTG) - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } CALL DEF (NT1) - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } CALL GHI (NRESL) - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } - COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "Unexpected COMMON" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } + COMMON /CCFILE/ INTG,NT1,NT2,NT3,NVM,NVE,NFRLE,NRESF,NRESL !{ dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } END diff --git a/gcc/testsuite/gfortran.dg/common_24.f b/gcc/testsuite/gfortran.dg/common_24.f index ea37c2a8660..1f35a40158e 100644 --- a/gcc/testsuite/gfortran.dg/common_24.f +++ b/gcc/testsuite/gfortran.dg/common_24.f @@ -7,5 +7,5 @@ c Contributed by Ilya Enkovich COMMON /FMCOM / X(80 000 000) CALL T(XX(A)) - COMMON /FMCOM / XX(80 000 000) ! { dg-error "Unexpected COMMON" } + COMMON /FMCOM / XX(80 000 000) ! { dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } END diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-1.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-1.f90 index 67c5f11be6a..6378c31309f 100644 --- a/gcc/testsuite/gfortran.dg/goacc/routine-1.f90 +++ b/gcc/testsuite/gfortran.dg/goacc/routine-1.f90 @@ -4,7 +4,7 @@ integer :: a(n), i integer, external :: fact i = 1 - !$acc routine (fact) ! { dg-error "Unexpected \\\!\\\$ACC ROUTINE" } + !$acc routine (fact) ! { dg-error "\\!\\$ACC ROUTINE statement at \\(1\\) cannot appear after executable statements" } !$acc routine () ! { dg-error "Syntax error in \\\!\\\$ACC ROUTINE \\\( NAME \\\)" } !$acc parallel !$acc loop @@ -21,7 +21,7 @@ recursive function fact (x) result (res) integer, intent(in) :: x integer :: res res = 1 - !$acc routine ! { dg-error "Unexpected \\\!\\\$ACC ROUTINE" } + !$acc routine ! { dg-error "\\!\\$ACC ROUTINE statement at \\(1\\) cannot appear after executable statements" } if (x < 1) then res = 1 else @@ -32,6 +32,6 @@ subroutine incr (x) integer, intent(inout) :: x integer i i = 0 - !$acc routine ! { dg-error "Unexpected \\\!\\\$ACC ROUTINE" } + !$acc routine ! { dg-error "\\!\\$ACC ROUTINE statement at \\(1\\) cannot appear after executable statements" } x = x + 1 end subroutine incr diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-2.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-2.f90 index 3be33511581..28d3205f4a7 100644 --- a/gcc/testsuite/gfortran.dg/goacc/routine-2.f90 +++ b/gcc/testsuite/gfortran.dg/goacc/routine-2.f90 @@ -7,7 +7,7 @@ integer :: res integer i i = 0 - !$acc routine ! { dg-error "Unexpected \\\!\\\$ACC ROUTINE" } + !$acc routine ! { dg-error "\\!\\$ACC ROUTINE statement at \\(1\\) cannot appear after executable statements" } if (x < 1) then res = 1 else diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90 b/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90 index df57f9c089c..9010a2369a8 100644 --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-17.f90 @@ -7,11 +7,11 @@ program main continue - !$omp declare variant (base: variant) match (construct={parallel}) ! { dg-error "Unexpected \\\!\\\$OMP DECLARE VARIANT statement at .1." } + !$omp declare variant (base: variant) match (construct={parallel}) ! { dg-error "\\!\\$OMP DECLARE VARIANT statement at \\(1\\) cannot appear after executable statements" } contains subroutine base () continue - !$omp declare variant (variant) match (construct={parallel}) ! { dg-error "Unexpected \\\!\\\$OMP DECLARE VARIANT statement at .1." } + !$omp declare variant (variant) match (construct={parallel}) ! { dg-error "\\!\\$OMP DECLARE VARIANT statement at \\(1\\) cannot appear after executable statements" } end subroutine end program diff --git a/gcc/testsuite/gfortran.dg/gomp/interop-1.f90 b/gcc/testsuite/gfortran.dg/gomp/interop-1.f90 index eae0cb3ae16..9dd047006ff 100644 --- a/gcc/testsuite/gfortran.dg/gomp/interop-1.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/interop-1.f90 @@ -19,7 +19,7 @@ end module m subroutine sub1 ! { dg-error "Program unit at .1. has OpenMP device constructs/routines but does not set !.OMP REQUIRES REVERSE_OFFLOAD but other program units do" } !$omp interop - integer :: y ! { dg-error "Unexpected data declaration statement" } + integer :: y ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } end subroutine sub1 program main diff --git a/gcc/testsuite/gfortran.dg/gomp/order-2.f90 b/gcc/testsuite/gfortran.dg/gomp/order-2.f90 index 4ee3a82d518..d1fb310f90f 100644 --- a/gcc/testsuite/gfortran.dg/gomp/order-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/order-2.f90 @@ -11,14 +11,14 @@ contains implicit none integer, save :: t t = 1 - !$omp threadprivate (t1) ! { dg-error "Unexpected" } + !$omp threadprivate (t1) ! { dg-error "\\!\\$OMP THREADPRIVATE statement at \\(1\\) cannot appear after executable statements" } end subroutine f2 subroutine f3 use m implicit none integer :: j j = 1 - !$omp declare reduction (foo:real:omp_out = omp_out + omp_in) ! { dg-error "Unexpected" } + !$omp declare reduction (foo:real:omp_out = omp_out + omp_in) ! { dg-error "\\!\\$OMP DECLARE REDUCTION statement at \\(1\\) cannot appear after executable statements" } end subroutine f3 subroutine f4 use m @@ -26,12 +26,12 @@ contains !$omp declare target integer, save :: f4_1 f4_1 = 1 - !$omp declare target (f4_1) ! { dg-error "Unexpected" } - !$omp declare target ! { dg-error "Unexpected" } + !$omp declare target (f4_1) ! { dg-error "\\!\\$OMP DECLARE TARGET statement at \\(1\\) cannot appear after executable statements" } + !$omp declare target ! { dg-error "\\!\\$OMP DECLARE TARGET statement at \\(1\\) cannot appear after executable statements" } end subroutine f4 integer function f5 (a, b) integer :: a, b a = 1; b = 2 - !$omp declare simd (f5) notinbranch ! { dg-error "Unexpected" } + !$omp declare simd (f5) notinbranch ! { dg-error "\\!\\$OMP DECLARE SIMD statement at \\(1\\) cannot appear after executable statements" } end function f5 end subroutine f1 diff --git a/gcc/testsuite/gfortran.dg/gomp/pr78026.f03 b/gcc/testsuite/gfortran.dg/gomp/pr78026.f03 index 61f945886e6..6995abc8367 100644 --- a/gcc/testsuite/gfortran.dg/gomp/pr78026.f03 +++ b/gcc/testsuite/gfortran.dg/gomp/pr78026.f03 @@ -1,5 +1,5 @@ ! PR fortran/78026 select type (a) ! { dg-error "Selector shall be polymorphic in SELECT TYPE statement" } end select -!$omp declare simd(b) ! { dg-error "Unexpected !.OMP DECLARE SIMD statement" } +!$omp declare simd(b) ! { dg-error "\\!\\$OMP DECLARE SIMD statement at \\(1\\) cannot appear after executable statements" } end ! { dg-error "should refer to containing procedure" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-4.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-4.f90 index 9d936197f8f..fd4d0a8d7c3 100644 --- a/gcc/testsuite/gfortran.dg/gomp/requires-4.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/requires-4.f90 @@ -16,7 +16,7 @@ end subroutine foobar i = 5 ! < execution statement -!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "Unexpected ..OMP REQUIRES statement" } +!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "\\!\\$OMP REQUIRES statement at \\(1\\) cannot appear after executable statements" } end program main diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-6.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-6.f90 index b20c218dd6b..10a6e696091 100644 --- a/gcc/testsuite/gfortran.dg/gomp/requires-6.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/requires-6.f90 @@ -10,5 +10,5 @@ end subroutine foobar !$omp atomic i = i + 5 -!$omp requires atomic_default_mem_order(acq_rel) ! { dg-error "Unexpected !.OMP REQUIRES statement" } +!$omp requires atomic_default_mem_order(acq_rel) ! { dg-error "\\!\\$OMP REQUIRES statement at \\(1\\) cannot appear after executable statements" } end diff --git a/gcc/testsuite/gfortran.dg/pr61669.f90 b/gcc/testsuite/gfortran.dg/pr61669.f90 index 5bceafda762..ce38d13c979 100644 --- a/gcc/testsuite/gfortran.dg/pr61669.f90 +++ b/gcc/testsuite/gfortran.dg/pr61669.f90 @@ -1,7 +1,7 @@ ! { dg-do compile } write (*,"(a)") char(12) - CHARACTER*80 A /"A"/ ! { dg-error "Unexpected data declaration statement" } - REAL*4 B ! { dg-error "Unexpected data declaration statement" } + CHARACTER*80 A /"A"/ ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + REAL*4 B ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } write (*,"(a)") char(12) DATA B / 0.02 / ! { dg-warning "Obsolescent feature: DATA statement" } END diff --git a/gcc/testsuite/gfortran.dg/spec_statement_in_exec.f90 b/gcc/testsuite/gfortran.dg/spec_statement_in_exec.f90 new file mode 100644 index 00000000000..9134a1ec315 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/spec_statement_in_exec.f90 @@ -0,0 +1,26 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } +! Test improved error messages for specification statements in executable section +! PR fortran/32365 - Better error message for specification statement in executable section + +subroutine test_spec_in_exec + implicit none + integer :: i + + ! First executable statement + i = 1 + + ! Test key specification statement types + integer :: j ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + real :: x ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + complex :: z ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + logical :: flag ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + character(len=20) :: name ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + double precision :: d ! { dg-error "data declaration statement at \\(1\\) cannot appear after executable statements" } + common /myblock/ i ! { dg-error "COMMON statement at \\(1\\) cannot appear after executable statements" } + equivalence (i, i) ! { dg-error "EQUIVALENCE statement at \\(1\\) cannot appear after executable statements" } + namelist /nml/ i ! { dg-error "NAMELIST statement at \\(1\\) cannot appear after executable statements" } +!$omp threadprivate(i) ! { dg-error "THREADPRIVATE statement at \\(1\\) cannot appear after executable statements" } +!$omp declare target (i) ! { dg-error "DECLARE TARGET statement at \\(1\\) cannot appear after executable statements" } + +end subroutine test_spec_in_exec