[flang-commits] [flang] [flang] Catch doubly-nested internal subprograms (PR #175992)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed Jan 14 09:12:39 PST 2026


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/175992

The check for double-nested internal subprograms is missing cases nested in main programs.

Fixes https://github.com/llvm/llvm-project/issues/150820.

>From a7f7f8831c67e53aa57153b4e775dc68624d5e15 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Wed, 14 Jan 2026 09:10:04 -0800
Subject: [PATCH] [flang] Catch doubly-nested internal subprograms

The check for double-nested internal subprograms is missing
cases nested in main programs.

Fixes https://github.com/llvm/llvm-project/issues/150820.
---
 flang/lib/Semantics/check-purity.cpp     |  6 +++++-
 flang/lib/Semantics/check-purity.h       |  2 ++
 flang/test/Semantics/bug150820.f90       | 20 ++++++++++++++++++
 flang/test/Semantics/misc-intrinsics.f90 | 27 +++++++++++++-----------
 flang/test/Semantics/symbol03.f90        |  7 ------
 5 files changed, 42 insertions(+), 20 deletions(-)
 create mode 100644 flang/test/Semantics/bug150820.f90

diff --git a/flang/lib/Semantics/check-purity.cpp b/flang/lib/Semantics/check-purity.cpp
index 1046f363e9485..b327282f390e5 100644
--- a/flang/lib/Semantics/check-purity.cpp
+++ b/flang/lib/Semantics/check-purity.cpp
@@ -17,6 +17,7 @@ void PurityChecker::Enter(const parser::ExecutableConstruct &exec) {
         "An image control statement may not appear in a pure subprogram"_err_en_US);
   }
 }
+
 void PurityChecker::Enter(const parser::SubroutineSubprogram &subr) {
   const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(subr.t)};
   Entered(
@@ -31,7 +32,10 @@ void PurityChecker::Enter(const parser::FunctionSubprogram &func) {
       stmt.source, std::get<std::list<parser::PrefixSpec>>(stmt.statement.t));
 }
 
-void PurityChecker::Leave(const parser::FunctionSubprogram &func) { Left(); }
+void PurityChecker::Leave(const parser::FunctionSubprogram &) { Left(); }
+
+void PurityChecker::Enter(const parser::MainProgram &) { ++depth_; }
+void PurityChecker::Leave(const parser::MainProgram &) { --depth_; }
 
 bool PurityChecker::InPureSubprogram() const {
   return pureDepth_ >= 0 && depth_ >= pureDepth_;
diff --git a/flang/lib/Semantics/check-purity.h b/flang/lib/Semantics/check-purity.h
index a6551162325f9..4e01bdc00e0bc 100644
--- a/flang/lib/Semantics/check-purity.h
+++ b/flang/lib/Semantics/check-purity.h
@@ -23,6 +23,8 @@ class PurityChecker : public virtual BaseChecker {
   void Enter(const parser::ExecutableConstruct &);
   void Enter(const parser::SubroutineSubprogram &);
   void Leave(const parser::SubroutineSubprogram &);
+  void Enter(const parser::MainProgram &);
+  void Leave(const parser::MainProgram &);
   void Enter(const parser::FunctionSubprogram &);
   void Leave(const parser::FunctionSubprogram &);
 
diff --git a/flang/test/Semantics/bug150820.f90 b/flang/test/Semantics/bug150820.f90
new file mode 100644
index 0000000000000..5a369c47934ca
--- /dev/null
+++ b/flang/test/Semantics/bug150820.f90
@@ -0,0 +1,20 @@
+!RUN: %python %S/test_errors.py %s %flang_fc1
+subroutine a
+ contains
+  subroutine b
+   contains
+    !ERROR: An internal subprogram may not contain an internal subprogram
+    subroutine c
+    end
+  end
+end
+
+program p
+ contains
+  subroutine b
+   contains
+    !ERROR: An internal subprogram may not contain an internal subprogram
+    subroutine c
+    end
+  end
+end
diff --git a/flang/test/Semantics/misc-intrinsics.f90 b/flang/test/Semantics/misc-intrinsics.f90
index a7895f7b7f16f..517a8b247ad28 100644
--- a/flang/test/Semantics/misc-intrinsics.f90
+++ b/flang/test/Semantics/misc-intrinsics.f90
@@ -105,16 +105,19 @@ subroutine test(arg, assumedRank, poly)
       print *, lbound(assumedRank, dim=2)
       print *, ubound(assumedRank, dim=2)
     end select
-   contains
-    subroutine inner
-      !ERROR: A dim= argument is required for 'size' when the array is assumed-size
-      print *, size(arg)
-      print *, size(arg, dim=1) ! ok
-      !ERROR: A dim= argument is required for 'ubound' when the array is assumed-size
-      print *, ubound(arg)
-      print *, ubound(arg, dim=1) ! ok
-      !ERROR: The 'source=' argument to the intrinsic function 'shape' may not be assumed-size
-      print *, shape(arg)
-    end
-  end subroutine
+  end
+end
+subroutine test2(arg)
+  real, dimension(5, *) :: arg
+ contains
+  subroutine inner
+    !ERROR: A dim= argument is required for 'size' when the array is assumed-size
+    print *, size(arg)
+    print *, size(arg, dim=1) ! ok
+    !ERROR: A dim= argument is required for 'ubound' when the array is assumed-size
+    print *, ubound(arg)
+    print *, ubound(arg, dim=1) ! ok
+    !ERROR: The 'source=' argument to the intrinsic function 'shape' may not be assumed-size
+    print *, shape(arg)
+  end
 end
diff --git a/flang/test/Semantics/symbol03.f90 b/flang/test/Semantics/symbol03.f90
index 62472495d9736..4651669020473 100644
--- a/flang/test/Semantics/symbol03.f90
+++ b/flang/test/Semantics/symbol03.f90
@@ -13,13 +13,6 @@ subroutine s
   !DEF: /MAIN/s/y (Implicit) ObjectEntity REAL(4)
   !DEF: /MAIN/s/x HostAssoc INTEGER(4)
   y = x
- contains
-  !DEF: /MAIN/s/s2 (Subroutine) Subprogram
-  subroutine s2
-   !DEF: /MAIN/s/s2/z (Implicit) ObjectEntity REAL(4)
-   !DEF: /MAIN/s/s2/x HostAssoc INTEGER(4)
-   z = x
-  end subroutine
  end subroutine
 end program
 



More information about the flang-commits mailing list