Improve overload-candidate diagnostic for a function template that

failed because the explicitly-specified template arguments did not
match its template parameters, e.g.,

test/SemaTemplate/overload-candidates.cpp:18:8: note: candidate
template
      ignored: invalid explicitly-specified argument for template
      parameter 'I'
  void get(const T&);
       ^
test/SemaTemplate/overload-candidates.cpp:20:8: note: candidate
template
      ignored: invalid explicitly-specified argument for 1st template
      parameter
  void get(const T&);
       ^

llvm-svn: 103344
This commit is contained in:
Douglas Gregor 2010-05-08 19:15:54 +00:00
parent 564767cf39
commit 1d72edd7c5
4 changed files with 66 additions and 16 deletions

View File

@ -1063,7 +1063,13 @@ def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored:
def note_ovl_candidate_inconsistent_deduction : Note<
"candidate template ignored: deduced conflicting %select{types|values|"
"templates}0 for parameter %1 (%2 vs. %3)">;
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for template parameter %0">;
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
"candidate template ignored: invalid explicitly-specified argument "
"for %ordinal0 template parameter">;
// Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate "
"%select{function|function|constructor|function|function|constructor|"

View File

@ -301,6 +301,7 @@ static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
break;
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
Result.Data = Info.Param.getOpaqueValue();
break;
@ -316,7 +317,6 @@ static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
break;
}
@ -331,6 +331,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
case Sema::TDK_Incomplete:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
break;
case Sema::TDK_Inconsistent:
@ -342,7 +343,6 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
// Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
break;
}
@ -358,6 +358,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return TemplateParameter();
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
return TemplateParameter::getFromOpaqueValue(Data);
case Sema::TDK_Inconsistent:
@ -367,7 +368,6 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
// Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
break;
}
@ -382,6 +382,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
case Sema::TDK_Incomplete:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
return 0;
case Sema::TDK_Inconsistent:
@ -391,7 +392,6 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
// Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
break;
}
@ -407,6 +407,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Incomplete:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
return 0;
case Sema::TDK_Inconsistent:
@ -416,7 +417,6 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
// Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
break;
}
@ -425,6 +425,12 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
}
void OverloadCandidateSet::clear() {
//
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
if (C->FailureKind == ovl_fail_bad_deduction)
C->DeductionFailure.Destroy();
}
inherited::clear();
Functions.clear();
}
@ -5086,15 +5092,15 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
FunctionDecl *Fn = Cand->Function; // pattern
TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter();
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
switch (Cand->DeductionFailure.Result) {
case Sema::TDK_Success:
llvm_unreachable("TDK_success while diagnosing bad deduction");
case Sema::TDK_Incomplete: {
NamedDecl *ParamD;
(ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) ||
(ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) ||
(ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>());
assert(ParamD && "no parameter found for incomplete deduction result");
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction)
<< ParamD->getDeclName();
@ -5103,14 +5109,13 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
case Sema::TDK_Inconsistent:
case Sema::TDK_InconsistentQuals: {
NamedDecl *ParamD;
assert(ParamD && "no parameter found for inconsistent deduction result");
int which = 0;
if ((ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()))
if (isa<TemplateTypeParmDecl>(ParamD))
which = 0;
else if ((ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()))
else if (isa<NonTypeTemplateParmDecl>(ParamD))
which = 1;
else {
ParamD = Param.get<TemplateTemplateParmDecl*>();
which = 2;
}
@ -5121,6 +5126,27 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
return;
}
case Sema::TDK_InvalidExplicitArguments:
assert(ParamD && "no parameter found for invalid explicit arguments");
if (ParamD->getDeclName())
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
<< ParamD->getDeclName();
else {
int index = 0;
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
index = TTP->getIndex();
else if (NonTypeTemplateParmDecl *NTTP
= dyn_cast<NonTypeTemplateParmDecl>(ParamD))
index = NTTP->getIndex();
else
index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
S.Diag(Fn->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
<< (index + 1);
}
return;
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Cand, NumArgs);
@ -5131,7 +5157,6 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
case Sema::TDK_InstantiationDepth:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_FailedOverloadResolution:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
return;

View File

@ -1190,8 +1190,11 @@ Sema::SubstituteExplicitTemplateArguments(
SourceLocation(),
ExplicitTemplateArgs,
true,
Builder) || Trap.hasErrorOccurred())
Builder) || Trap.hasErrorOccurred()) {
Info.Param = makeTemplateParameter(TemplateParams->getParam(
Builder.structuredSize()));
return TDK_InvalidExplicitArguments;
}
// Form the template argument list from the explicitly-specified
// template arguments.

View File

@ -6,3 +6,19 @@ const T& min(const T&, const T&); // expected-note{{candidate template ignored:
void test_min() {
(void)min(1, 2l); // expected-error{{no matching function for call to 'min'}}
}
template<typename R, typename T>
R *dyn_cast(const T&); // expected-note{{candidate template ignored: couldn't infer template argument 'R'}}
void test_dyn_cast(int* ptr) {
(void)dyn_cast(ptr); // expected-error{{no matching function for call to 'dyn_cast'}}
}
template<int I, typename T>
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for template parameter 'I'}}
template<template<class T> class, typename T>
void get(const T&); // expected-note{{candidate template ignored: invalid explicitly-specified argument for 1st template parameter}}
void test_get(void *ptr) {
get<int>(ptr); // expected-error{{no matching function for call to 'get'}}
}