diff options
author | David Blaikie <dblaikie@gmail.com> | 2019-05-03 00:44:50 +0000 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2019-05-03 00:44:50 +0000 |
commit | 5e328050503c52aff41f96c8c7ca538e3cab85d5 (patch) | |
tree | a33472a5c50006cf417fb5e8fa4d0e1b454c33da /clang/lib | |
parent | d45df094353b8b0b5f1f76d9f5f828c34595fe11 (diff) | |
download | bcm5719-llvm-5e328050503c52aff41f96c8c7ca538e3cab85d5.tar.gz bcm5719-llvm-5e328050503c52aff41f96c8c7ca538e3cab85d5.zip |
SemaOverload: Complete candidates before emitting the error, to ensure diagnostics emitted (or suppressed) during completion don't interfere with the overload notes
Because diagnostics and their notes are not connected at the API level,
if the error message for an overload is emitted, then the overload
candidates are completed - if a diagnostic is emitted during that work,
the notes related to overload candidates would be attached to the latter
diagnostic, not the original error. Sort of worse, if the latter
diagnostic was disabled, the notes are disabled.
Reviewers: rsmith
Differential Revision: https://reviews.llvm.org/D61357
llvm-svn: 359854
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/TemplateName.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 49 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 97 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 269 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 17 |
6 files changed, 283 insertions, 173 deletions
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp index b3c44f6d032..2474d6278b2 100644 --- a/clang/lib/AST/TemplateName.cpp +++ b/clang/lib/AST/TemplateName.cpp @@ -250,6 +250,20 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB << NameStr; } +const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD, + TemplateName N) { + std::string NameStr; + llvm::raw_string_ostream OS(NameStr); + LangOptions LO; + LO.CPlusPlus = true; + LO.Bool = true; + OS << '\''; + N.print(OS, PrintingPolicy(LO)); + OS << '\''; + OS.flush(); + return PD << NameStr; +} + void TemplateName::dump(raw_ostream &OS) const { LangOptions LO; // FIXME! LO.CPlusPlus = true; diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index ce6481c030b..21a4d107ba2 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -399,11 +399,11 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT, break; } - S.Diag(range.getBegin(), msg) - << CT << srcType << destType - << range << src->getSourceRange(); - - candidates.NoteCandidates(S, howManyCandidates, src); + candidates.NoteCandidates( + PartialDiagnosticAt(range.getBegin(), + S.PDiag(msg) << CT << srcType << destType << range + << src->getSourceRange()), + S, howManyCandidates, src); return true; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 807e705ca30..36e82d3900d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2301,8 +2301,8 @@ static bool resolveAllocationOverload( } if (Diagnose) { - S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) - << R.getLookupName() << Range; + PartialDiagnosticAt PD(R.getNameLoc(), S.PDiag(diag::err_ovl_no_viable_function_in_call) + << R.getLookupName() << Range); // If we have aligned candidates, only note the align_val_t candidates // from AlignedCandidates and the non-align_val_t candidates from @@ -2317,30 +2317,34 @@ static bool resolveAllocationOverload( // This was an overaligned allocation, so list the aligned candidates // first. Args.insert(Args.begin() + 1, AlignArg); - AlignedCandidates->NoteCandidates(S, OCD_AllCandidates, Args, "", + AlignedCandidates->NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(), IsAligned); Args.erase(Args.begin() + 1); - Candidates.NoteCandidates(S, OCD_AllCandidates, Args, "", R.getNameLoc(), + Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(), IsUnaligned); } else { - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args); } } return true; case OR_Ambiguous: if (Diagnose) { - S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range), + S, OCD_ViableCandidates, Args); } return true; case OR_Deleted: { if (Diagnose) { - S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_deleted_call) + << R.getLookupName() << Range), + S, OCD_AllCandidates, Args); } return true; } @@ -3504,21 +3508,26 @@ static bool resolveBuiltinNewDeleteOverload(Sema &S, CallExpr *TheCall, } case OR_No_Viable_Function: - S.Diag(R.getNameLoc(), diag::err_ovl_no_viable_function_in_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_no_viable_function_in_call) + << R.getLookupName() << Range), + S, OCD_AllCandidates, Args); return true; case OR_Ambiguous: - S.Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_ViableCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), + S.PDiag(diag::err_ovl_ambiguous_call) + << R.getLookupName() << Range), + S, OCD_ViableCandidates, Args); return true; case OR_Deleted: { - S.Diag(R.getNameLoc(), diag::err_ovl_deleted_call) - << R.getLookupName() << Range; - Candidates.NoteCandidates(S, OCD_AllCandidates, Args); + Candidates.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), S.PDiag(diag::err_ovl_deleted_call) + << R.getLookupName() << Range), + S, OCD_AllCandidates, Args); return true; } } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1ae18b90f85..e8a8887736e 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5971,21 +5971,25 @@ static ExprResult CopyObject(Sema &S, break; case OR_No_Viable_Function: - S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() - ? diag::ext_rvalue_to_reference_temp_copy_no_viable - : diag::err_temp_copy_no_viable) - << (int)Entity.getKind() << CurInitExpr->getType() - << CurInitExpr->getSourceRange(); - CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); + CandidateSet.NoteCandidates( + PartialDiagnosticAt( + Loc, S.PDiag(IsExtraneousCopy && !S.isSFINAEContext() + ? diag::ext_rvalue_to_reference_temp_copy_no_viable + : diag::err_temp_copy_no_viable) + << (int)Entity.getKind() << CurInitExpr->getType() + << CurInitExpr->getSourceRange()), + S, OCD_AllCandidates, CurInitExpr); if (!IsExtraneousCopy || S.isSFINAEContext()) return ExprError(); return CurInit; case OR_Ambiguous: - S.Diag(Loc, diag::err_temp_copy_ambiguous) - << (int)Entity.getKind() << CurInitExpr->getType() - << CurInitExpr->getSourceRange(); - CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Loc, S.PDiag(diag::err_temp_copy_ambiguous) + << (int)Entity.getKind() + << CurInitExpr->getType() + << CurInitExpr->getSourceRange()), + S, OCD_ViableCandidates, CurInitExpr); return ExprError(); case OR_Deleted: @@ -6120,13 +6124,13 @@ static void CheckCXX98CompatAccessibleCopy(Sema &S, break; case OR_No_Viable_Function: - S.Diag(Loc, Diag); - CandidateSet.NoteCandidates(S, OCD_AllCandidates, CurInitExpr); + CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S, + OCD_AllCandidates, CurInitExpr); break; case OR_Ambiguous: - S.Diag(Loc, Diag); - CandidateSet.NoteCandidates(S, OCD_ViableCandidates, CurInitExpr); + CandidateSet.NoteCandidates(PartialDiagnosticAt(Loc, Diag), S, + OCD_ViableCandidates, CurInitExpr); break; case OR_Deleted: @@ -8399,19 +8403,22 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_UserConversionOverloadFailed: switch (FailedOverloadResult) { case OR_Ambiguous: - if (Failure == FK_UserConversionOverloadFailed) - S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition) - << OnlyArg->getType() << DestType - << Args[0]->getSourceRange(); - else - S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous) - << DestType << OnlyArg->getType() - << Args[0]->getSourceRange(); - FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); + FailedCandidateSet.NoteCandidates( + PartialDiagnosticAt( + Kind.getLocation(), + Failure == FK_UserConversionOverloadFailed + ? (S.PDiag(diag::err_typecheck_ambiguous_condition) + << OnlyArg->getType() << DestType + << Args[0]->getSourceRange()) + : (S.PDiag(diag::err_ref_init_ambiguous) + << DestType << OnlyArg->getType() + << Args[0]->getSourceRange())), + S, OCD_ViableCandidates, Args); break; - case OR_No_Viable_Function: + case OR_No_Viable_Function: { + auto Cands = FailedCandidateSet.CompleteCandidates(S, OCD_AllCandidates, Args); if (!S.RequireCompleteType(Kind.getLocation(), DestType.getNonReferenceType(), diag::err_typecheck_nonviable_condition_incomplete, @@ -8421,9 +8428,9 @@ bool InitializationSequence::Diagnose(Sema &S, << OnlyArg->getType() << Args[0]->getSourceRange() << DestType.getNonReferenceType(); - FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); + FailedCandidateSet.NoteCandidates(S, Args, Cands); break; - + } case OR_Deleted: { S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function) << OnlyArg->getType() << DestType.getNonReferenceType() @@ -8587,9 +8594,11 @@ bool InitializationSequence::Diagnose(Sema &S, // bad. switch (FailedOverloadResult) { case OR_Ambiguous: - S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) - << DestType << ArgsRange; - FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args); + FailedCandidateSet.NoteCandidates( + PartialDiagnosticAt(Kind.getLocation(), + S.PDiag(diag::err_ovl_ambiguous_init) + << DestType << ArgsRange), + S, OCD_ViableCandidates, Args); break; case OR_No_Viable_Function: @@ -8638,9 +8647,12 @@ bool InitializationSequence::Diagnose(Sema &S, break; } - S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) - << DestType << ArgsRange; - FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args); + FailedCandidateSet.NoteCandidates( + PartialDiagnosticAt( + Kind.getLocation(), + S.PDiag(diag::err_ovl_no_viable_function_in_init) + << DestType << ArgsRange), + S, OCD_AllCandidates, Args); break; case OR_Deleted: { @@ -9438,12 +9450,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( switch (Result) { case OR_Ambiguous: - Diag(Kind.getLocation(), diag::err_deduced_class_template_ctor_ambiguous) - << TemplateName; // FIXME: For list-initialization candidates, it'd usually be better to // list why they were not viable when given the initializer list itself as // an argument. - Candidates.NoteCandidates(*this, OCD_ViableCandidates, Inits); + Candidates.NoteCandidates( + PartialDiagnosticAt( + Kind.getLocation(), + PDiag(diag::err_deduced_class_template_ctor_ambiguous) + << TemplateName), + *this, OCD_ViableCandidates, Inits); return QualType(); case OR_No_Viable_Function: { @@ -9451,11 +9466,13 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( cast<ClassTemplateDecl>(Template)->getTemplatedDecl(); bool Complete = isCompleteType(Kind.getLocation(), Context.getTypeDeclType(Primary)); - Diag(Kind.getLocation(), - Complete ? diag::err_deduced_class_template_ctor_no_viable - : diag::err_deduced_class_template_incomplete) - << TemplateName << !Guides.empty(); - Candidates.NoteCandidates(*this, OCD_AllCandidates, Inits); + Candidates.NoteCandidates( + PartialDiagnosticAt( + Kind.getLocation(), + PDiag(Complete ? diag::err_deduced_class_template_ctor_no_viable + : diag::err_deduced_class_template_incomplete) + << TemplateName << !Guides.empty()), + *this, OCD_AllCandidates, Inits); return QualType(); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 6da10ac12d7..df979b68b6e 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -3505,18 +3505,25 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { OverloadingResult OvResult = IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false, false); + + if (!(OvResult == OR_Ambiguous || + (OvResult == OR_No_Viable_Function && !CandidateSet.empty()))) + return false; + + auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, From); if (OvResult == OR_Ambiguous) Diag(From->getBeginLoc(), diag::err_typecheck_ambiguous_condition) << From->getType() << ToType << From->getSourceRange(); - else if (OvResult == OR_No_Viable_Function && !CandidateSet.empty()) { + else { // OR_No_Viable_Function && !CandidateSet.empty() if (!RequireCompleteType(From->getBeginLoc(), ToType, diag::err_typecheck_nonviable_condition_incomplete, From->getType(), From->getSourceRange())) Diag(From->getBeginLoc(), diag::err_typecheck_nonviable_condition) << false << From->getType() << From->getSourceRange() << ToType; - } else - return false; - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, From); + } + + CandidateSet.NoteCandidates( + *this, From, Cands); return true; } @@ -10745,11 +10752,9 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, } } -/// When overload resolution fails, prints diagnostic messages containing the -/// candidates in the candidate set. -void OverloadCandidateSet::NoteCandidates( +SmallVector<OverloadCandidate *, 32> OverloadCandidateSet::CompleteCandidates( Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args, - StringRef Opc, SourceLocation OpLoc, + SourceLocation OpLoc, llvm::function_ref<bool(OverloadCandidate &)> Filter) { // Sort the candidates by viability and position. Sorting directly would // be prohibitive, so we make a set of pointers and sort those. @@ -10772,12 +10777,32 @@ void OverloadCandidateSet::NoteCandidates( llvm::stable_sort( Cands, CompareOverloadCandidatesForDisplay(S, OpLoc, Args.size(), Kind)); + return Cands; +} + +/// When overload resolution fails, prints diagnostic messages containing the +/// candidates in the candidate set. +void OverloadCandidateSet::NoteCandidates(PartialDiagnosticAt PD, + Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args, + StringRef Opc, SourceLocation OpLoc, + llvm::function_ref<bool(OverloadCandidate &)> Filter) { + + auto Cands = CompleteCandidates(S, OCD, Args, OpLoc, Filter); + + S.Diag(PD.first, PD.second); + + NoteCandidates(S, Args, Cands, Opc, OpLoc); +} + +void OverloadCandidateSet::NoteCandidates(Sema &S, ArrayRef<Expr *> Args, + ArrayRef<OverloadCandidate *> Cands, + StringRef Opc, SourceLocation OpLoc) { bool ReportedAmbiguousConversions = false; - SmallVectorImpl<OverloadCandidate*>::iterator I, E; const OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); unsigned CandsShown = 0; - for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { + auto I = Cands.begin(), E = Cands.end(); + for (; I != E; ++I) { OverloadCandidate *Cand = *I; // Set an arbitrary limit on the number of candidate functions we'll spam @@ -12096,22 +12121,29 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, } } - SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_no_viable_function_in_call) - << ULE->getName() << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); + CandidateSet->NoteCandidates( + PartialDiagnosticAt( + Fn->getBeginLoc(), + SemaRef.PDiag(diag::err_ovl_no_viable_function_in_call) + << ULE->getName() << Fn->getSourceRange()), + SemaRef, OCD_AllCandidates, Args); break; } case OR_Ambiguous: - SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_ambiguous_call) - << ULE->getName() << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_ViableCandidates, Args); + CandidateSet->NoteCandidates( + PartialDiagnosticAt(Fn->getBeginLoc(), + SemaRef.PDiag(diag::err_ovl_ambiguous_call) + << ULE->getName() << Fn->getSourceRange()), + SemaRef, OCD_ViableCandidates, Args); break; case OR_Deleted: { - SemaRef.Diag(Fn->getBeginLoc(), diag::err_ovl_deleted_call) - << ULE->getName() << Fn->getSourceRange(); - CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); + CandidateSet->NoteCandidates( + PartialDiagnosticAt(Fn->getBeginLoc(), + SemaRef.PDiag(diag::err_ovl_deleted_call) + << ULE->getName() << Fn->getSourceRange()), + SemaRef, OCD_AllCandidates, Args); // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. @@ -12345,19 +12377,22 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, break; case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) - << UnaryOperator::getOpcodeStr(Opc) - << Input->getType() - << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, ArgsArray, - UnaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, + PDiag(diag::err_ovl_ambiguous_oper_unary) + << UnaryOperator::getOpcodeStr(Opc) + << Input->getType() << Input->getSourceRange()), + *this, OCD_ViableCandidates, ArgsArray, + UnaryOperator::getOpcodeStr(Opc), OpLoc); return ExprError(); case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) - << UnaryOperator::getOpcodeStr(Opc) << Input->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, ArgsArray, - UnaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) + << UnaryOperator::getOpcodeStr(Opc) + << Input->getSourceRange()), + *this, OCD_AllCandidates, ArgsArray, UnaryOperator::getOpcodeStr(Opc), + OpLoc); return ExprError(); } @@ -12591,6 +12626,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // operator do not fall through to handling in built-in, but report that // no overloaded assignment operator found ExprResult Result = ExprError(); + StringRef OpcStr = BinaryOperator::getOpcodeStr(Opc); + auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, + Args, OpLoc); if (Args[0]->getType()->isRecordType() && Opc >= BO_Assign && Opc <= BO_OrAssign) { Diag(OpLoc, diag::err_ovl_no_viable_oper) @@ -12615,19 +12653,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); - if (Result.isInvalid()) - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, - BinaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates(*this, Args, Cands, OpcStr, OpLoc); return Result; } case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary) - << BinaryOperator::getOpcodeStr(Opc) - << Args[0]->getType() << Args[1]->getType() - << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, - BinaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_binary) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getType() + << Args[1]->getType() + << Args[0]->getSourceRange() + << Args[1]->getSourceRange()), + *this, OCD_ViableCandidates, Args, BinaryOperator::getOpcodeStr(Opc), + OpLoc); return ExprError(); case OR_Deleted: @@ -12641,13 +12680,14 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // explain why it's deleted. NoteDeletedFunction(Method); return ExprError(); - } else { - Diag(OpLoc, diag::err_ovl_deleted_oper) - << BinaryOperator::getOpcodeStr(Opc) << Args[0]->getSourceRange() - << Args[1]->getSourceRange(); } - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, - BinaryOperator::getOpcodeStr(Opc), OpLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) + << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getSourceRange() + << Args[1]->getSourceRange()), + *this, OCD_AllCandidates, Args, BinaryOperator::getOpcodeStr(Opc), + OpLoc); return ExprError(); } @@ -12789,32 +12829,34 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, } case OR_No_Viable_Function: { - if (CandidateSet.empty()) - Diag(LLoc, diag::err_ovl_no_oper) - << Args[0]->getType() << /*subscript*/ 0 - << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - else - Diag(LLoc, diag::err_ovl_no_viable_subscript) - << Args[0]->getType() - << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, - "[]", LLoc); + PartialDiagnostic PD = CandidateSet.empty() + ? (PDiag(diag::err_ovl_no_oper) + << Args[0]->getType() << /*subscript*/ 0 + << Args[0]->getSourceRange() << Args[1]->getSourceRange()) + : (PDiag(diag::err_ovl_no_viable_subscript) + << Args[0]->getType() << Args[0]->getSourceRange() + << Args[1]->getSourceRange()); + CandidateSet.NoteCandidates(PartialDiagnosticAt(LLoc, PD), *this, + OCD_AllCandidates, Args, "[]", LLoc); return ExprError(); } case OR_Ambiguous: - Diag(LLoc, diag::err_ovl_ambiguous_oper_binary) - << "[]" - << Args[0]->getType() << Args[1]->getType() - << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, - "[]", LLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(LLoc, PDiag(diag::err_ovl_ambiguous_oper_binary) + << "[]" << Args[0]->getType() + << Args[1]->getType() + << Args[0]->getSourceRange() + << Args[1]->getSourceRange()), + *this, OCD_ViableCandidates, Args, "[]", LLoc); return ExprError(); case OR_Deleted: - Diag(LLoc, diag::err_ovl_deleted_oper) - << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, "[]", LLoc); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(LLoc, PDiag(diag::err_ovl_deleted_oper) + << "[]" << Args[0]->getSourceRange() + << Args[1]->getSourceRange()), + *this, OCD_AllCandidates, Args, "[]", LLoc); return ExprError(); } @@ -12983,24 +13025,30 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, break; case OR_No_Viable_Function: - Diag(UnresExpr->getMemberLoc(), - diag::err_ovl_no_viable_member_function_in_call) - << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt( + UnresExpr->getMemberLoc(), + PDiag(diag::err_ovl_no_viable_member_function_in_call) + << DeclName << MemExprE->getSourceRange()), + *this, OCD_AllCandidates, Args); // FIXME: Leaking incoming expressions! return ExprError(); case OR_Ambiguous: - Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call) - << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(UnresExpr->getMemberLoc(), + PDiag(diag::err_ovl_ambiguous_member_call) + << DeclName << MemExprE->getSourceRange()), + *this, OCD_AllCandidates, Args); // FIXME: Leaking incoming expressions! return ExprError(); case OR_Deleted: - Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call) - << DeclName << MemExprE->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(UnresExpr->getMemberLoc(), + PDiag(diag::err_ovl_deleted_member_call) + << DeclName << MemExprE->getSourceRange()), + *this, OCD_AllCandidates, Args); // FIXME: Leaking incoming expressions! return ExprError(); } @@ -13204,27 +13252,35 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, // below. break; - case OR_No_Viable_Function: - if (CandidateSet.empty()) - Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_oper) - << Object.get()->getType() << /*call*/ 1 - << Object.get()->getSourceRange(); - else - Diag(Object.get()->getBeginLoc(), diag::err_ovl_no_viable_object_call) - << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + case OR_No_Viable_Function: { + PartialDiagnostic PD = + CandidateSet.empty() + ? (PDiag(diag::err_ovl_no_oper) + << Object.get()->getType() << /*call*/ 1 + << Object.get()->getSourceRange()) + : (PDiag(diag::err_ovl_no_viable_object_call) + << Object.get()->getType() << Object.get()->getSourceRange()); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Object.get()->getBeginLoc(), PD), *this, + OCD_AllCandidates, Args); break; - + } case OR_Ambiguous: - Diag(Object.get()->getBeginLoc(), diag::err_ovl_ambiguous_object_call) - << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Object.get()->getBeginLoc(), + PDiag(diag::err_ovl_ambiguous_object_call) + << Object.get()->getType() + << Object.get()->getSourceRange()), + *this, OCD_ViableCandidates, Args); break; case OR_Deleted: - Diag(Object.get()->getBeginLoc(), diag::err_ovl_deleted_object_call) - << Object.get()->getType() << Object.get()->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Object.get()->getBeginLoc(), + PDiag(diag::err_ovl_deleted_object_call) + << Object.get()->getType() + << Object.get()->getSourceRange()), + *this, OCD_AllCandidates, Args); break; } @@ -13423,7 +13479,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, // Overload resolution succeeded; we'll build the call below. break; - case OR_No_Viable_Function: + case OR_No_Viable_Function: { + auto Cands = CandidateSet.CompleteCandidates(*this, OCD_AllCandidates, Base); if (CandidateSet.empty()) { QualType BaseType = Base->getType(); if (NoArrowOperatorFound) { @@ -13441,18 +13498,22 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, } else Diag(OpLoc, diag::err_ovl_no_viable_oper) << "operator->" << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); + CandidateSet.NoteCandidates(*this, Base, Cands); return ExprError(); - + } case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) - << "->" << Base->getType() << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Base); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_ambiguous_oper_unary) + << "->" << Base->getType() + << Base->getSourceRange()), + *this, OCD_ViableCandidates, Base); return ExprError(); case OR_Deleted: - Diag(OpLoc, diag::err_ovl_deleted_oper) << "->" << Base->getSourceRange(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Base); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(OpLoc, PDiag(diag::err_ovl_deleted_oper) + << "->" << Base->getSourceRange()), + *this, OCD_AllCandidates, Base); return ExprError(); } @@ -13514,14 +13575,18 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, break; case OR_No_Viable_Function: - Diag(UDSuffixLoc, diag::err_ovl_no_viable_function_in_call) - << R.getLookupName(); - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(UDSuffixLoc, + PDiag(diag::err_ovl_no_viable_function_in_call) + << R.getLookupName()), + *this, OCD_AllCandidates, Args); return ExprError(); case OR_Ambiguous: - Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); - CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(R.getNameLoc(), PDiag(diag::err_ovl_ambiguous_call) + << R.getLookupName()), + *this, OCD_ViableCandidates, Args); return ExprError(); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 34a769b2519..fe0cf744964 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2227,9 +2227,11 @@ BuildNonArrayForRange(Sema &SemaRef, Expr *BeginRange, Expr *EndRange, return Sema::FRS_Success; case Sema::FRS_NoViableFunction: - SemaRef.Diag(BeginRange->getBeginLoc(), diag::err_for_range_invalid) - << BeginRange->getType() << BEFFound; - CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, BeginRange); + CandidateSet->NoteCandidates( + PartialDiagnosticAt(BeginRange->getBeginLoc(), + SemaRef.PDiag(diag::err_for_range_invalid) + << BeginRange->getType() << BEFFound), + SemaRef, OCD_AllCandidates, BeginRange); LLVM_FALLTHROUGH; case Sema::FRS_DiagnosticIssued: @@ -2526,9 +2528,12 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, // Otherwise, emit diagnostics if we haven't already. if (RangeStatus == FRS_NoViableFunction) { Expr *Range = BEFFailure ? EndRangeRef.get() : BeginRangeRef.get(); - Diag(Range->getBeginLoc(), diag::err_for_range_invalid) - << RangeLoc << Range->getType() << BEFFailure; - CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Range); + CandidateSet.NoteCandidates( + PartialDiagnosticAt(Range->getBeginLoc(), + PDiag(diag::err_for_range_invalid) + << RangeLoc << Range->getType() + << BEFFailure), + *this, OCD_AllCandidates, Range); } // Return an error if no fix was discovered. if (RangeStatus != FRS_Success) |