From: Peter Klausler Date: Tue, 18 Jul 2023 23:14:49 +0000 (-0700) Subject: [flang] Preserve errors from generic matching X-Git-Tag: upstream/17.0.6~778 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fe33374fbff267e54e543745b98f826e05c8bab8;p=platform%2Fupstream%2Fllvm.git [flang] Preserve errors from generic matching When searching for a matching specific procedure for a set of actual arguments in a type-bound generic interface for a defined operator, don't discard any error messages that may have been produced for the specific that was found. Tweak the code to preserve those messages and add them to the context's messages, and add a test. Differential Revision: https://reviews.llvm.org/D155966 --- diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index f1087c7..be67ae8 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -3038,14 +3038,14 @@ std::optional ExpressionAnalyzer::CheckCall( ok &= semantics::CheckArguments(*chars, arguments, context_, context_.FindScope(callSite), treatExternalAsImplicit, specificIntrinsic); - if (procSymbol && !IsPureProcedure(*procSymbol)) { - if (const semantics::Scope * - pure{semantics::FindPureProcedureContaining( - context_.FindScope(callSite))}) { - Say(callSite, - "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US, - procSymbol->name(), DEREF(pure->symbol()).name()); - } + } + if (procSymbol && !IsPureProcedure(*procSymbol)) { + if (const semantics::Scope * + pure{semantics::FindPureProcedureContaining( + context_.FindScope(callSite))}) { + Say(callSite, + "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US, + procSymbol->name(), DEREF(pure->symbol()).name()); } } if (ok && !treatExternalAsImplicit && procSymbol && @@ -4010,8 +4010,10 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( std::string oprNameString{ isUserOp ? std::string{opr} : "operator("s + opr + ')'}; parser::CharBlock oprName{oprNameString}; + parser::Messages hitBuffer; { - auto restorer{context_.GetContextualMessages().DiscardMessages()}; + parser::Messages buffer; + auto restorer{context_.GetContextualMessages().SetMessages(buffer)}; const auto &scope{context_.context().FindScope(source_)}; if (Symbol *symbol{scope.FindSymbol(oprName)}) { anyPossibilities = true; @@ -4023,10 +4025,12 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( result.reset(); } else { hit.push_back(symbol); + hitBuffer = std::move(buffer); } } } for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) { + buffer.clear(); const Symbol *generic{nullptr}; if (const Symbol *binding{ FindBoundOp(oprName, passIndex, generic, false)}) { @@ -4038,6 +4042,7 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( } else { result = std::move(thisResult); hit.push_back(binding); + hitBuffer = std::move(buffer); } } } @@ -4053,6 +4058,9 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( } } } + if (auto *msgs{context_.GetContextualMessages().messages()}) { + msgs->Annex(std::move(hitBuffer)); + } } else if (inaccessible) { context_.Say(source_, std::move(*inaccessible)); } else if (anyPossibilities) { @@ -4074,12 +4082,15 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( } MaybeExpr result; std::vector hit; + parser::Messages hitBuffer; { - auto restorer{context_.GetContextualMessages().DiscardMessages()}; for (std::size_t i{0}; i < oprs.size(); ++i) { + parser::Messages buffer; + auto restorer{context_.GetContextualMessages().SetMessages(buffer)}; if (MaybeExpr thisResult{TryDefinedOp(oprs[i], error)}) { result = std::move(thisResult); hit.push_back(oprs[i]); + hitBuffer = std::move(buffer); } } } @@ -4089,6 +4100,8 @@ MaybeExpr ArgumentAnalyzer::TryDefinedOp( context_.Say( "Matching accessible definitions were found with %zd variant spellings of the generic operator ('%s', '%s')"_err_en_US, hit.size(), ToUpperCase(hit[0]), ToUpperCase(hit[1])); + } else { // one hit; preserve errors + context_.context().messages().Annex(std::move(hitBuffer)); } return result; } diff --git a/flang/test/Semantics/pure01.f90 b/flang/test/Semantics/pure01.f90 new file mode 100644 index 0000000..e0911ef --- /dev/null +++ b/flang/test/Semantics/pure01.f90 @@ -0,0 +1,19 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Ensure that an impure bound operator can't be called +! from a pure context. +module m + type t + contains + procedure :: binding => func + generic :: operator(.not.) => binding + end type + contains + impure integer function func(x) + class(t), intent(in) :: x + func = 0 + end + pure integer function test + !ERROR: Procedure 'func' referenced in pure subprogram 'test' must be pure too + test = .not. t() + end +end