Index: include/clang/AST/TemplateName.h =================================================================== --- include/clang/AST/TemplateName.h +++ include/clang/AST/TemplateName.h @@ -31,6 +31,7 @@ class NestedNameSpecifier; enum OverloadedOperatorKind : int; class OverloadedTemplateStorage; +class PartialDiagnostic; struct PrintingPolicy; class QualifiedTemplateName; class SubstTemplateTemplateParmPackStorage; @@ -319,6 +320,8 @@ /// into a diagnostic with <<. const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, TemplateName N); +const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + TemplateName N); /// A structure for storing the information associated with a /// substituted template template parameter. Index: include/clang/Basic/PartialDiagnostic.h =================================================================== --- include/clang/Basic/PartialDiagnostic.h +++ include/clang/Basic/PartialDiagnostic.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/SmallVector.h" Index: include/clang/Sema/Overload.h =================================================================== --- include/clang/Sema/Overload.h +++ include/clang/Sema/Overload.h @@ -961,13 +961,23 @@ OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, OverloadCandidateSet::iterator& Best); - void NoteCandidates(Sema &S, - OverloadCandidateDisplayKind OCD, - ArrayRef Args, + SmallVector CompleteCandidates( + Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef Args, + SourceLocation OpLoc = SourceLocation(), + llvm::function_ref Filter = + [](OverloadCandidate &) { return true; }); + + void NoteCandidates( + PartialDiagnosticAt PA, Sema &S, OverloadCandidateDisplayKind OCD, + ArrayRef Args, StringRef Opc = "", + SourceLocation Loc = SourceLocation(), + llvm::function_ref Filter = + [](OverloadCandidate &) { return true; }); + + void NoteCandidates(Sema &S, ArrayRef Args, + ArrayRef Cands, StringRef Opc = "", - SourceLocation Loc = SourceLocation(), - llvm::function_ref Filter = - [](OverloadCandidate&) { return true; }); + SourceLocation OpLoc = SourceLocation()); }; bool isBetterOverloadCandidate(Sema &S, Index: lib/AST/TemplateName.cpp =================================================================== --- lib/AST/TemplateName.cpp +++ lib/AST/TemplateName.cpp @@ -250,6 +250,20 @@ 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; Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -399,11 +399,11 @@ 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; } Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -2301,8 +2301,8 @@ } 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 @@ // 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 @@ } 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; } } Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -5971,21 +5971,25 @@ 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 @@ 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 @@ 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 @@ << 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 @@ // 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 @@ 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 @@ 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 @@ cast(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(); } Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -3505,18 +3505,25 @@ 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 @@ } } -/// When overload resolution fails, prints diagnostic messages containing the -/// candidates in the candidate set. -void OverloadCandidateSet::NoteCandidates( +SmallVector OverloadCandidateSet::CompleteCandidates( Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef Args, - StringRef Opc, SourceLocation OpLoc, + SourceLocation OpLoc, llvm::function_ref 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 @@ 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 Args, + StringRef Opc, SourceLocation OpLoc, + llvm::function_ref 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 Args, + ArrayRef Cands, + StringRef Opc, SourceLocation OpLoc) { bool ReportedAmbiguousConversions = false; - SmallVectorImpl::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 @@ } } - 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 @@ 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 @@ // 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 @@ } 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 @@ // 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 @@ } 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 @@ 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 @@ // 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 @@ // 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 @@ } 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 @@ 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(); } Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -2227,9 +2227,11 @@ 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 @@ // 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) Index: test/SemaCXX/overload-template.cpp =================================================================== --- test/SemaCXX/overload-template.cpp +++ test/SemaCXX/overload-template.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +enum copy_traits { movable = 1 }; + +template +struct optional_ctor_base {}; +template +struct ctor_copy_traits { + // this would produce a c++98-compat warning, which would erroneously get the + // no-matching-function-call error's notes attached to it (or suppress those + // notes if this diagnostic was suppressed, as it is in this case) + static constexpr int traits = copy_traits::movable; +}; +template +struct optional : optional_ctor_base::traits> { + template + constexpr optional(U&& v); +}; +struct A {}; +struct XA { + XA(const A&); +}; +struct B {}; +struct XB { + XB(const B&); + XB(const optional&); +}; +struct YB : XB { + using XB::XB; +}; +void InsertRow(const XA&, const YB&); // expected-note {{candidate function not viable: no known conversion from 'int' to 'const XA' for 1st argument}} +void ReproducesBugSimply() { + InsertRow(3, B{}); // expected-error {{no matching function for call to 'InsertRow'}} +} +