aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--lib/Sema/SemaOverload.cpp62
-rw-r--r--lib/Sema/SemaOverload.h4
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp13
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp4
-rw-r--r--test/SemaTemplate/overload-candidates.cpp7
6 files changed, 82 insertions, 15 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 235ac86a22..95dce63c05 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1069,7 +1069,12 @@ def note_ovl_candidate_explicit_arg_mismatch_named : Note<
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
"candidate template ignored: invalid explicitly-specified argument "
"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.
def note_ovl_candidate_arity : Note<"candidate "
"%select{function|function|constructor|function|function|constructor|"
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index f738236133..b86719e15b 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -289,7 +289,7 @@ namespace {
/// to the form used in overload-candidate information.
OverloadCandidate::DeductionFailureInfo
static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
- const Sema::TemplateDeductionInfo &Info) {
+ Sema::TemplateDeductionInfo &Info) {
OverloadCandidate::DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.Data = 0;
@@ -316,6 +316,9 @@ static MakeDeductionFailureInfo(Sema::TemplateDeductionResult TDK,
}
case Sema::TDK_SubstitutionFailure:
+ Result.Data = Info.take();
+ break;
+
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
@@ -339,9 +342,13 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() {
delete static_cast<DFIParamWithArguments*>(Data);
Data = 0;
break;
+
+ case Sema::TDK_SubstitutionFailure:
+ // FIXME: Destroy the template arugment list?
+ Data = 0;
+ break;
// Unhandled
- case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
@@ -355,6 +362,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
+ case Sema::TDK_SubstitutionFailure:
return TemplateParameter();
case Sema::TDK_Incomplete:
@@ -366,7 +374,6 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
return static_cast<DFIParamWithArguments*>(Data)->Param;
// Unhandled
- case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
@@ -374,7 +381,32 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() {
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() {
switch (static_cast<Sema::TemplateDeductionResult>(Result)) {
case Sema::TDK_Success:
@@ -383,6 +415,7 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_SubstitutionFailure:
return 0;
case Sema::TDK_Inconsistent:
@@ -390,7 +423,6 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() {
return &static_cast<DFIParamWithArguments*>(Data)->FirstArg;
// Unhandled
- case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
@@ -408,6 +440,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_SubstitutionFailure:
return 0;
case Sema::TDK_Inconsistent:
@@ -415,7 +448,6 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() {
return &static_cast<DFIParamWithArguments*>(Data)->SecondArg;
// Unhandled
- case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
break;
@@ -5151,11 +5183,25 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Cand, NumArgs);
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
// note_ovl_candidate_bad_deduction, which is uselessly vague.
- case Sema::TDK_InstantiationDepth:
- case Sema::TDK_SubstitutionFailure:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction);
diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h
index c13fb17b85..cf16943826 100644
--- a/lib/Sema/SemaOverload.h
+++ b/lib/Sema/SemaOverload.h
@@ -539,6 +539,10 @@ namespace clang {
/// refers to, if any.
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
/// refers to, if any.
const TemplateArgument *getFirstArg();
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index f716ccd6f7..aca820dec6 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1030,10 +1030,8 @@ FinishTemplateArgumentDeduction(Sema &S,
ClassTemplate->getTemplateParameters(), N);
if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
- InstArgs, false, ConvertedInstArgs)) {
- // FIXME: fail with more useful information?
+ InstArgs, false, ConvertedInstArgs))
return Sema::TDK_SubstitutionFailure;
- }
for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
@@ -1377,6 +1375,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
NTTP->getDeclName());
if (NTTPType.isNull()) {
Info.Param = makeTemplateParameter(Param);
+ Info.reset(new (Context) TemplateArgumentList(Context, Builder,
+ /*TakeArgs=*/true));
return TDK_SubstitutionFailure;
}
}
@@ -1402,6 +1402,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
: CTAK_Deduced)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ Info.reset(new (Context) TemplateArgumentList(Context, Builder,
+ /*TakeArgs=*/true));
return TDK_SubstitutionFailure;
}
@@ -1432,6 +1434,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
CTAK_Deduced)) {
Info.Param = makeTemplateParameter(
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
+ Info.reset(new (Context) TemplateArgumentList(Context, Builder,
+ /*TakeArgs=*/true));
return TDK_SubstitutionFailure;
}
@@ -1459,7 +1463,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
// If the template argument list is owned by the function template
// specialization, release it.
- if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+ if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList &&
+ !Trap.hasErrorOccurred())
Info.take();
// There may have been an error that did not prevent us from constructing a
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp
index af8bb39244..bf5f96225d 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p17.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
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() {
A<1> a;
@@ -22,7 +22,7 @@ void k3() {
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() {
A<5> a;
int array[5];
diff --git a/test/SemaTemplate/overload-candidates.cpp b/test/SemaTemplate/overload-candidates.cpp
index 936a6d7aaf..937d633e68 100644
--- a/test/SemaTemplate/overload-candidates.cpp
+++ b/test/SemaTemplate/overload-candidates.cpp
@@ -22,3 +22,10 @@ template<template<class T> class, typename T>
void test_get(void *ptr) {
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'}}
+}