When printing an overload candidate that failed due to SFINAE, print a

specific message that includes the template arguments, e.g.,

test/SemaTemplate/overload-candidates.cpp:27:20: note: candidate template
      ignored: substitution failure [with T = int *]
  typename T::type get_type(const T&); // expected-note{{candidate ...
                   ^

llvm-svn: 103348
This commit is contained in:
Douglas Gregor 2010-05-08 20:07:26 +00:00
parent 5a62d6e578
commit d09efd43d3
6 changed files with 82 additions and 15 deletions

View File

@ -1069,6 +1069,11 @@ def note_ovl_candidate_explicit_arg_mismatch_named : Note<
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note< def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
"candidate template ignored: invalid explicitly-specified argument " "candidate template ignored: invalid explicitly-specified argument "
"for %ordinal0 template parameter">; "for %ordinal0 template parameter">;
def note_ovl_candidate_instantiation_depth : Note<
"candidate template ignored: substitution exceeded maximum template "
"instantiation depth">;
def note_ovl_candidate_substitution_failure : Note<
"candidate template ignored: substitution failure %0">;
// Note that we don't treat templates differently for this diagnostic. // Note that we don't treat templates differently for this diagnostic.
def note_ovl_candidate_arity : Note<"candidate " def note_ovl_candidate_arity : Note<"candidate "

View File

@ -289,7 +289,7 @@ namespace {
/// to the form used in overload-candidate information. /// to the form used in overload-candidate information.
OverloadCandidate::DeductionFailureInfo OverloadCandidate::DeductionFailureInfo
static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK, static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
const Sema::TemplateDeductionInfo &Info) { Sema::TemplateDeductionInfo &Info) {
OverloadCandidate::DeductionFailureInfo Result; OverloadCandidate::DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK); Result.Result = static_cast<unsigned>(TDK);
Result.Data = 0; Result.Data = 0;
@ -316,6 +316,9 @@ static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
} }
case Sema::TDK_SubstitutionFailure: case Sema::TDK_SubstitutionFailure:
Result.Data = Info.take();
break;
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
break; break;
@ -340,8 +343,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
Data = 0; Data = 0;
break; break;
// Unhandled
case Sema::TDK_SubstitutionFailure: case Sema::TDK_SubstitutionFailure:
// FIXME: Destroy the template arugment list?
Data = 0;
break;
// Unhandled
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
break; break;
@ -355,6 +362,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_InstantiationDepth: case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments: case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments: case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
return TemplateParameter(); return TemplateParameter();
case Sema::TDK_Incomplete: case Sema::TDK_Incomplete:
@ -366,7 +374,6 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return static_cast<DFIParamWithArguments*>(Data)->Param; return static_cast<DFIParamWithArguments*>(Data)->Param;
// Unhandled // Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
break; break;
@ -375,6 +382,31 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return TemplateParameter(); return TemplateParameter();
} }
TemplateArgumentList *
OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_Incomplete:
case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_Inconsistent:
case Sema::TDK_InconsistentQuals:
return 0;
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
// Unhandled
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
}
return 0;
}
const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) { switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success: case Sema::TDK_Success:
@ -383,6 +415,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
case Sema::TDK_TooManyArguments: case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments: case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
return 0; return 0;
case Sema::TDK_Inconsistent: case Sema::TDK_Inconsistent:
@ -390,7 +423,6 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
// Unhandled // Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
break; break;
@ -408,6 +440,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
case Sema::TDK_TooManyArguments: case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments: case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_InvalidExplicitArguments:
case Sema::TDK_SubstitutionFailure:
return 0; return 0;
case Sema::TDK_Inconsistent: case Sema::TDK_Inconsistent:
@ -415,7 +448,6 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
return &static_cast<DFIParamWithArguments*>(Data)->SecondArg; return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
// Unhandled // Unhandled
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
break; break;
@ -5152,10 +5184,24 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
DiagnoseArityMismatch(S, Cand, NumArgs); DiagnoseArityMismatch(S, Cand, NumArgs);
return; return;
case Sema::TDK_InstantiationDepth:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth);
return;
case Sema::TDK_SubstitutionFailure: {
std::string ArgString;
if (TemplateArgumentList *Args
= Cand->DeductionFailure.getTemplateArgumentList())
ArgString = S.getTemplateArgumentBindingsText(
Fn->getDescribedFunctionTemplate()->getTemplateParameters(),
*Args);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure)
<< ArgString;
return;
}
// TODO: diagnose these individually, then kill off // TODO: diagnose these individually, then kill off
// note_ovl_candidate_bad_deduction, which is uselessly vague. // note_ovl_candidate_bad_deduction, which is uselessly vague.
case Sema::TDK_InstantiationDepth:
case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch: case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution: case Sema::TDK_FailedOverloadResolution:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);

