Skip to content

Commit 076cc19

Browse files
author
git apple-llvm automerger
committed
Merge commit 'e34d603f185b' from llvm.org/main into next
2 parents f1f7a7c + e34d603 commit 076cc19

File tree

7 files changed

+123
-53
lines changed

7 files changed

+123
-53
lines changed

flang/include/flang/Evaluate/call.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class ActualArgument {
112112
int Rank() const;
113113
bool operator==(const ActualArgument &) const;
114114
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;
115+
std::string AsFortran() const;
115116

116117
std::optional<parser::CharBlock> keyword() const { return keyword_; }
117118
ActualArgument &set_keyword(parser::CharBlock x) {

flang/include/flang/Semantics/expression.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,16 @@ class ExpressionAnalyzer {
367367
using AdjustActuals =
368368
std::optional<std::function<bool(const Symbol &, ActualArguments &)>>;
369369
const Symbol *ResolveForward(const Symbol &);
370-
std::pair<const Symbol *, bool /* failure due ambiguity */> ResolveGeneric(
371-
const Symbol &, const ActualArguments &, const AdjustActuals &,
372-
bool isSubroutine, bool mightBeStructureConstructor = false);
373-
void EmitGenericResolutionError(
374-
const Symbol &, bool dueToNullActuals, bool isSubroutine);
370+
struct GenericResolution {
371+
const Symbol *specific{nullptr};
372+
bool failedDueToAmbiguity{false};
373+
SymbolVector tried{};
374+
};
375+
GenericResolution ResolveGeneric(const Symbol &, const ActualArguments &,
376+
const AdjustActuals &, bool isSubroutine, SymbolVector &&tried,
377+
bool mightBeStructureConstructor = false);
378+
void EmitGenericResolutionError(const Symbol &, bool dueToNullActuals,
379+
bool isSubroutine, ActualArguments &, const SymbolVector &);
375380
const Symbol &AccessSpecific(
376381
const Symbol &originalGeneric, const Symbol &specific);
377382
std::optional<CalleeAndArguments> GetCalleeAndArguments(const parser::Name &,

flang/lib/Evaluate/formatting.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,13 @@ llvm::raw_ostream &ActualArgument::AsFortran(llvm::raw_ostream &o) const {
252252
return o;
253253
}
254254

255+
std::string ActualArgument::AsFortran() const {
256+
std::string result;
257+
llvm::raw_string_ostream sstream(result);
258+
AsFortran(sstream);
259+
return result;
260+
}
261+
255262
llvm::raw_ostream &SpecificIntrinsic::AsFortran(llvm::raw_ostream &o) const {
256263
return o << name;
257264
}

flang/lib/Semantics/check-call.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2241,10 +2241,9 @@ static void CheckSpecificIntrinsic(const characteristics::Procedure &proc,
22412241
}
22422242
}
22432243

2244-
static parser::Messages CheckExplicitInterface(
2245-
const characteristics::Procedure &proc, evaluate::ActualArguments &actuals,
2246-
SemanticsContext &context, const Scope *scope,
2247-
const evaluate::SpecificIntrinsic *intrinsic,
2244+
parser::Messages CheckExplicitInterface(const characteristics::Procedure &proc,
2245+
evaluate::ActualArguments &actuals, SemanticsContext &context,
2246+
const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic,
22482247
bool allowActualArgumentConversions, bool extentErrors,
22492248
bool ignoreImplicitVsExplicit) {
22502249
evaluate::FoldingContext &foldingContext{context.foldingContext()};

flang/lib/Semantics/check-call.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,8 @@
1212
#define FORTRAN_SEMANTICS_CHECK_CALL_H_
1313

1414
#include "flang/Evaluate/call.h"
15+
#include "flang/Parser/message.h"
1516

16-
namespace Fortran::parser {
17-
class Messages;
18-
class ContextualMessages;
19-
} // namespace Fortran::parser
2017
namespace Fortran::evaluate::characteristics {
2118
struct Procedure;
2219
}
@@ -47,6 +44,12 @@ bool CheckArgumentIsConstantExprInRange(
4744
const evaluate::ActualArguments &actuals, int index, int lowerBound,
4845
int upperBound, parser::ContextualMessages &messages);
4946

47+
parser::Messages CheckExplicitInterface(
48+
const evaluate::characteristics::Procedure &, evaluate::ActualArguments &,
49+
SemanticsContext &, const Scope *, const evaluate::SpecificIntrinsic *,
50+
bool allowActualArgumentConversions, bool extentErrors,
51+
bool ignoreImplicitVsExplicit);
52+
5053
// Checks actual arguments for the purpose of resolving a generic interface.
5154
bool CheckInterfaceForGeneric(const evaluate::characteristics::Procedure &,
5255
evaluate::ActualArguments &, SemanticsContext &,

flang/lib/Semantics/expression.cpp

Lines changed: 74 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,11 +2552,12 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
25522552
}
25532553
return true;
25542554
}};
2555-
auto pair{
2556-
ResolveGeneric(generic, arguments, adjustment, isSubroutine)};
2557-
sym = pair.first;
2555+
auto result{ResolveGeneric(
2556+
generic, arguments, adjustment, isSubroutine, SymbolVector{})};
2557+
sym = result.specific;
25582558
if (!sym) {
2559-
EmitGenericResolutionError(generic, pair.second, isSubroutine);
2559+
EmitGenericResolutionError(generic, result.failedDueToAmbiguity,
2560+
isSubroutine, arguments, result.tried);
25602561
return std::nullopt;
25612562
}
25622563
// re-resolve the name to the specific binding
@@ -2886,10 +2887,10 @@ const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
28862887

28872888
// Resolve a call to a generic procedure with given actual arguments.
28882889
// adjustActuals is called on procedure bindings to handle pass arg.
2889-
std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
2890-
const Symbol &symbol, const ActualArguments &actuals,
2891-
const AdjustActuals &adjustActuals, bool isSubroutine,
2892-
bool mightBeStructureConstructor) {
2890+
auto ExpressionAnalyzer::ResolveGeneric(const Symbol &symbol,
2891+
const ActualArguments &actuals, const AdjustActuals &adjustActuals,
2892+
bool isSubroutine, SymbolVector &&tried, bool mightBeStructureConstructor)
2893+
-> GenericResolution {
28932894
const Symbol &ultimate{symbol.GetUltimate()};
28942895
// Check for a match with an explicit INTRINSIC
28952896
const Symbol *explicitIntrinsic{nullptr};
@@ -2948,7 +2949,7 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
29482949
// cannot be unambiguously distinguished
29492950
// Underspecified external procedure actual arguments can
29502951
// also lead to ambiguity.
2951-
return {nullptr, true /* due to ambiguity */};
2952+
return {nullptr, true /* due to ambiguity */, std::move(tried)};
29522953
}
29532954
}
29542955
if (!procedure->IsElemental()) {
@@ -2959,6 +2960,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
29592960
}
29602961
crtMatchingDistance = ComputeCudaMatchingDistance(
29612962
context_.languageFeatures(), *procedure, localActuals);
2963+
} else {
2964+
tried.push_back(*specific);
29622965
}
29632966
}
29642967
}
@@ -3038,11 +3041,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
30383041
// Check parent derived type
30393042
if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) {
30403043
if (const Symbol * extended{parentScope->FindComponent(symbol.name())}) {
3041-
auto pair{ResolveGeneric(
3042-
*extended, actuals, adjustActuals, isSubroutine, false)};
3043-
if (pair.first) {
3044-
return pair;
3044+
auto result{ResolveGeneric(*extended, actuals, adjustActuals,
3045+
isSubroutine, std::move(tried), false)};
3046+
if (result.specific != nullptr) {
3047+
return result;
30453048
}
3049+
tried = std::move(result.tried);
30463050
}
30473051
}
30483052
// Structure constructor?
@@ -3054,14 +3058,15 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric(
30543058
if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) {
30553059
if (const Symbol *
30563060
outer{symbol.owner().parent().FindSymbol(symbol.name())}) {
3057-
auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine,
3058-
mightBeStructureConstructor)};
3059-
if (pair.first) {
3060-
return pair;
3061+
auto result{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine,
3062+
std::move(tried), mightBeStructureConstructor)};
3063+
if (result.specific) {
3064+
return result;
30613065
}
3066+
tried = std::move(result.tried);
30623067
}
30633068
}
3064-
return {nullptr, false};
3069+
return {nullptr, false, std::move(tried)};
30653070
}
30663071

