[flang-commits] [flang] aee8491 - [Flang][Semantics] Fix crash on invalid function result declaration (#194648)

via flang-commits flang-commits at lists.llvm.org
Wed Apr 29 07:11:52 PDT 2026


Author: ShashwathiNavada
Date: 2026-04-29T09:11:46-05:00
New Revision: aee84917ea7960abfa87ba353e5ee39e3ef81850

URL: https://github.com/llvm/llvm-project/commit/aee84917ea7960abfa87ba353e5ee39e3ef81850
DIFF: https://github.com/llvm/llvm-project/commit/aee84917ea7960abfa87ba353e5ee39e3ef81850.diff

LOG: [Flang][Semantics] Fix crash on invalid function result declaration (#194648)

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

When the function result symbol is encountered while the compiler is
already completing the function result type, flang could recursively
re-enter _CompleteFunctionResultType()_ and crash on invalid code.

Instead of crashing on conflicting declarations, flang now reports an
“already declared” error and stops further recursion.

Added: 
    flang/test/Semantics/resolve128.f90

Modified: 
    flang/lib/Semantics/resolve-names.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index e49ae8e53900c..9ed2e73c155b0 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -498,6 +498,8 @@ class FuncResultStack {
     // Result symbol
     Symbol *resultSymbol{nullptr};
     bool inFunctionStmt{false}; // true between Pre/Post of FunctionStmt
+    // 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};
@@ -2985,6 +2987,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)}) {
@@ -3019,7 +3022,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();
+      }
     }
   }
 }

diff  --git a/flang/test/Semantics/resolve128.f90 b/flang/test/Semantics/resolve128.f90
new file mode 100644
index 0000000000000..3af92d03d164c
--- /dev/null
+++ b/flang/test/Semantics/resolve128.f90
@@ -0,0 +1,26 @@
+!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.
+
+!ERROR: 'f1' is already declared in this scoping unit
+character(f1) function f1()
+  implicit integer(f)
+  f = 2
+end function
+
+!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
+
+!ERROR: 'f3' is already declared in this scoping unit
+integer(f3) function f3()
+  f3 = 2
+end function
+
+!ERROR: 'f4' is already declared in this scoping unit
+character*(f4) function bb() result(f4)
+f4 = "a"
+end


        


More information about the flang-commits mailing list