https://gcc.gnu.org/g:7db49bf4be2e5ec2d13b53963d33172c4a347b83

commit r16-5393-g7db49bf4be2e5ec2d13b53963d33172c4a347b83
Author: Jerry DeLisle <[email protected]>
Date:   Mon Nov 17 18:55:03 2025 -0800

    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 <[email protected]>

Diff:
---
 gcc/fortran/parse.cc                               |  9 ++++++++
 gcc/testsuite/gfortran.dg/common_22.f90            | 16 ++++++-------
 gcc/testsuite/gfortran.dg/common_24.f              |  2 +-
 gcc/testsuite/gfortran.dg/goacc/routine-1.f90      |  6 ++---
 gcc/testsuite/gfortran.dg/goacc/routine-2.f90      |  2 +-
 .../gfortran.dg/gomp/declare-variant-17.f90        |  4 ++--
 gcc/testsuite/gfortran.dg/gomp/interop-1.f90       |  2 +-
 gcc/testsuite/gfortran.dg/gomp/order-2.f90         | 10 ++++-----
 gcc/testsuite/gfortran.dg/gomp/pr78026.f03         |  2 +-
 gcc/testsuite/gfortran.dg/gomp/requires-4.f90      |  2 +-
 gcc/testsuite/gfortran.dg/gomp/requires-6.f90      |  2 +-
 gcc/testsuite/gfortran.dg/pr61669.f90              |  4 ++--
 .../gfortran.dg/spec_statement_in_exec.f90         | 26 ++++++++++++++++++++++
 13 files changed, 61 insertions(+), 26 deletions(-)

diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 19139ccb9559..e4d65200f3ab 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 e2254099d72f..f92319b80767 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  <[email protected]>
 
       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 ea37c2a8660e..1f35a40158e8 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 <[email protected]>
 
       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 67c5f11be6a5..6378c31309fb 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 3be335115816..28d3205f4a77 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 df57f9c089cf..9010a2369a88 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 eae0cb3ae16a..9dd047006ffb 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 4ee3a82d5180..d1fb310f90f5 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 61f945886e62..6995abc83672 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 9d936197f8f8..fd4d0a8d7c30 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 b20c218dd6bc..10a6e6960910 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 5bceafda7621..ce38d13c979c 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 000000000000..9134a1ec3151
--- /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

Reply via email to