Skip to content

[flang] Complete RESULT() name constraint checking #91476

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion flang/lib/Semantics/check-declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1352,7 +1352,7 @@ void CheckHelper::CheckSubprogram(
SubprogramMatchHelper{*this}.Check(symbol, *iface);
}
if (const Scope *entryScope{details.entryScope()}) {
// ENTRY 15.6.2.6, esp. C1571
// ENTRY F'2023 15.6.2.6
std::optional<parser::MessageFixedText> error;
const Symbol *subprogram{entryScope->symbol()};
const SubprogramDetails *subprogramDetails{nullptr};
Expand Down Expand Up @@ -1384,6 +1384,27 @@ void CheckHelper::CheckSubprogram(
}
}
}
if (details.isFunction() &&
details.result().name() != symbol.name()) { // F'2023 C1569 & C1583
if (auto iter{symbol.owner().find(details.result().name())};
iter != symbol.owner().end()) {
const Symbol &resNameSym{*iter->second};
if (const auto *resNameSubp{resNameSym.detailsIf<SubprogramDetails>()}) {
if (const Scope * resNameEntryScope{resNameSubp->entryScope()}) {
const Scope *myScope{
details.entryScope() ? details.entryScope() : symbol.scope()};
if (resNameEntryScope == myScope) {
if (auto *msg{messages_.Say(symbol.name(),
"Explicit RESULT('%s') of function '%s' cannot have the same name as a distinct ENTRY into the same scope"_err_en_US,
details.result().name(), symbol.name())}) {
msg->Attach(
resNameSym.name(), "ENTRY with conflicting name"_en_US);
}
}
}
}
}
}
if (const MaybeExpr & stmtFunction{details.stmtFunction()}) {
if (auto msg{evaluate::CheckStatementFunction(
symbol, *stmtFunction, context_.foldingContext())}) {
Expand Down
49 changes: 19 additions & 30 deletions flang/lib/Semantics/resolve-names.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4048,27 +4048,10 @@ void SubprogramVisitor::CreateEntry(
attrs = extant->attrs();
}
}
bool badResultName{false};
std::optional<SourceName> distinctResultName;
if (suffix && suffix->resultName &&
suffix->resultName->source != entryName.source) {
distinctResultName = suffix->resultName->source;
const parser::Name &resultName{*suffix->resultName};
if (resultName.source == subprogram.name()) { // C1574
Say2(resultName.source,
"RESULT(%s) may not have the same name as the function"_err_en_US,
subprogram, "Containing function"_en_US);
badResultName = true;
} else if (const Symbol * extant{FindSymbol(outer, resultName)}) { // C1574
if (const auto *details{extant->detailsIf<SubprogramDetails>()}) {
if (details->entryScope() == &currScope()) {
Say2(resultName.source,
"RESULT(%s) may not have the same name as an ENTRY in the function"_err_en_US,
extant->name(), "Conflicting ENTRY"_en_US);
badResultName = true;
}
}
}
}
if (outer.IsModule() && !attrs.test(Attr::PRIVATE)) {
attrs.set(Attr::PUBLIC);
Expand Down Expand Up @@ -4104,17 +4087,24 @@ void SubprogramVisitor::CreateEntry(
EntityDetails resultDetails;
resultDetails.set_funcResult(true);
if (distinctResultName) {
if (!badResultName) {
// RESULT(x) can be the same explicitly-named RESULT(x) as
// the enclosing function or another ENTRY.
if (auto iter{currScope().find(suffix->resultName->source)};
iter != currScope().end()) {
result = &*iter->second;
}
if (!result) {
result = &MakeSymbol(
*distinctResultName, Attrs{}, std::move(resultDetails));
}
// An explicit RESULT() can also be an explicit RESULT()
// of the function or another ENTRY.
if (auto iter{currScope().find(suffix->resultName->source)};
iter != currScope().end()) {
result = &*iter->second;
}
if (!result) {
result =
&MakeSymbol(*distinctResultName, Attrs{}, std::move(resultDetails));
} else if (!result->has<EntityDetails>()) {
Say(*distinctResultName,
"ENTRY cannot have RESULT(%s) that is not a variable"_err_en_US,
*distinctResultName)
.Attach(result->name(), "Existing declaration of '%s'"_en_US,
result->name());
result = nullptr;
}
if (result) {
Resolve(*suffix->resultName, *result);
}
} else {
Expand All @@ -4124,8 +4114,7 @@ void SubprogramVisitor::CreateEntry(
entryDetails.set_result(*result);
}
}
if (subpFlag == Symbol::Flag::Subroutine ||
(distinctResultName && !badResultName)) {
if (subpFlag == Symbol::Flag::Subroutine || distinctResultName) {
Symbol &assoc{MakeSymbol(entryName.source)};
assoc.set_details(HostAssocDetails{*entrySymbol});
assoc.set(Symbol::Flag::Subroutine);
Expand Down
15 changes: 13 additions & 2 deletions flang/test/Semantics/entry01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,12 @@ function ifunc()
entry ibad2()
!ERROR: ENTRY in a function may not have an alternate return dummy argument
entry ibadalt(*) ! C1573
!ERROR: RESULT(ifunc) may not have the same name as the function
!ERROR: ENTRY cannot have RESULT(ifunc) that is not a variable
entry isameres() result(ifunc) ! C1574
entry iok()
!ERROR: RESULT(iok) may not have the same name as an ENTRY in the function
!ERROR: Explicit RESULT('iok') of function 'isameres2' cannot have the same name as a distinct ENTRY into the same scope
entry isameres2() result(iok) ! C1574
!ERROR: Explicit RESULT('iok2') of function 'isameres3' cannot have the same name as a distinct ENTRY into the same scope
entry isameres3() result(iok2) ! C1574
!ERROR: 'iok2' is already declared in this scoping unit
entry iok2()
Expand Down Expand Up @@ -255,3 +256,13 @@ subroutine s7(q,q)
!ERROR: 'z' appears more than once as a dummy argument name in this ENTRY statement
entry baz(z,z)
end

!ERROR: Explicit RESULT('f8e1') of function 'f8' cannot have the same name as a distinct ENTRY into the same scope
function f8() result(f8e1)
entry f8e1()
entry f8e2() result(f8e2) ! ok
!ERROR: Explicit RESULT('f8e1') of function 'f8e3' cannot have the same name as a distinct ENTRY into the same scope
entry f8e3() result(f8e1)
!ERROR: ENTRY cannot have RESULT(f8) that is not a variable
entry f8e4() result(f8)
end