Index: flang/lib/Semantics/resolve-names.cpp =================================================================== --- flang/lib/Semantics/resolve-names.cpp +++ flang/lib/Semantics/resolve-names.cpp @@ -807,7 +807,6 @@ public: bool HandleStmtFunction(const parser::StmtFunctionStmt &); bool Pre(const parser::SubroutineStmt &); - void Post(const parser::SubroutineStmt &); bool Pre(const parser::FunctionStmt &); void Post(const parser::FunctionStmt &); bool Pre(const parser::EntryStmt &); @@ -825,7 +824,8 @@ const ProgramTree::EntryStmtList * = nullptr); bool BeginMpSubprogram(const parser::Name &); void PushBlockDataScope(const parser::Name &); - void EndSubprogram(); + void EndSubprogram( + const std::optional * = nullptr); protected: // Set when we see a stmt function that is really an array element assignment @@ -3196,7 +3196,9 @@ } } } - return true; + // LanguageBindingSpec deferred to Post(EntryStmt) or, for FunctionStmt, + // all the way to EndSubprogram(). + return false; } bool SubprogramVisitor::Pre(const parser::PrefixSpec &x) { @@ -3222,30 +3224,27 @@ std::get>(x.t).statement.t)}; return BeginSubprogram(name, Symbol::Flag::Subroutine); } -void SubprogramVisitor::Post(const parser::InterfaceBody::Subroutine &) { - EndSubprogram(); +void SubprogramVisitor::Post(const parser::InterfaceBody::Subroutine &x) { + EndSubprogram(&std::get>( + std::get>(x.t).statement.t)); } bool SubprogramVisitor::Pre(const parser::InterfaceBody::Function &x) { const auto &name{std::get( std::get>(x.t).statement.t)}; return BeginSubprogram(name, Symbol::Flag::Function); } -void SubprogramVisitor::Post(const parser::InterfaceBody::Function &) { - EndSubprogram(); -} - -bool SubprogramVisitor::Pre(const parser::SubroutineStmt &) { - return BeginAttrs(); -} -bool SubprogramVisitor::Pre(const parser::FunctionStmt &) { - FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())}; - CHECK(!info.inFunctionStmt); - info.inFunctionStmt = true; - return BeginAttrs(); +void SubprogramVisitor::Post(const parser::InterfaceBody::Function &x) { + const auto &maybeSuffix{std::get>( + std::get>(x.t).statement.t)}; + EndSubprogram(maybeSuffix ? &maybeSuffix->binding : nullptr); } -bool SubprogramVisitor::Pre(const parser::EntryStmt &) { return BeginAttrs(); } -void SubprogramVisitor::Post(const parser::SubroutineStmt &stmt) { +bool SubprogramVisitor::Pre(const parser::SubroutineStmt &stmt) { + BeginAttrs(); + Walk(std::get>(stmt.t)); + Walk(std::get(stmt.t)); + Walk(std::get>(stmt.t)); + // Don't traverse the LanguageBindingSpec now; it's deferred to EndSubprogram. const auto &name{std::get(stmt.t)}; auto &details{PostSubprogramStmt(name)}; for (const auto &dummyArg : std::get>(stmt.t)) { @@ -3256,7 +3255,15 @@ details.add_alternateReturn(); } } + return false; } +bool SubprogramVisitor::Pre(const parser::FunctionStmt &) { + FuncResultStack::FuncInfo &info{DEREF(funcResultStack().Top())}; + CHECK(!info.inFunctionStmt); + info.inFunctionStmt = true; + return BeginAttrs(); +} +bool SubprogramVisitor::Pre(const parser::EntryStmt &) { return BeginAttrs(); } void SubprogramVisitor::Post(const parser::FunctionStmt &stmt) { const auto &name{std::get(stmt.t)}; @@ -3309,11 +3316,6 @@ SubprogramDetails &SubprogramVisitor::PostSubprogramStmt( const parser::Name &name) { Symbol &symbol{*currScope().symbol()}; - auto &subp{symbol.get()}; - SetBindNameOn(symbol); - CHECK(name.source == symbol.name() || - (subp.bindName() && symbol.owner().IsGlobal() && - context().IsTempName(symbol.name().ToString()))); symbol.attrs() |= EndAttrs(); if (symbol.attrs().test(Attr::MODULE)) { symbol.attrs().set(Attr::EXTERNAL, false); @@ -3322,6 +3324,9 @@ } void SubprogramVisitor::Post(const parser::EntryStmt &stmt) { + if (const auto &suffix{std::get>(stmt.t)}) { + Walk(suffix->binding); + } PostEntryStmt(stmt); EndAttrs(); } @@ -3576,10 +3581,20 @@ return true; } -void SubprogramVisitor::EndSubprogram() { +void SubprogramVisitor::EndSubprogram( + const std::optional *binding) { if (IsFunction(currScope())) { funcResultStack().Pop(); } + if (binding && *binding && currScope().symbol()) { + // Finally process the BIND(C,NAME=name) now that symbols in the name + // expression will resolve local names. + auto flagRestorer{common::ScopedSet(inSpecificationPart_, false)}; + BeginAttrs(); + Walk(**binding); + SetBindNameOn(*currScope().symbol()); + currScope().symbol()->attrs() |= EndAttrs(); + } PopScope(); } @@ -7405,7 +7420,27 @@ } void ResolveNamesVisitor::EndScopeForNode(const ProgramTree &node) { - EndSubprogram(); + using BindingPtr = const std::optional *; + EndSubprogram(common::visit( + common::visitors{ + [](const parser::Statement *stmt) { + if (stmt) { + if (const auto &maybeSuffix{ + std::get>( + stmt->statement.t)}) { + return &maybeSuffix->binding; + } + } + return BindingPtr{}; + }, + [](const parser::Statement *stmt) { + return stmt ? &std::get>( + stmt->statement.t) + : BindingPtr{}; + }, + [](const auto *) { return BindingPtr{}; }, + }, + node.stmt())); } // Some analyses and checks, such as the processing of initializers of Index: flang/test/Lower/program-units-fir-mangling.f90 =================================================================== --- flang/test/Lower/program-units-fir-mangling.f90 +++ flang/test/Lower/program-units-fir-mangling.f90 @@ -185,4 +185,41 @@ entry some_other_entry() bind(c) end subroutine +! Test that semantics constructs binding labels with local name resolution +module testMod3 + character*(*), parameter :: foo = "bad!!" + character*(*), parameter :: ok = "ok" + interface + real function f1() bind(c,name=ok//'1') + import ok + end function + subroutine s1() bind(c,name=ok//'2') + import ok + end subroutine + end interface + contains +! CHECK-LABEL: func @ok3() -> f32 attributes {fir.sym_name = "_QMtestmod3Pf2"} { + real function f2() bind(c,name=foo//'3') + character*(*), parameter :: foo = ok +! CHECK: fir.call @ok1() : () -> f32 +! CHECK-LABEL: func @ok4() -> f32 attributes {fir.sym_name = "_QMtestmod3Pf3"} { + entry f3() bind(c,name=foo//'4') +! CHECK: fir.call @ok1() : () -> f32 + f2 = f1() + end function +! CHECK-LABEL: func @ok5() attributes {fir.sym_name = "_QMtestmod3Ps2"} { + subroutine s2() bind(c,name=foo//'5') + character*(*), parameter :: foo = ok +! CHECK: fir.call @ok2() : () -> () +! CHECK-LABEL: func @ok6() attributes {fir.sym_name = "_QMtestmod3Ps3"} { + entry s3() bind(c,name=foo//'6') +! CHECK: fir.call @ok2() : () -> () + continue ! force end of specification part +! CHECK-LABEL: func @ok7() attributes {fir.sym_name = "_QMtestmod3Ps4"} { + entry s4() bind(c,name=foo//'7') +! CHECK: fir.call @ok2() : () -> () + call s1 + end subroutine +end module + ! CHECK-LABEL: fir.global internal @_QFfooEpi : f32 {