forked from OSchip/llvm-project
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:
parent
5a62d6e578
commit
d09efd43d3
|
@ -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 "
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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'}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue