[flang-commits] [flang] [flang] Fix crash on self-referencing character length in function prefix (PR #194678)

via flang-commits flang-commits at lists.llvm.org
Tue Apr 28 10:03:39 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics

Author: Caroline Newcombe (cenewcombe)

<details>
<summary>Changes</summary>

**Bug Description:** `character*(a) function a()` causes a stack overflow in semantics. The function name in the character-length expression triggers `ConvertToObjectEntity`, which re-enters `CompleteFunctionResultType` before `ProcessTypeSpec` returns. Since `parsedType` is only cleared after `ProcessTypeSpec` returned, the re-entrant call walks the type-spec again, recursing infinitely.

**Fix:** clear `parsedType` before calling `ProcessTypeSpec` so re-entrant calls are no-ops.

**Testing:** A new semantics LIT test has been added with three cases. The first test case (`character(f1) function f1()`) is the bug reproducer — a simple name reference to the function in its own character-length expression, which caused infinite recursion. The second test case (`character(f2(1)) function f2()`) uses the function-call form of the self-reference, which already produced correct diagnostics before the fix. The third test case (`integer(f3) function f3()`) uses a self-referencing kind parameter, which was also found to crash without the fix.

---
Full diff: https://github.com/llvm/llvm-project/pull/194678.diff


2 Files Affected:

- (modified) flang/lib/Semantics/resolve-names.cpp (+5-2) 
- (added) flang/test/Semantics/resolve128.f90 (+20) 


``````````diff
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 3d42208688497..f87cbb67a1d05 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -2985,9 +2985,13 @@ void FuncResultStack::CompleteFunctionResultType() {
   if (info && &info->scope == &scopeHandler_.currScope() &&
       info->resultSymbol) {
     if (info->parsedType) {
+      // Clear parsedType first to avoid re-entrance via ConvertToObjectEntity
+      // when the type-spec references the function result name.
+      const auto *savedParsedType{info->parsedType};
+      info->parsedType = nullptr;
       scopeHandler_.messageHandler().set_currStmtSource(info->source);
       if (const auto *type{
-              scopeHandler_.ProcessTypeSpec(*info->parsedType, true)}) {
+              scopeHandler_.ProcessTypeSpec(*savedParsedType, true)}) {
         Symbol &symbol{*info->resultSymbol};
         if (!scopeHandler_.context().HasError(symbol)) {
           if (symbol.GetType()) {
@@ -2999,7 +3003,6 @@ void FuncResultStack::CompleteFunctionResultType() {
           }
         }
       }
-      info->parsedType = nullptr;
     }
     if (TypesMismatchIfNonNull(
             info->resultSymbol->GetType(), info->previousImplicitType)) {
diff --git a/flang/test/Semantics/resolve128.f90 b/flang/test/Semantics/resolve128.f90
new file mode 100644
index 0000000000000..5acdcac1d9f5d
--- /dev/null
+++ b/flang/test/Semantics/resolve128.f90
@@ -0,0 +1,20 @@
+! 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: Function cannot have both an explicit type prefix and a RESULT suffix
+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: Must be a constant value
+integer(f3) function f3()
+  f3 = 2
+end function

``````````

</details>


https://github.com/llvm/llvm-project/pull/194678


More information about the flang-commits mailing list