[flang-commits] [flang] [Flang][Semantics] Fix crash on invalid function result declaration (PR #194648)
via flang-commits
flang-commits at lists.llvm.org
Tue Apr 28 20:53:28 PDT 2026
https://github.com/ShashwathiNavada updated https://github.com/llvm/llvm-project/pull/194648
>From 82e6af002c9a3aa58c8d527e62969573e44a4267 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Tue, 28 Apr 2026 09:41:39 -0500
Subject: [PATCH 1/5] Fix crash on invalid function result declaration; report
semantic error instead
---
flang/lib/Semantics/resolve-names.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index b6907cc792d76..409a793534399 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -496,6 +496,7 @@ class FuncResultStack {
// Result symbol
Symbol *resultSymbol{nullptr};
bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
+ bool completingType{false}; // re-entrancy guard for CompleteFunctionResultType
// Functions with previous implicitly-typed references get those types
// checked against their later definitions.
const DeclTypeSpec *previousImplicitType{nullptr};
@@ -2874,6 +2875,7 @@ void FuncResultStack::CompleteFunctionResultType() {
if (info && &info->scope == &scopeHandler_.currScope() &&
info->resultSymbol) {
if (info->parsedType) {
+ auto completingTypeScope{common::ScopedSet(info->completingType, true)};
scopeHandler_.messageHandler().set_currStmtSource(info->source);
if (const auto *type{
scopeHandler_.ProcessTypeSpec(*info->parsedType, true)}) {
@@ -2908,7 +2910,15 @@ void FuncResultStack::CompleteFunctionResultType() {
void FuncResultStack::CompleteTypeIfFunctionResult(Symbol &symbol) {
if (FuncInfo * info{Top()}) {
if (info->resultSymbol == &symbol) {
- CompleteFunctionResultType();
+ if (info->completingType) {
+ if (!scopeHandler_.context().HasError(symbol)) {
+ scopeHandler_.SayAlreadyDeclared(symbol.name(),
+ info->resultName ? info->resultName->source : symbol.name());
+ scopeHandler_.context().SetError(symbol);
+ }
+ } else {
+ CompleteFunctionResultType();
+ }
}
}
}
>From e4e1d09b267312701abf39ec3e90882abd0ab8c5 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Tue, 28 Apr 2026 09:58:52 -0500
Subject: [PATCH 2/5] Simple change
---
flang/lib/Semantics/resolve-names.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 409a793534399..17037f84e732e 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -496,7 +496,8 @@ class FuncResultStack {
// Result symbol
Symbol *resultSymbol{nullptr};
bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
- bool completingType{false}; // re-entrancy guard for CompleteFunctionResultType
+ bool completingType{
+ false}; // re-entrancy guard for CompleteFunctionResultType
// Functions with previous implicitly-typed references get those types
// checked against their later definitions.
const DeclTypeSpec *previousImplicitType{nullptr};
>From c47176e69e849a8e14ab33bef376478e98f3a5db Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Tue, 28 Apr 2026 15:02:04 -0500
Subject: [PATCH 3/5] Added lit test
---
flang/test/Semantics/resolve128.f90 | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
create mode 100644 flang/test/Semantics/resolve128.f90
diff --git a/flang/test/Semantics/resolve128.f90 b/flang/test/Semantics/resolve128.f90
new file mode 100644
index 0000000000000..64b8371b98729
--- /dev/null
+++ b/flang/test/Semantics/resolve128.f90
@@ -0,0 +1,25 @@
+!RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+!Test that a self-referencing character length specification in a function
+!prefix does not cause infinite recursion (crash) in the compiler.
+
+!CHECK: error: 'f1' is already declared in this scoping unit
+character(f1) function f1()
+ implicit integer(f)
+ f = 2
+end function
+
+!CHECK: error: Use of 'f2' as a procedure conflicts with its declaration
+character(f2(1)) function f2()
+ implicit integer(f)
+ f = 2
+end function
+
+!CHECK: error: 'f3' is already declared in this scoping unit
+integer(f3) function f3()
+ f3 = 2
+end function
+
+!CHECK: error: 'f4' is already declared in this scoping unit
+character*(f4) function bb() result(f4) ! ERROR
+f4 = "a"
+end
>From b9b2397820a7cf90ca2600196a3f7241d5490602 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Tue, 28 Apr 2026 22:51:02 -0500
Subject: [PATCH 4/5] Suggested changes
---
flang/lib/Semantics/resolve-names.cpp | 4 ++--
flang/test/Semantics/resolve128.f90 | 11 ++++++-----
2 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 17037f84e732e..387a99d5cf130 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -496,8 +496,8 @@ class FuncResultStack {
// Result symbol
Symbol *resultSymbol{nullptr};
bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
- bool completingType{
- false}; // re-entrancy guard for CompleteFunctionResultType
+ // re-entrancy guard for CompleteFunctionResultType
+ bool completingType{false};
// Functions with previous implicitly-typed references get those types
// checked against their later definitions.
const DeclTypeSpec *previousImplicitType{nullptr};
diff --git a/flang/test/Semantics/resolve128.f90 b/flang/test/Semantics/resolve128.f90
index 64b8371b98729..ac2055eb3ca65 100644
--- a/flang/test/Semantics/resolve128.f90
+++ b/flang/test/Semantics/resolve128.f90
@@ -1,25 +1,26 @@
-!RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+!RUN: %python %S/test_errors.py %s %flang_fc1
!Test that a self-referencing character length specification in a function
!prefix does not cause infinite recursion (crash) in the compiler.
-!CHECK: error: 'f1' is already declared in this scoping unit
+!ERROR: 'f1' is already declared in this scoping unit
character(f1) function f1()
implicit integer(f)
f = 2
end function
-!CHECK: error: Use of 'f2' as a procedure conflicts with its declaration
+!ERROR: 'f2' is not a callable procedure
+!ERROR: Use of 'f2' as a procedure conflicts with its declaration
character(f2(1)) function f2()
implicit integer(f)
f = 2
end function
-!CHECK: error: 'f3' is already declared in this scoping unit
+!ERROR: 'f3' is already declared in this scoping unit
integer(f3) function f3()
f3 = 2
end function
-!CHECK: error: 'f4' is already declared in this scoping unit
+!ERROR: 'f4' is already declared in this scoping unit
character*(f4) function bb() result(f4) ! ERROR
f4 = "a"
end
>From aa21031fe0e480c7db5329ea275ba90def3958f0 Mon Sep 17 00:00:00 2001
From: ShashwathiNavada <shashwathinavada at gmail.com>
Date: Tue, 28 Apr 2026 22:53:13 -0500
Subject: [PATCH 5/5] Simple
---
flang/lib/Semantics/resolve-names.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 387a99d5cf130..005d55aa2e9c9 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -497,7 +497,7 @@ class FuncResultStack {
Symbol *resultSymbol{nullptr};
bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
// re-entrancy guard for CompleteFunctionResultType
- bool completingType{false};
+ bool completingType{false};
// Functions with previous implicitly-typed references get those types
// checked against their later definitions.
const DeclTypeSpec *previousImplicitType{nullptr};
More information about the flang-commits
mailing list