summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Sema/Sema.h3
-rw-r--r--clang/include/clang/Sema/TemplateDeduction.h33
-rw-r--r--clang/lib/Sema/SemaOverload.cpp56
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp8
-rw-r--r--clang/test/CXX/drs/dr5xx.cpp3
-rw-r--r--clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp2
-rw-r--r--clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp2
8 files changed, 95 insertions, 16 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 25fbe2db1ca..a8e468d956c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3112,6 +3112,10 @@ def note_addrof_ovl_candidate_disabled_by_enable_if_attr : Note<
def note_ovl_candidate_failed_overload_resolution : Note<
"candidate template ignored: couldn't resolve reference to overloaded "
"function %0">;
+def note_ovl_candidate_deduced_mismatch : Note<
+ "candidate template ignored: deduced type "
+ "%diff{$ of %ordinal0 parameter does not match adjusted type $ of argument"
+ "|of %ordinal0 parameter does not match adjusted type of argument}1,2%3">;
def note_ovl_candidate_non_deduced_mismatch : Note<
"candidate template ignored: could not match %diff{$ against $|types}0,1">;
// This note is needed because the above note would sometimes print two
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7873843ab3b..bce2f0c0bad 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6302,6 +6302,9 @@ public:
/// \brief Substitution of the deduced template argument values
/// resulted in an error.
TDK_SubstitutionFailure,
+ /// \brief After substituting deduced template arguments, a dependent
+ /// parameter type did not match the corresponding argument.
+ TDK_DeducedMismatch,
/// \brief A non-depnedent component of the parameter did not match the
/// corresponding component of the argument.
TDK_NonDeducedMismatch,
diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index 9315ddd89c6..c22c703ef73 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -140,6 +140,9 @@ public:
/// TDK_SubstitutionFailure: this argument is the template
/// argument we were instantiating when we encountered an error.
///
+ /// TDK_DeducedMismatch: this is the parameter type, after substituting
+ /// deduced arguments.
+ ///
/// TDK_NonDeducedMismatch: this is the component of the 'parameter'
/// of the deduction, directly provided in the source code.
TemplateArgument FirstArg;
@@ -147,18 +150,32 @@ public:
/// \brief The second template argument to which the template
/// argument deduction failure refers.
///
+ /// TDK_Inconsistent: this argument is the second value deduced
+ /// for the corresponding template parameter.
+ ///
+ /// TDK_DeducedMismatch: this is the (adjusted) call argument type.
+ ///
/// TDK_NonDeducedMismatch: this is the mismatching component of the
/// 'argument' of the deduction, from which we are deducing arguments.
///
/// FIXME: Finish documenting this.
TemplateArgument SecondArg;
- /// \brief The expression which caused a deduction failure.
- ///
- /// TDK_FailedOverloadResolution: this argument is the reference to
- /// an overloaded function which could not be resolved to a specific
- /// function.
- Expr *Expression;
+ union {
+ /// \brief The expression which caused a deduction failure.
+ ///
+ /// TDK_FailedOverloadResolution: this argument is the reference to
+ /// an overloaded function which could not be resolved to a specific
+ /// function.
+ Expr *Expression;
+
+ /// \brief The index of the function argument that caused a deduction
+ /// failure.
+ ///
+ /// TDK_DeducedMismatch: this is the index of the argument that had a
+ /// different argument type from its substituted parameter type.
+ unsigned CallArgIndex;
+ };
/// \brief Information on packs that we're currently expanding.
///
@@ -211,6 +228,10 @@ struct DeductionFailureInfo {
/// if any.
Expr *getExpr();
+ /// \brief Return the index of the call argument that this deduction
+ /// failure refers to, if any.
+ llvm::Optional<unsigned> getCallArgIndex();
+
/// \brief Free any memory associated with this deduction failure.
void Destroy();
};
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 1caa94c9a45..e0c10e4479e 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -543,6 +543,12 @@ namespace {
struct DFIParamWithArguments : DFIArguments {
TemplateParameter Param;
};
+ // Structure used by DeductionFailureInfo to store template argument
+ // information and the index of the problematic call argument.
+ struct DFIDeducedMismatchArgs : DFIArguments {
+ TemplateArgumentList *TemplateArgs;
+ unsigned CallArgIndex;
+ };
}
/// \brief Convert from Sema's representation of template deduction information
@@ -554,13 +560,14 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
DeductionFailureInfo Result;
Result.Result = static_cast<unsigned>(TDK);
Result.HasDiagnostic = false;
- Result.Data = nullptr;
switch (TDK) {
case Sema::TDK_Success:
case Sema::TDK_Invalid:
case Sema::TDK_InstantiationDepth:
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
+ case Sema::TDK_MiscellaneousDeductionFailure:
+ Result.Data = nullptr;
break;
case Sema::TDK_Incomplete:
@@ -568,6 +575,17 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
Result.Data = Info.Param.getOpaqueValue();
break;
+ case Sema::TDK_DeducedMismatch: {
+ // FIXME: Should allocate from normal heap so that we can free this later.
+ auto *Saved = new (Context) DFIDeducedMismatchArgs;
+ Saved->FirstArg = Info.FirstArg;
+ Saved->SecondArg = Info.SecondArg;
+ Saved->TemplateArgs = Info.take();
+ Saved->CallArgIndex = Info.CallArgIndex;
+ Result.Data = Saved;
+ break;
+ }
+
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Should allocate from normal heap so that we can free this later.
DFIArguments *Saved = new (Context) DFIArguments;
@@ -601,9 +619,6 @@ clang::MakeDeductionFailureInfo(ASTContext &Context,
case Sema::TDK_FailedOverloadResolution:
Result.Data = Info.Expression;
break;
-
- case Sema::TDK_MiscellaneousDeductionFailure:
- break;
}
return Result;
@@ -623,6 +638,7 @@ void DeductionFailureInfo::Destroy() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
// FIXME: Destroy the data?
Data = nullptr;
@@ -657,6 +673,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() {
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_FailedOverloadResolution:
return TemplateParameter();
@@ -692,6 +709,9 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() {
case Sema::TDK_FailedOverloadResolution:
return nullptr;
+ case Sema::TDK_DeducedMismatch:
+ return static_cast<DFIDeducedMismatchArgs*>(Data)->TemplateArgs;
+
case Sema::TDK_SubstitutionFailure:
return static_cast<TemplateArgumentList*>(Data);
@@ -718,6 +738,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->FirstArg;
@@ -744,6 +765,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() {
case Sema::TDK_Inconsistent:
case Sema::TDK_Underqualified:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
return &static_cast<DFIArguments*>(Data)->SecondArg;
@@ -763,6 +785,14 @@ Expr *DeductionFailureInfo::getExpr() {
return nullptr;
}
+llvm::Optional<unsigned> DeductionFailureInfo::getCallArgIndex() {
+ if (static_cast<Sema::TemplateDeductionResult>(Result) ==
+ Sema::TDK_DeducedMismatch)
+ return static_cast<DFIDeducedMismatchArgs*>(Data)->CallArgIndex;
+
+ return llvm::None;
+}
+
void OverloadCandidateSet::destroyCandidates() {
for (iterator i = begin(), e = end(); i != e; ++i) {
for (unsigned ii = 0, ie = i->NumConversions; ii != ie; ++ii)
@@ -9397,6 +9427,23 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
return;
}
+ case Sema::TDK_DeducedMismatch: {
+ // Format the template argument list into the argument string.
+ SmallString<128> TemplateArgString;
+ if (TemplateArgumentList *Args =
+ DeductionFailure.getTemplateArgumentList()) {
+ TemplateArgString = " ";
+ TemplateArgString += S.getTemplateArgumentBindingsText(
+ getDescribedTemplate(Templated)->getTemplateParameters(), *Args);
+ }
+
+ S.Diag(Templated->getLocation(), diag::note_ovl_candidate_deduced_mismatch)
+ << (*DeductionFailure.getCallArgIndex() + 1)
+ << *DeductionFailure.getFirstArg() << *DeductionFailure.getSecondArg()
+ << TemplateArgString;
+ break;
+ }
+
case Sema::TDK_NonDeducedMismatch: {
// FIXME: Provide a source location to indicate what we couldn't match.
TemplateArgument FirstTA = *DeductionFailure.getFirstArg();
@@ -9686,6 +9733,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) {
return 2;
case Sema::TDK_SubstitutionFailure:
+ case Sema::TDK_DeducedMismatch:
case Sema::TDK_NonDeducedMismatch:
case Sema::TDK_MiscellaneousDeductionFailure:
return 3;
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 837e0de4038..cd54920b08c 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2954,8 +2954,12 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
continue;
QualType DeducedA = Specialization->getParamDecl(ParamIdx)->getType();
- if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA))
- return Sema::TDK_SubstitutionFailure;
+ if (CheckOriginalCallArgDeduction(*this, OriginalArg, DeducedA)) {
+ Info.FirstArg = TemplateArgument(DeducedA);
+ Info.SecondArg = TemplateArgument(OriginalArg.OriginalArgType);
+ Info.CallArgIndex = OriginalArg.ArgIdx;
+ return TDK_DeducedMismatch;
+ }
}
}
diff --git a/clang/test/CXX/drs/dr5xx.cpp b/clang/test/CXX/drs/dr5xx.cpp
index 17b525d9622..96d3494bf06 100644
--- a/clang/test/CXX/drs/dr5xx.cpp
+++ b/clang/test/CXX/drs/dr5xx.cpp
@@ -148,8 +148,7 @@ namespace dr522 { // dr522: yes
template<typename T> void b2(volatile T * const *);
template<typename T> void b2(volatile T * const S::*);
template<typename T> void b2(volatile T * const S::* const *);
- // FIXME: This diagnostic isn't very good. The problem is not substitution failure.
- template<typename T> void b2a(volatile T *S::* const *); // expected-note {{substitution failure}}
+ template<typename T> void b2a(volatile T *S::* const *); // expected-note {{candidate template ignored: deduced type 'volatile int *dr522::S::*const *' of 1st parameter does not match adjusted type 'int *dr522::S::**' of argument}}
template<typename T> struct Base {};
struct Derived : Base<int> {};
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
index 295f080a75d..f46ea2e585d 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
@@ -139,7 +139,7 @@ namespace N {
}
namespace PR9233 {
- template<typename T> void f(const T **q); // expected-note{{candidate template ignored: substitution failure [with T = int]}}
+ template<typename T> void f(const T **q); // expected-note{{candidate template ignored: deduced type 'const int **' of 1st parameter does not match adjusted type 'int **' of argument [with T = int]}}
void g(int **p) {
f(p); // expected-error{{no matching function for call to 'f'}}
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
index 782057d397b..b807a0ff9f1 100644
--- a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p9-0x.cpp
@@ -55,7 +55,7 @@ namespace DeduceNonTypeTemplateArgsInArray {
}
namespace DeduceWithDefaultArgs {
- template<template<typename...> class Container> void f(Container<int>); // expected-note {{substitution failure [with Container = X]}}
+ template<template<typename...> class Container> void f(Container<int>); // expected-note {{deduced type 'X<[...], (default) int>' of 1st parameter does not match adjusted type 'X<[...], double>' of argument [with Container = X]}}
template<typename, typename = int> struct X {};
void g() {
// OK, use default argument for the second template parameter.
OpenPOWER on IntegriCloud