diff options
Diffstat (limited to 'flang/lib/Semantics')
| -rw-r--r-- | flang/lib/Semantics/check-call.cpp | 7 | ||||
| -rw-r--r-- | flang/lib/Semantics/check-call.h | 11 | ||||
| -rw-r--r-- | flang/lib/Semantics/check-declarations.cpp | 6 | ||||
| -rw-r--r-- | flang/lib/Semantics/expression.cpp | 114 | ||||
| -rw-r--r-- | flang/lib/Semantics/openmp-utils.cpp | 3 | ||||
| -rw-r--r-- | flang/lib/Semantics/resolve-names.cpp | 6 |
6 files changed, 94 insertions, 53 deletions
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp index e4d2a0d..c51d40b 100644 --- a/flang/lib/Semantics/check-call.cpp +++ b/flang/lib/Semantics/check-call.cpp @@ -2241,10 +2241,9 @@ static void CheckSpecificIntrinsic(const characteristics::Procedure &proc, } } -static parser::Messages CheckExplicitInterface( - const characteristics::Procedure &proc, evaluate::ActualArguments &actuals, - SemanticsContext &context, const Scope *scope, - const evaluate::SpecificIntrinsic *intrinsic, +parser::Messages CheckExplicitInterface(const characteristics::Procedure &proc, + evaluate::ActualArguments &actuals, SemanticsContext &context, + const Scope *scope, const evaluate::SpecificIntrinsic *intrinsic, bool allowActualArgumentConversions, bool extentErrors, bool ignoreImplicitVsExplicit) { evaluate::FoldingContext &foldingContext{context.foldingContext()}; diff --git a/flang/lib/Semantics/check-call.h b/flang/lib/Semantics/check-call.h index 46bc61a..a69b792 100644 --- a/flang/lib/Semantics/check-call.h +++ b/flang/lib/Semantics/check-call.h @@ -12,11 +12,8 @@ #define FORTRAN_SEMANTICS_CHECK_CALL_H_ #include "flang/Evaluate/call.h" +#include "flang/Parser/message.h" -namespace Fortran::parser { -class Messages; -class ContextualMessages; -} // namespace Fortran::parser namespace Fortran::evaluate::characteristics { struct Procedure; } @@ -47,6 +44,12 @@ bool CheckArgumentIsConstantExprInRange( const evaluate::ActualArguments &actuals, int index, int lowerBound, int upperBound, parser::ContextualMessages &messages); +parser::Messages CheckExplicitInterface( + const evaluate::characteristics::Procedure &, evaluate::ActualArguments &, + SemanticsContext &, const Scope *, const evaluate::SpecificIntrinsic *, + bool allowActualArgumentConversions, bool extentErrors, + bool ignoreImplicitVsExplicit); + // Checks actual arguments for the purpose of resolving a generic interface. bool CheckInterfaceForGeneric(const evaluate::characteristics::Procedure &, evaluate::ActualArguments &, SemanticsContext &, diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp index 31e246c..549ee83 100644 --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -472,6 +472,10 @@ void CheckHelper::Check(const Symbol &symbol) { messages_.Say( "A function result may not also be a named constant"_err_en_US); } + if (!IsProcedurePointer(symbol) && IsProcedure(symbol)) { + messages_.Say( + "A function result may not be a procedure unless it is a procedure pointer"_err_en_US); + } } if (IsAutomatic(symbol)) { if (const Symbol * common{FindCommonBlockContaining(symbol)}) { @@ -1781,7 +1785,7 @@ void CheckHelper::CheckExternal(const Symbol &symbol) { if (auto previousChars{Characterize(previous)}) { std::string whyNot; if (!chars->IsCompatibleWith(*previousChars, - /*ignoreImplicitVsExplicit=*/false, &whyNot)) { + /*ignoreImplicitVsExplicit=*/true, &whyNot)) { if (auto *msg{Warn(common::UsageWarning::ExternalInterfaceMismatch, "The external interface '%s' is not compatible with an earlier definition (%s)"_warn_en_US, symbol.name(), whyNot)}) { diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 4aeb9a4..32aa6b1 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2552,11 +2552,12 @@ auto ExpressionAnalyzer::AnalyzeProcedureComponentRef( } return true; }}; - auto pair{ - ResolveGeneric(generic, arguments, adjustment, isSubroutine)}; - sym = pair.first; + auto result{ResolveGeneric( + generic, arguments, adjustment, isSubroutine, SymbolVector{})}; + sym = result.specific; if (!sym) { - EmitGenericResolutionError(generic, pair.second, isSubroutine); + EmitGenericResolutionError(generic, result.failedDueToAmbiguity, + isSubroutine, arguments, result.tried); return std::nullopt; } // re-resolve the name to the specific binding @@ -2886,10 +2887,10 @@ const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) { // Resolve a call to a generic procedure with given actual arguments. // adjustActuals is called on procedure bindings to handle pass arg. -std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( - const Symbol &symbol, const ActualArguments &actuals, - const AdjustActuals &adjustActuals, bool isSubroutine, - bool mightBeStructureConstructor) { +auto ExpressionAnalyzer::ResolveGeneric(const Symbol &symbol, + const ActualArguments &actuals, const AdjustActuals &adjustActuals, + bool isSubroutine, SymbolVector &&tried, bool mightBeStructureConstructor) + -> GenericResolution { const Symbol &ultimate{symbol.GetUltimate()}; // Check for a match with an explicit INTRINSIC const Symbol *explicitIntrinsic{nullptr}; @@ -2948,7 +2949,7 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( // cannot be unambiguously distinguished // Underspecified external procedure actual arguments can // also lead to ambiguity. - return {nullptr, true /* due to ambiguity */}; + return {nullptr, true /* due to ambiguity */, std::move(tried)}; } } if (!procedure->IsElemental()) { @@ -2959,6 +2960,8 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( } crtMatchingDistance = ComputeCudaMatchingDistance( context_.languageFeatures(), *procedure, localActuals); + } else { + tried.push_back(*specific); } } } @@ -3038,11 +3041,12 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( // Check parent derived type if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) { if (const Symbol * extended{parentScope->FindComponent(symbol.name())}) { - auto pair{ResolveGeneric( - *extended, actuals, adjustActuals, isSubroutine, false)}; - if (pair.first) { - return pair; + auto result{ResolveGeneric(*extended, actuals, adjustActuals, + isSubroutine, std::move(tried), false)}; + if (result.specific != nullptr) { + return result; } + tried = std::move(result.tried); } } // Structure constructor? @@ -3054,14 +3058,15 @@ std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) { if (const Symbol * outer{symbol.owner().parent().FindSymbol(symbol.name())}) { - auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine, - mightBeStructureConstructor)}; - if (pair.first) { - return pair; + auto result{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine, + std::move(tried), mightBeStructureConstructor)}; + if (result.specific) { + return result; } + tried = std::move(result.tried); } } - return {nullptr, false}; + return {nullptr, false, std::move(tried)}; } const Symbol &ExpressionAnalyzer::AccessSpecific( @@ -3098,16 +3103,39 @@ const Symbol &ExpressionAnalyzer::AccessSpecific( } } -void ExpressionAnalyzer::EmitGenericResolutionError( - const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) { - Say(dueToAmbiguity - ? "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 - : semantics::IsGenericDefinedOp(symbol) - ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US - : isSubroutine - ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US - : "No specific function of generic '%s' matches the actual arguments"_err_en_US, - symbol.name()); +void ExpressionAnalyzer::EmitGenericResolutionError(const Symbol &symbol, + bool dueToAmbiguity, bool isSubroutine, ActualArguments &arguments, + const SymbolVector &tried) { + if (auto *msg{Say(dueToAmbiguity + ? "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 + : semantics::IsGenericDefinedOp(symbol) + ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US + : isSubroutine + ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US + : "No specific function of generic '%s' matches the actual arguments"_err_en_US, + symbol.name())}) { + parser::ContextualMessages &messages{GetContextualMessages()}; + semantics::Scope &scope{context_.FindScope(messages.at())}; + for (const Symbol &specific : tried) { + if (auto procChars{characteristics::Procedure::Characterize( + specific, GetFoldingContext())}) { + if (procChars->HasExplicitInterface()) { + if (auto reasons{semantics::CheckExplicitInterface(*procChars, + arguments, context_, &scope, /*intrinsic=*/nullptr, + /*allocActualArgumentConversions=*/false, + /*extentErrors=*/false, + /*ignoreImplicitVsExplicit=*/false)}; + !reasons.empty()) { + reasons.AttachTo( + msg->Attach(specific.name(), + "Specific procedure '%s' does not match the actual arguments because"_en_US, + specific.name()), + parser::Severity::None); + } + } + } + } + } } auto ExpressionAnalyzer::GetCalleeAndArguments( @@ -3146,12 +3174,14 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name, bool isGenericInterface{ultimate.has<semantics::GenericDetails>()}; bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)}; const Symbol *resolution{nullptr}; + SymbolVector tried; if (isGenericInterface || isExplicitIntrinsic) { ExpressionAnalyzer::AdjustActuals noAdjustment; - auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine, - mightBeStructureConstructor)}; - resolution = pair.first; - dueToAmbiguity = pair.second; + auto result{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine, + SymbolVector{}, mightBeStructureConstructor)}; + resolution = result.specific; + dueToAmbiguity = result.failedDueToAmbiguity; + tried = std::move(result.tried); if (resolution) { if (context_.GetPPCBuiltinsScope() && resolution->name().ToString().rfind("__ppc_", 0) == 0) { @@ -3182,7 +3212,8 @@ auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name, std::move(specificCall->arguments)}; } else { if (isGenericInterface) { - EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine); + EmitGenericResolutionError( + *symbol, dueToAmbiguity, isSubroutine, arguments, tried); } return std::nullopt; } @@ -4955,8 +4986,10 @@ std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc( auto restorer{context_.GetContextualMessages().DiscardMessages()}; if (const Symbol *symbol{scope.FindSymbol(oprName)}) { ExpressionAnalyzer::AdjustActuals noAdjustment; - proc = - context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first; + proc = context_ + .ResolveGeneric( + *symbol, actuals_, noAdjustment, true, SymbolVector{}) + .specific; if (proc) { isProcElemental = IsElementalProcedure(*proc); } @@ -5105,17 +5138,18 @@ const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, [&](const Symbol &proc, ActualArguments &) { return passIndex == GetPassIndex(proc).value_or(-1); }}; - auto pair{ - context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)}; - if (const Symbol *binding{pair.first}) { + auto result{context_.ResolveGeneric( + *generic, actuals_, adjustment, isSubroutine, SymbolVector{})}; + if (const Symbol *binding{result.specific}) { CHECK(binding->has<semantics::ProcBindingDetails>()); // Use the most recent override of the binding, if any return scope->FindComponent(binding->name()); } else { if (isAmbiguous) { - *isAmbiguous = pair.second; + *isAmbiguous = result.failedDueToAmbiguity; } - context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); + context_.EmitGenericResolutionError(*generic, result.failedDueToAmbiguity, + isSubroutine, actuals_, result.tried); } } return nullptr; diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp index cc55bb4..6b304b6 100644 --- a/flang/lib/Semantics/openmp-utils.cpp +++ b/flang/lib/Semantics/openmp-utils.cpp @@ -26,7 +26,9 @@ #include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/scope.h" #include "flang/Semantics/semantics.h" +#include "flang/Semantics/symbol.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" @@ -505,5 +507,4 @@ bool IsStrictlyStructuredBlock(const parser::Block &block) { return false; } } - } // namespace Fortran::semantics::omp diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index db75437..4af6cf6 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1772,11 +1772,11 @@ public: messageHandler().set_currStmtSource(std::nullopt); } - bool Pre(const parser::OmpTypeSpecifier &x) { + bool Pre(const parser::OmpTypeName &x) { BeginDeclTypeSpec(); return true; } - void Post(const parser::OmpTypeSpecifier &x) { // + void Post(const parser::OmpTypeName &x) { // EndDeclTypeSpec(); } @@ -2007,7 +2007,7 @@ void OmpVisitor::ProcessReductionSpecifier( } } EndDeclTypeSpec(); - Walk(std::get<std::optional<parser::OmpReductionCombiner>>(spec.t)); + Walk(std::get<std::optional<parser::OmpCombinerExpression>>(spec.t)); Walk(clauses); PopScope(); } |
