Skip to content

Commit 69f1891

Browse files
committed
[flang] Whether a procedure's interface is explicit or not is not a distinguishing characteristic
We note whether a procedure's interface is explicit or implicit as an attribute of its characteristics, so that other semantics can be checked appropriately, but this internal attribute should not be used as a distinguishing characteristic in itself. Fixes #81876.
1 parent fc8d481 commit 69f1891

File tree

7 files changed

+36
-16
lines changed

7 files changed

+36
-16
lines changed

flang/include/flang/Evaluate/characteristics.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,8 @@ struct Procedure {
381381
int FindPassIndex(std::optional<parser::CharBlock>) const;
382382
bool CanBeCalledViaImplicitInterface(std::string *whyNot = nullptr) const;
383383
bool CanOverride(const Procedure &, std::optional<int> passIndex) const;
384-
bool IsCompatibleWith(const Procedure &, std::string *whyNot = nullptr,
385-
const SpecificIntrinsic * = nullptr,
384+
bool IsCompatibleWith(const Procedure &, bool ignoreImplicitVsExplicit,
385+
std::string *whyNot = nullptr, const SpecificIntrinsic * = nullptr,
386386
std::optional<std::string> *warning = nullptr) const;
387387

388388
llvm::raw_ostream &Dump(llvm::raw_ostream &) const;

flang/lib/Evaluate/characteristics.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,8 @@ bool DummyProcedure::IsCompatibleWith(
533533
}
534534
return false;
535535
}
536-
if (!procedure.value().IsCompatibleWith(actual.procedure.value(), whyNot)) {
536+
if (!procedure.value().IsCompatibleWith(actual.procedure.value(),
537+
/*ignoreImplicitVsExplicit=*/false, whyNot)) {
537538
if (whyNot) {
538539
*whyNot = "incompatible dummy procedure interfaces: "s + *whyNot;
539540
}
@@ -1206,7 +1207,8 @@ bool FunctionResult::IsCompatibleWith(
12061207
CHECK(ifaceProc != nullptr);
12071208
if (const auto *actualProc{
12081209
std::get_if<CopyableIndirection<Procedure>>(&actual.u)}) {
1209-
if (ifaceProc->value().IsCompatibleWith(actualProc->value(), whyNot)) {
1210+
if (ifaceProc->value().IsCompatibleWith(actualProc->value(),
1211+
/*ignoreImplicitVsExplicit=*/false, whyNot)) {
12101212
return true;
12111213
}
12121214
if (whyNot) {
@@ -1251,7 +1253,8 @@ bool Procedure::operator==(const Procedure &that) const {
12511253
cudaSubprogramAttrs == that.cudaSubprogramAttrs;
12521254
}
12531255

1254-
bool Procedure::IsCompatibleWith(const Procedure &actual, std::string *whyNot,
1256+
bool Procedure::IsCompatibleWith(const Procedure &actual,
1257+
bool ignoreImplicitVsExplicit, std::string *whyNot,
12551258
const SpecificIntrinsic *specificIntrinsic,
12561259
std::optional<std::string> *warning) const {
12571260
// 15.5.2.9(1): if dummy is not pure, actual need not be.
@@ -1265,6 +1268,9 @@ bool Procedure::IsCompatibleWith(const Procedure &actual, std::string *whyNot,
12651268
}
12661269
Attrs differences{attrs ^ actualAttrs};
12671270
differences.reset(Attr::Subroutine); // dealt with specifically later
1271+
if (ignoreImplicitVsExplicit) {
1272+
differences.reset(Attr::ImplicitInterface);
1273+
}
12681274
if (!differences.empty()) {
12691275
if (whyNot) {
12701276
auto sep{": "s};

flang/lib/Evaluate/tools.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,8 @@ std::optional<parser::MessageFixedText> CheckProcCompatibility(bool isCall,
10971097
*rhsProcedure->functionResult, &whyNotCompatible)) {
10981098
msg =
10991099
"Function %s associated with incompatible function designator '%s': %s"_err_en_US;
1100-
} else if (lhsProcedure->IsCompatibleWith(*rhsProcedure, &whyNotCompatible,
1100+
} else if (lhsProcedure->IsCompatibleWith(*rhsProcedure,
1101+
/*ignoreImplictVsExplicit=*/true, &whyNotCompatible,
11011102
specificIntrinsic, &warning)) {
11021103
// OK
11031104
} else if (isCall) {

flang/lib/Semantics/check-call.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,8 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg,
975975
if (interface.HasExplicitInterface()) {
976976
std::string whyNot;
977977
std::optional<std::string> warning;
978-
if (!interface.IsCompatibleWith(argInterface, &whyNot,
978+
if (!interface.IsCompatibleWith(argInterface,
979+
/*ignoreImplicitVsExplicit=*/true, &whyNot,
979980
/*specificIntrinsic=*/nullptr, &warning)) {
980981
// 15.5.2.9(1): Explicit interfaces must match
981982
if (argInterface.HasExplicitInterface()) {

flang/lib/Semantics/check-declarations.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,7 +1481,8 @@ void CheckHelper::CheckExternal(const Symbol &symbol) {
14811481
if (auto globalChars{Characterize(*global)}) {
14821482
if (chars->HasExplicitInterface()) {
14831483
std::string whyNot;
1484-
if (!chars->IsCompatibleWith(*globalChars, &whyNot)) {
1484+
if (!chars->IsCompatibleWith(*globalChars,
1485+
/*ignoreImplicitVsExplicit=*/false, &whyNot)) {
14851486
msg = WarnIfNotInModuleFile(
14861487
"The global subprogram '%s' is not compatible with its local procedure declaration (%s)"_warn_en_US,
14871488
global->name(), whyNot);
@@ -1507,7 +1508,8 @@ void CheckHelper::CheckExternal(const Symbol &symbol) {
15071508
if (auto chars{Characterize(symbol)}) {
15081509
if (auto previousChars{Characterize(previous)}) {
15091510
std::string whyNot;
1510-
if (!chars->IsCompatibleWith(*previousChars, &whyNot)) {
1511+
if (!chars->IsCompatibleWith(*previousChars,
1512+
/*ignoreImplicitVsExplicit=*/false, &whyNot)) {
15111513
if (auto *msg{WarnIfNotInModuleFile(
15121514
"The external interface '%s' is not compatible with an earlier definition (%s)"_warn_en_US,
15131515
symbol.name(), whyNot)}) {

flang/lib/Semantics/expression.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3129,7 +3129,8 @@ std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
31293129
if (auto iter{implicitInterfaces_.find(name)};
31303130
iter != implicitInterfaces_.end()) {
31313131
std::string whyNot;
3132-
if (!chars->IsCompatibleWith(iter->second.second, &whyNot)) {
3132+
if (!chars->IsCompatibleWith(iter->second.second,
3133+
/*ignoreImplicitVsExplicit=*/false, &whyNot)) {
31333134
if (auto *msg{Say(callSite,
31343135
"Reference to the procedure '%s' has an implicit interface that is distinct from another reference: %s"_warn_en_US,
31353136
name, whyNot)}) {

flang/lib/Semantics/resolve-names.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8362,16 +8362,25 @@ bool ResolveNamesVisitor::Pre(const parser::PointerAssignmentStmt &x) {
83628362
const auto &bounds{std::get<parser::PointerAssignmentStmt::Bounds>(x.t)};
83638363
const auto &expr{std::get<parser::Expr>(x.t)};
83648364
ResolveDataRef(dataRef);
8365+
Symbol *ptrSymbol{parser::GetLastName(dataRef).symbol};
83658366
Walk(bounds);
83668367
// Resolve unrestricted specific intrinsic procedures as in "p => cos".
83678368
if (const parser::Name * name{parser::Unwrap<parser::Name>(expr)}) {
83688369
if (NameIsKnownOrIntrinsic(*name)) {
8369-
// If the name is known because it is an object entity from a host
8370-
// procedure, create a host associated symbol.
8371-
if (Symbol * symbol{name->symbol}; symbol &&
8372-
symbol->GetUltimate().has<ObjectEntityDetails>() &&
8373-
IsUplevelReference(*symbol)) {
8374-
MakeHostAssocSymbol(*name, *symbol);
8370+
if (Symbol * symbol{name->symbol}) {
8371+
if (IsProcedurePointer(ptrSymbol) &&
8372+
!ptrSymbol->test(Symbol::Flag::Function) &&
8373+
!ptrSymbol->test(Symbol::Flag::Subroutine)) {
8374+
if (symbol->test(Symbol::Flag::Function)) {
8375+
ApplyImplicitRules(*ptrSymbol);
8376+
}
8377+
}
8378+
// If the name is known because it is an object entity from a host
8379+
// procedure, create a host associated symbol.
8380+
if (symbol->GetUltimate().has<ObjectEntityDetails>() &&
8381+
IsUplevelReference(*symbol)) {
8382+
MakeHostAssocSymbol(*name, *symbol);
8383+
}
83758384
}
83768385
return false;
83778386
}

0 commit comments

Comments
 (0)