View File

@ -539,6 +539,10 @@ namespace clang {
/// refers to, if any. /// refers to, if any.
TemplateParameter getTemplateParameter(); TemplateParameter getTemplateParameter();
/// \brief Retrieve the template argument list associated with this
/// deduction failure, if any.
TemplateArgumentList *getTemplateArgumentList();
/// \brief Return the first template argument this deduction failure /// \brief Return the first template argument this deduction failure
/// refers to, if any. /// refers to, if any.
const TemplateArgument *getFirstArg(); const TemplateArgument *getFirstArg();

View File

@ -1030,10 +1030,8 @@ FinishTemplateArgumentDeduction(Sema &S,
ClassTemplate->getTemplateParameters(), N); ClassTemplate->getTemplateParameters(), N);
if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
InstArgs, false, ConvertedInstArgs)) { InstArgs, false, ConvertedInstArgs))
// FIXME: fail with more useful information?
return Sema::TDK_SubstitutionFailure; return Sema::TDK_SubstitutionFailure;
}
for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) { for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I]; TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
@ -1377,6 +1375,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
NTTP->getDeclName()); NTTP->getDeclName());
if (NTTPType.isNull()) { if (NTTPType.isNull()) {
Info.Param = makeTemplateParameter(Param); Info.Param = makeTemplateParameter(Param);
Info.reset(new (Context) TemplateArgumentList(Context, Builder,
/*TakeArgs=*/true));
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
} }
} }
@ -1402,6 +1402,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
: CTAK_Deduced)) { : CTAK_Deduced)) {
Info.Param = makeTemplateParameter( Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I))); const_cast<NamedDecl *>(TemplateParams->getParam(I)));
Info.reset(new (Context) TemplateArgumentList(Context, Builder,
/*TakeArgs=*/true));
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
} }
@ -1432,6 +1434,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
CTAK_Deduced)) { CTAK_Deduced)) {
Info.Param = makeTemplateParameter( Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I))); const_cast<NamedDecl *>(TemplateParams->getParam(I)));
Info.reset(new (Context) TemplateArgumentList(Context, Builder,
/*TakeArgs=*/true));
return TDK_SubstitutionFailure; return TDK_SubstitutionFailure;
} }
@ -1459,7 +1463,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// If the template argument list is owned by the function template // If the template argument list is owned by the function template
// specialization, release it. // specialization, release it.
if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList) if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
!Trap.hasErrorOccurred())
Info.take(); Info.take();
// There may have been an error that did not prevent us from constructing a // There may have been an error that did not prevent us from constructing a

View File

@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify %s
template<int i> class A { }; template<int i> class A { };
template<short s> void f(A<s>); // expected-note{{failed template argument deduction}} template<short s> void f(A<s>); // expected-note{{candidate template ignored: substitution failure}}
void k1() { void k1() {
A<1> a; A<1> a;
@ -22,7 +22,7 @@ void k3() {
h<5>(array); h<5>(array);
} }
template<short s> void h(int (&)[s], A<s>); // expected-note{{failed template argument deduction}} template<short s> void h(int (&)[s], A<s>); // expected-note{{candidate template ignored: substitution failure}}
void k4() { void k4() {
A<5> a; A<5> a;
int array[5]; int array[5];

View File

@ -22,3 +22,10 @@ template<template<class T> class, typename T>
void test_get(void *ptr) { void test_get(void *ptr) {
get<int>(ptr); // expected-error{{no matching function for call to 'get'}} get<int>(ptr); // expected-error{{no matching function for call to 'get'}}
} }
template<typename T>
typename T::type get_type(const T&); // expected-note{{candidate template ignored: substitution failure [with T = int *]}}
void test_get_type(int *ptr) {
(void)get_type(ptr); // expected-error{{no matching function for call to 'get_type'}}
}