}
namespace {
- // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // Structure used by DeductionFailureInfo to store
// template argument information.
struct DFIArguments {
TemplateArgument FirstArg;
TemplateArgument SecondArg;
};
- // Structure used by OverloadCandidate::DeductionFailureInfo to store
+ // Structure used by DeductionFailureInfo to store
// template parameter and template argument information.
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
/// \brief Convert from Sema's representation of template deduction information
/// to the form used in overload-candidate information.
-OverloadCandidate::DeductionFailureInfo
-static MakeDeductionFailureInfo(ASTContext &Context,
- Sema::TemplateDeductionResult TDK,
- TemplateDeductionInfo &Info) {
- OverloadCandidate::DeductionFailureInfo Result;
+DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context,
+ Sema::TemplateDeductionResult TDK,
+ TemplateDeductionInfo &Info) {
+ DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
Result.Data = 0;
return Result;
}
-void OverloadCandidate::DeductionFailureInfo::Destroy() {
+void DeductionFailureInfo::Destroy() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
}
}
-PartialDiagnosticAt *
-OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() {
+PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() {
if (HasDiagnostic)
return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic));
return 0;
}
-TemplateParameter
-OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
+TemplateParameter DeductionFailureInfo::getTemplateParameter() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
return TemplateParameter();
}
-TemplateArgumentList *
-OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
+TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
return 0;
}
-const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
+const TemplateArgument *DeductionFailureInfo::getFirstArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
return 0;
}
-const TemplateArgument *
-OverloadCandidate::DeductionFailureInfo::getSecondArg() {
+const TemplateArgument *DeductionFailureInfo::getSecondArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
return 0;
}
-Expr *
-OverloadCandidate::DeductionFailureInfo::getExpr() {
+Expr *DeductionFailureInfo::getExpr() {
if (static_cast<Sema::TemplateDeductionResult>(Result) ==
Sema::TDK_FailedOverloadResolution)
return static_cast<Expr*>(Data);
return isTemplate ? oc_function_template : oc_function;
}
-void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) {
+void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) {
const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn);
if (!Ctor) return;
MaybeEmitInheritedConstructorNote(S, Fn);
}
-void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
- unsigned NumFormalArgs) {
- // TODO: treat calls to a missing default constructor as a special case
-
+/// Additional arity mismatch diagnosis specific to a function overload
+/// candidates. This is not covered by the more general DiagnoseArityMismatch()
+/// over a candidate in any candidate set.
+bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumArgs) {
FunctionDecl *Fn = Cand->Function;
- const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
-
unsigned MinParams = Fn->getMinRequiredArguments();
// With invalid overloaded operators, it's possible that we think we
- // have an arity mismatch when it fact it looks like we have the
+ // have an arity mismatch when in fact it looks like we have the
// right number of arguments, because only overloaded operators have
// the weird behavior of overloading member and non-member functions.
// Just don't report anything.
if (Fn->isInvalidDecl() &&
Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
- return;
+ return true;
- // at least / at most / exactly
- unsigned mode, modeCount;
- if (NumFormalArgs < MinParams) {
+ if (NumArgs < MinParams) {
assert((Cand->FailureKind == ovl_fail_too_few_arguments) ||
(Cand->FailureKind == ovl_fail_bad_deduction &&
Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments));
+ } else {
+ assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
+ (Cand->FailureKind == ovl_fail_bad_deduction &&
+ Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
+ }
+
+ return false;
+}
+
+/// General arity mismatch diagnosis over a candidate in a candidate set.
+void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
+ assert(isa<FunctionDecl>(D) &&
+ "The templated declaration should at least be a function"
+ " when diagnosing bad template argument deduction due to too many"
+ " or too few arguments");
+
+ FunctionDecl *Fn = cast<FunctionDecl>(D);
+
+ // TODO: treat calls to a missing default constructor as a special case
+ const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>();
+ unsigned MinParams = Fn->getMinRequiredArguments();
+
+ // at least / at most / exactly
+ unsigned mode, modeCount;
+ if (NumFormalArgs < MinParams) {
if (MinParams != FnTy->getNumArgs() ||
FnTy->isVariadic() || FnTy->isTemplateVariadic())
mode = 0; // "at least"
mode = 2; // "exactly"
modeCount = MinParams;
} else {
- assert((Cand->FailureKind == ovl_fail_too_many_arguments) ||
- (Cand->FailureKind == ovl_fail_bad_deduction &&
- Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments));
if (MinParams != FnTy->getNumArgs())
mode = 1; // "at most"
else
MaybeEmitInheritedConstructorNote(S, Fn);
}
+/// Arity mismatch diagnosis specific to a function overload candidate.
+void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
+ unsigned NumFormalArgs) {
+ if (!CheckArityMismatch(S, Cand, NumFormalArgs))
+ DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
+}
+
+TemplateDecl *getDescribedTemplate(Decl *Templated) {
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
+ return FD->getDescribedFunctionTemplate();
+ else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
+ return RD->getDescribedClassTemplate();
+
+ llvm_unreachable("Unsupported: Getting the described template declaration"
+ " for bad deduction diagnosis");
+}
+
/// Diagnose a failed template-argument deduction.
-void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
+void DiagnoseBadDeduction(Sema &S, Decl *Templated,
+ DeductionFailureInfo &DeductionFailure,
unsigned NumArgs) {
- FunctionDecl *Fn = Cand->Function; // pattern
-
- TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
+ TemplateParameter Param = DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
- switch (Cand->DeductionFailure.Result) {
+ switch (DeductionFailure.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Incomplete: {
assert(ParamD && "no parameter found for incomplete deduction result");
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
- << ParamD->getDeclName();
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_incomplete_deduction)
+ << ParamD->getDeclName();
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
assert(ParamD && "no parameter found for bad qualifiers deduction result");
TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD);
- QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType();
+ QualType Param = DeductionFailure.getFirstArg()->getAsType();
// Param will have been canonicalized, but it should just be a
// qualified version of ParamD, so move the qualifiers to that.
// about that. It also doesn't matter as much, because it won't
// have any template parameters in it (because deduction isn't
// done on dependent types).
- QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType();
+ QualType Arg = DeductionFailure.getSecondArg()->getAsType();
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified)
- << ParamD->getDeclName() << Arg << NonCanonParam;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified)
+ << ParamD->getDeclName() << Arg << NonCanonParam;
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
which = 2;
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction)
- << which << ParamD->getDeclName()
- << *Cand->DeductionFailure.getFirstArg()
- << *Cand->DeductionFailure.getSecondArg();
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_inconsistent_deduction)
+ << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg()
+ << *DeductionFailure.getSecondArg();
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
case Sema::TDK_InvalidExplicitArguments:
assert(ParamD && "no parameter found for invalid explicit arguments");
if (ParamD->getDeclName())
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
- << ParamD->getDeclName();
+ << ParamD->getDeclName();
else {
int index = 0;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
index = NTTP->getIndex();
else
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
- << (index + 1);
+ << (index + 1);
}
- MaybeEmitInheritedConstructorNote(S, Fn);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
- DiagnoseArityMismatch(S, Cand, NumArgs);
+ DiagnoseArityMismatch(S, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_instantiation_depth);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
case Sema::TDK_SubstitutionFailure: {
// Format the template argument list into the argument string.
SmallString<128> TemplateArgString;
if (TemplateArgumentList *Args =
- Cand->DeductionFailure.getTemplateArgumentList()) {
+ DeductionFailure.getTemplateArgumentList()) {
TemplateArgString = " ";
TemplateArgString += S.getTemplateArgumentBindingsText(
- Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args);
+ getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
}
// If this candidate was disabled by enable_if, say so.
- PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic();
+ PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic();
if (PDiag && PDiag->second.getDiagID() ==
diag::err_typename_nested_not_found_enable_if) {
// FIXME: Use the source range of the condition, and the fully-qualified
PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString);
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
- << TemplateArgString << SFINAEArgString << R;
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_substitution_failure)
+ << TemplateArgString << SFINAEArgString << R;
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
case Sema::TDK_FailedOverloadResolution: {
- OverloadExpr::FindResult R =
- OverloadExpr::find(Cand->DeductionFailure.getExpr());
- S.Diag(Fn->getLocation(),
+ OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr());
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_failed_overload_resolution)
- << R.Expression->getName();
+ << R.Expression->getName();
return;
}
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Provide a source location to indicate what we couldn't match.
- TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg();
- TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg();
+ TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
+ TemplateArgument SecondTA = *DeductionFailure.getSecondArg();
if (FirstTA.getKind() == TemplateArgument::Template &&
SecondTA.getKind() == TemplateArgument::Template) {
TemplateName FirstTN = FirstTA.getAsTemplate();
// 2) The diagnostic printer only attempts to find a better
// name for types, not decls.
// Ideally, this should folded into the diagnostic printer.
- S.Diag(Fn->getLocation(),
+ S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_non_deduced_mismatch_qualified)
<< FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl();
return;
}
}
}
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch)
- << FirstTA << SecondTA;
+ S.Diag(Templated->getLocation(),
+ diag::note_ovl_candidate_non_deduced_mismatch)
+ << FirstTA << SecondTA;
return;
}
// TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_MiscellaneousDeductionFailure:
- S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
- MaybeEmitInheritedConstructorNote(S, Fn);
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction);
+ MaybeEmitInheritedConstructorNote(S, Templated);
return;
}
}
+/// Diagnose a failed template-argument deduction, for function calls.
+void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) {
+ unsigned TDK = Cand->DeductionFailure.Result;
+ if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) {
+ if (CheckArityMismatch(S, Cand, NumArgs))
+ return;
+ }
+ DiagnoseBadDeduction(S, Cand->Function, // pattern
+ Cand->DeductionFailure, NumArgs);
+}
+
/// CUDA: diagnose an invalid call across targets.
void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext);
}
}
-SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
+static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) {
if (Cand->Function)
return Cand->Function->getLocation();
if (Cand->IsSurrogate)
return SourceLocation();
}
-static unsigned
-RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) {
+static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
switch ((Sema::TemplateDeductionResult)DFI.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I);
}
+static SourceLocation
+GetLocationForCandidate(const TemplateSpecCandidate *Cand) {
+ return Cand->Specialization ? Cand->Specialization->getLocation()
+ : SourceLocation();
+}
+
+struct CompareTemplateSpecCandidatesForDisplay {
+ Sema &S;
+ CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {}
+
+ bool operator()(const TemplateSpecCandidate *L,
+ const TemplateSpecCandidate *R) {
+ // Fast-path this check.
+ if (L == R)
+ return false;
+
+ // Assuming that both candidates are not matches...
+
+ // Sort by the ranking of deduction failures.
+ if (L->DeductionFailure.Result != R->DeductionFailure.Result)
+ return RankDeductionFailure(L->DeductionFailure) <
+ RankDeductionFailure(R->DeductionFailure);
+
+ // Sort everything else by location.
+ SourceLocation LLoc = GetLocationForCandidate(L);
+ SourceLocation RLoc = GetLocationForCandidate(R);
+
+ // Put candidates without locations (e.g. builtins) at the end.
+ if (LLoc.isInvalid())
+ return false;
+ if (RLoc.isInvalid())
+ return true;
+
+ return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc);
+ }
+};
+
+/// Diagnose a template argument deduction failure.
+/// We are treating these failures as overload failures due to bad
+/// deductions.
+void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) {
+ DiagnoseBadDeduction(S, Specialization, // pattern
+ DeductionFailure, /*NumArgs=*/0);
+}
+
+void TemplateSpecCandidateSet::destroyCandidates() {
+ for (iterator i = begin(), e = end(); i != e; ++i) {
+ i->DeductionFailure.Destroy();
+ }
+}
+
+void TemplateSpecCandidateSet::clear() {
+ destroyCandidates();
+ Candidates.clear();
+}
+
+/// NoteCandidates - When no template specialization match is found, prints
+/// diagnostic messages containing the non-matching specializations that form
+/// the candidate set.
+/// This is analoguous to OverloadCandidateSet::NoteCandidates() with
+/// OCD == OCD_AllCandidates and Cand->Viable == false.
+void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) {
+ // Sort the candidates by position (assuming no candidate is a match).
+ // Sorting directly would be prohibitive, so we make a set of pointers
+ // and sort those.
+ SmallVector<TemplateSpecCandidate *, 32> Cands;
+ Cands.reserve(size());
+ for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) {
+ if (Cand->Specialization)
+ Cands.push_back(Cand);
+ // Otherwise, this is a non matching builtin candidate. We do not,
+ // in general, want to list every possible builtin candidate.
+ }
+
+ std::sort(Cands.begin(), Cands.end(),
+ CompareTemplateSpecCandidatesForDisplay(S));
+
+ // FIXME: Perhaps rename OverloadsShown and getShowOverloads()
+ // for generalization purposes (?).
+ const OverloadsShown ShowOverloads = S.Diags.getShowOverloads();
+
+ SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E;
+ unsigned CandsShown = 0;
+ for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+ TemplateSpecCandidate *Cand = *I;
+
+ // Set an arbitrary limit on the number of candidates we'll spam
+ // the user with. FIXME: This limit should depend on details of the
+ // candidate list.
+ if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
+ break;
+ ++CandsShown;
+
+ assert(Cand->Specialization &&
+ "Non-matching built-in candidates are not added to Cands.");
+ Cand->NoteDeductionFailure(S);
+ }
+
+ if (I != E)
+ S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I);
+}
+
// [PossiblyAFunctionType] --> [Return]
// NonFunctionType --> NonFunctionType
// R (A) --> R(A)
OverloadExpr *OvlExpr;
TemplateArgumentListInfo OvlExplicitTemplateArgs;
SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches;
+ TemplateSpecCandidateSet FailedCandidates;
public:
- AddressOfFunctionResolver(Sema &S, Expr* SourceExpr,
- const QualType& TargetType, bool Complain)
- : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
- Complain(Complain), Context(S.getASTContext()),
- TargetTypeIsNonStaticMemberFunction(
- !!TargetType->getAs<MemberPointerType>()),
- FoundNonTemplateFunction(false),
- OvlExprInfo(OverloadExpr::find(SourceExpr)),
- OvlExpr(OvlExprInfo.Expression)
- {
+ AddressOfFunctionResolver(Sema &S, Expr *SourceExpr,
+ const QualType &TargetType, bool Complain)
+ : S(S), SourceExpr(SourceExpr), TargetType(TargetType),
+ Complain(Complain), Context(S.getASTContext()),
+ TargetTypeIsNonStaticMemberFunction(
+ !!TargetType->getAs<MemberPointerType>()),
+ FoundNonTemplateFunction(false),
+ OvlExprInfo(OverloadExpr::find(SourceExpr)),
+ OvlExpr(OvlExprInfo.Expression),
+ FailedCandidates(OvlExpr->getNameLoc()) {
ExtractUnqualifiedFunctionTypeFromTargetType();
if (!TargetFunctionType->isFunctionType()) {
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(OvlExpr->getNameLoc());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (Sema::TemplateDeductionResult Result
= S.DeduceTemplateArguments(FunctionTemplate,
&OvlExplicitTemplateArgs,
TargetFunctionType, Specialization,
Info, /*InOverloadResolution=*/true)) {
- // FIXME: make a note of the failed deduction for diagnostics.
+ // Make a note of the failed deduction for diagnostics.
+ FailedCandidates.addCandidate()
+ .set(FunctionTemplate->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
return false;
}
for (unsigned I = 0, E = Matches.size(); I != E; ++I)
MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess());
- UnresolvedSetIterator Result =
- S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(),
- TPOC_Other, 0, SourceExpr->getLocStart(),
- S.PDiag(),
- S.PDiag(diag::err_addr_ovl_ambiguous)
- << Matches[0].second->getDeclName(),
- S.PDiag(diag::note_ovl_candidate)
- << (unsigned) oc_function_template,
- Complain, TargetFunctionType);
+ // TODO: It looks like FailedCandidates does not serve much purpose
+ // here, since the no_viable diagnostic has index 0.
+ UnresolvedSetIterator Result = S.getMostSpecialized(
+ MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, TPOC_Other, 0,
+ SourceExpr->getLocStart(), S.PDiag(),
+ S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0]
+ .second->getDeclName(),
+ S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template,
+ Complain, TargetFunctionType);
if (Result != MatchesCopy.end()) {
// Make it the first and only element
S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable)
<< OvlExpr->getName() << TargetFunctionType
<< OvlExpr->getSourceRange();
+ FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType);
}
TemplateArgumentListInfo ExplicitTemplateArgs;
ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc());
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(ovl->getNameLoc());
+ TemplateDeductionInfo Info(FailedCandidates.getLocation());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info,
/*InOverloadResolution=*/true)) {
- // FIXME: make a note of the failed deduction for diagnostics.
+ // Make a note of the failed deduction for diagnostics.
+ // TODO: Actually use the failed-deduction info?
+ FailedCandidates.addCandidate()
+ .set(FunctionTemplate->getTemplatedDecl(),
+ MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
continue;
}