[flang-commits] [flang] [flang] Fix crash from undetected program error. (PR #159847)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 19 13:52:35 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
When a function or subroutine interface block conflicts with a name already in scope, emit an error and avoid a crash.
Fixes https://github.com/llvm/llvm-project/issues/159554.
---
Full diff: https://github.com/llvm/llvm-project/pull/159847.diff
2 Files Affected:
- (modified) flang/lib/Semantics/resolve-names.cpp (+22-14)
- (added) flang/test/Semantics/bug159554.f90 (+8)
``````````diff
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index d0d3b0e1caa5a..6f0a5a567a25c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -955,7 +955,7 @@ class SubprogramVisitor : public virtual ScopeHandler, public InterfaceVisitor {
bool HandlePreviousCalls(const parser::Name &, Symbol &, Symbol::Flag);
const Symbol *CheckExtantProc(const parser::Name &, Symbol::Flag);
// Create a subprogram symbol in the current scope and push a new scope.
- Symbol &PushSubprogramScope(const parser::Name &, Symbol::Flag,
+ Symbol *PushSubprogramScope(const parser::Name &, Symbol::Flag,
const parser::LanguageBindingSpec * = nullptr,
bool hasModulePrefix = false);
Symbol *GetSpecificFromGeneric(const parser::Name &);
@@ -4501,10 +4501,13 @@ bool SubprogramVisitor::HandleStmtFunction(const parser::StmtFunctionStmt &x) {
"'%s' has not been declared as an array or pointer-valued function"_err_en_US);
return false;
}
- auto &symbol{PushSubprogramScope(name, Symbol::Flag::Function)};
- symbol.set(Symbol::Flag::StmtFunction);
- EraseSymbol(symbol); // removes symbol added by PushSubprogramScope
- auto &details{symbol.get<SubprogramDetails>()};
+ Symbol *symbol{PushSubprogramScope(name, Symbol::Flag::Function)};
+ if (!symbol) {
+ return false;
+ }
+ symbol->set(Symbol::Flag::StmtFunction);
+ EraseSymbol(*symbol); // removes symbol added by PushSubprogramScope
+ auto &details{symbol->get<SubprogramDetails>()};
for (const auto &dummyName : std::get<std::list<parser::Name>>(x.t)) {
ObjectEntityDetails dummyDetails{true};
if (auto *dummySymbol{FindInScope(currScope().parent(), dummyName)}) {
@@ -5133,19 +5136,22 @@ bool SubprogramVisitor::BeginSubprogram(const parser::Name &name,
}
}
}
- Symbol &newSymbol{
+ Symbol *newSymbol{
PushSubprogramScope(name, subpFlag, bindingSpec, hasModulePrefix)};
+ if (!newSymbol) {
+ return false;
+ }
if (moduleInterface) {
- newSymbol.get<SubprogramDetails>().set_moduleInterface(*moduleInterface);
+ newSymbol->get<SubprogramDetails>().set_moduleInterface(*moduleInterface);
if (moduleInterface->attrs().test(Attr::PRIVATE)) {
- SetImplicitAttr(newSymbol, Attr::PRIVATE);
+ SetImplicitAttr(*newSymbol, Attr::PRIVATE);
} else if (moduleInterface->attrs().test(Attr::PUBLIC)) {
- SetImplicitAttr(newSymbol, Attr::PUBLIC);
+ SetImplicitAttr(*newSymbol, Attr::PUBLIC);
}
}
if (entryStmts) {
for (const auto &ref : *entryStmts) {
- CreateEntry(*ref, newSymbol);
+ CreateEntry(*ref, *newSymbol);
}
}
return true;
@@ -5252,12 +5258,16 @@ const Symbol *SubprogramVisitor::CheckExtantProc(
return prev;
}
-Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
+Symbol *SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
Symbol::Flag subpFlag, const parser::LanguageBindingSpec *bindingSpec,
bool hasModulePrefix) {
Symbol *symbol{GetSpecificFromGeneric(name)};
const DeclTypeSpec *previousImplicitType{nullptr};
SourceName previousName;
+ if (symbol && inInterfaceBlock() && !symbol->has<SubprogramDetails>()) {
+ SayAlreadyDeclared(name, *symbol);
+ return nullptr;
+ }
if (!symbol) {
if (bindingSpec && currScope().IsGlobal() &&
std::get<std::optional<parser::ScalarDefaultCharConstantExpr>>(
@@ -5286,9 +5296,7 @@ Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
if (subpFlag == Symbol::Flag::Function) {
auto &funcResultTop{funcResultStack().Push(currScope(), name.source)};
funcResultTop.previousImplicitType = previousImplicitType;
- ;
funcResultTop.previousName = previousName;
- ;
}
if (inInterfaceBlock()) {
auto &details{symbol->get<SubprogramDetails>()};
@@ -5314,7 +5322,7 @@ Symbol &SubprogramVisitor::PushSubprogramScope(const parser::Name &name,
found && found->has<HostAssocDetails>()) {
found->set(subpFlag); // PushScope() created symbol
}
- return *symbol;
+ return symbol;
}
void SubprogramVisitor::PushBlockDataScope(const parser::Name &name) {
diff --git a/flang/test/Semantics/bug159554.f90 b/flang/test/Semantics/bug159554.f90
new file mode 100644
index 0000000000000..f5a51ebc0b5cb
--- /dev/null
+++ b/flang/test/Semantics/bug159554.f90
@@ -0,0 +1,8 @@
+!RUN: %python %S/test_errors.py %s %flang_fc1
+use, intrinsic :: iso_c_binding
+interface c_funloc
+!ERROR: 'c_funloc' is already declared in this scoping unit
+ function c_funloc()
+ end function
+end interface
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/159847
More information about the flang-commits
mailing list