30673072
const Symbol &ExpressionAnalyzer::AccessSpecific(
@@ -3098,16 +3103,39 @@ const Symbol &ExpressionAnalyzer::AccessSpecific(
30983103
}
30993104
}
31003105

3101-
void ExpressionAnalyzer::EmitGenericResolutionError(
3102-
const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) {
3103-
Say(dueToAmbiguity
3104-
? "The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface"_err_en_US
3105-
: semantics::IsGenericDefinedOp(symbol)
3106-
? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US
3107-
: isSubroutine
3108-
? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US
3109-
: "No specific function of generic '%s' matches the actual arguments"_err_en_US,
3110-
symbol.name());
3106+
void ExpressionAnalyzer::EmitGenericResolutionError(const Symbol &symbol,
3107+
bool dueToAmbiguity, bool isSubroutine, ActualArguments &arguments,
3108+
const SymbolVector &tried) {
3109+
if (auto *msg{Say(dueToAmbiguity
3110+
? "The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface"_err_en_US
3111+
: semantics::IsGenericDefinedOp(symbol)
3112+
? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US
3113+
: isSubroutine
3114+
? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US
3115+
: "No specific function of generic '%s' matches the actual arguments"_err_en_US,
3116+
symbol.name())}) {
3117+
parser::ContextualMessages &messages{GetContextualMessages()};
3118+
semantics::Scope &scope{context_.FindScope(messages.at())};
3119+
for (const Symbol &specific : tried) {
3120+
if (auto procChars{characteristics::Procedure::Characterize(
3121+
specific, GetFoldingContext())}) {
3122+
if (procChars->HasExplicitInterface()) {
3123+
if (auto reasons{semantics::CheckExplicitInterface(*procChars,
3124+
arguments, context_, &scope, /*intrinsic=*/nullptr,
3125+
/*allocActualArgumentConversions=*/false,
3126+
/*extentErrors=*/false,
3127+
/*ignoreImplicitVsExplicit=*/false)};
3128+
!reasons.empty()) {
3129+
reasons.AttachTo(
3130+
msg->Attach(specific.name(),
3131+
"Specific procedure '%s' does not match the actual arguments because"_en_US,
3132+
specific.name()),
3133+
parser::Severity::None);
3134+
}
3135+
}
3136+
}
3137+
}
3138+
}
31113139
}
31123140

31133141
auto ExpressionAnalyzer::GetCalleeAndArguments(
@@ -3146,12 +3174,14 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
31463174
bool isGenericInterface{ultimate.has<semantics::GenericDetails>()};
31473175
bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)};
31483176
const Symbol *resolution{nullptr};
3177+
SymbolVector tried;
31493178
if (isGenericInterface || isExplicitIntrinsic) {
31503179
ExpressionAnalyzer::AdjustActuals noAdjustment;
3151-
auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine,
3152-
mightBeStructureConstructor)};
3153-
resolution = pair.first;
3154-
dueToAmbiguity = pair.second;
3180+
auto result{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine,
3181+
SymbolVector{}, mightBeStructureConstructor)};
3182+
resolution = result.specific;
3183+
dueToAmbiguity = result.failedDueToAmbiguity;
3184+
tried = std::move(result.tried);
31553185
if (resolution) {
31563186
if (context_.GetPPCBuiltinsScope() &&
31573187
resolution->name().ToString().rfind("__ppc_", 0) == 0) {
@@ -3182,7 +3212,8 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
31823212
std::move(specificCall->arguments)};
31833213
} else {
31843214
if (isGenericInterface) {
3185-
EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine);
3215+
EmitGenericResolutionError(
3216+
*symbol, dueToAmbiguity, isSubroutine, arguments, tried);
31863217
}
31873218
return std::nullopt;
31883219
}
@@ -4955,8 +4986,10 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc(
49554986
auto restorer{context_.GetContextualMessages().DiscardMessages()};
49564987
if (const Symbol *symbol{scope.FindSymbol(oprName)}) {
49574988
ExpressionAnalyzer::AdjustActuals noAdjustment;
4958-
proc =
4959-
context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first;
4989+
proc = context_
4990+
.ResolveGeneric(
4991+
*symbol, actuals_, noAdjustment, true, SymbolVector{})
4992+
.specific;
49604993
if (proc) {
49614994
isProcElemental = IsElementalProcedure(*proc);
49624995
}
@@ -5105,17 +5138,18 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName,
51055138
[&](const Symbol &proc, ActualArguments &) {
51065139
return passIndex == GetPassIndex(proc).value_or(-1);
51075140
}};
5108-
auto pair{
5109-
context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)};
5110-
if (const Symbol *binding{pair.first}) {
5141+
auto result{context_.ResolveGeneric(
5142+
*generic, actuals_, adjustment, isSubroutine, SymbolVector{})};
5143+
if (const Symbol *binding{result.specific}) {
51115144
CHECK(binding->has<semantics::ProcBindingDetails>());
51125145
// Use the most recent override of the binding, if any
51135146
return scope->FindComponent(binding->name());
51145147
} else {
51155148
if (isAmbiguous) {
5116-
*isAmbiguous = pair.second;
5149+
*isAmbiguous = result.failedDueToAmbiguity;
51175150
}
5118-
context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine);
5151+
context_.EmitGenericResolutionError(*generic, result.failedDueToAmbiguity,
5152+
isSubroutine, actuals_, result.tried);
51195153
}
51205154
}
51215155
return nullptr;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2+
module m
3+
interface generic
4+
procedure :: sub1, sub2
5+
end interface
6+
contains
7+
subroutine sub1(x)
8+
end
9+
subroutine sub2(j)
10+
end
11+
end
12+
13+
program test
14+
use m
15+
!CHECK: error: No specific subroutine of generic 'generic' matches the actual arguments
16+
!CHECK: Specific procedure 'sub1' does not match the actual arguments
17+
!CHECK: Actual argument type 'REAL(8)' is not compatible with dummy argument type 'REAL(4)'
18+
!CHECK: Specific procedure 'sub2' does not match the actual arguments
19+
!CHECK: Actual argument type 'REAL(8)' is not compatible with dummy argument type 'INTEGER(4)'
20+
call generic(1.d0)
21+
end

0 commit comments

Comments
 (0)