diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 10 | ||||
-rw-r--r-- | include/clang/Sema/TemplateDeduction.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 88 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 22 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp | 3 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp | 3 | ||||
-rw-r--r-- | test/SemaCXX/c99-variable-length-array.cpp | 3 | ||||
-rw-r--r-- | test/SemaTemplate/instantiate-init.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/operator-template.cpp | 2 | ||||
-rw-r--r-- | test/SemaTemplate/recursive-template-instantiation.cpp | 2 |
11 files changed, 91 insertions, 53 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index f20bd06ce5..28082267e3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2334,6 +2334,8 @@ def note_ovl_candidate_disabled_by_enable_if : Note< def note_ovl_candidate_failed_overload_resolution : Note< "candidate template ignored: couldn't resolve reference to overloaded " "function %0">; +def note_ovl_candidate_non_deduced_mismatch : Note< + "candidate template ignored: could not match %diff{$ against $|types}0,1">; // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b77897a243..47b2de8bd1 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5451,10 +5451,8 @@ public: /// \brief Substitution of the deduced template argument values /// resulted in an error. TDK_SubstitutionFailure, - /// \brief Substitution of the deduced template argument values - /// into a non-deduced context produced a type or value that - /// produces a type that does not match the original template - /// arguments provided. + /// \brief A non-depnedent component of the parameter did not match the + /// corresponding component of the argument. TDK_NonDeducedMismatch, /// \brief When performing template argument deduction for a function /// template, there were too many call arguments. @@ -5467,7 +5465,9 @@ public: TDK_InvalidExplicitArguments, /// \brief The arguments included an overloaded function name that could /// not be resolved to a suitable function. - TDK_FailedOverloadResolution + TDK_FailedOverloadResolution, + /// \brief Deduction failed; that's all we know. + TDK_MiscellaneousDeductionFailure }; TemplateDeductionResult diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index e9a1449dbb..3abb8f1889 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -141,13 +141,16 @@ public: /// TDK_SubstitutionFailure: this argument is the template /// argument we were instantiating when we encountered an error. /// - /// TDK_NonDeducedMismatch: this is the template argument - /// provided in the source code. + /// TDK_NonDeducedMismatch: this is the component of the 'parameter' + /// of the deduction, directly provided in the source code. TemplateArgument FirstArg; /// \brief The second template argument to which the template /// argument deduction failure refers. /// + /// 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; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index dbab739832..82fe0c9ed0 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -536,12 +536,16 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { namespace { // Structure used by OverloadCandidate::DeductionFailureInfo to store - // template parameter and template argument information. - struct DFIParamWithArguments { - TemplateParameter Param; + // template argument information. + struct DFIArguments { TemplateArgument FirstArg; TemplateArgument SecondArg; }; + // Structure used by OverloadCandidate::DeductionFailureInfo to store + // template parameter and template argument information. + struct DFIParamWithArguments : DFIArguments { + TemplateParameter Param; + }; } /// \brief Convert from Sema's representation of template deduction information @@ -567,6 +571,15 @@ static MakeDeductionFailureInfo(ASTContext &Context, Result.Data = Info.Param.getOpaqueValue(); break; + case Sema::TDK_NonDeducedMismatch: { + // FIXME: Should allocate from normal heap so that we can free this later. + DFIArguments *Saved = new (Context) DFIArguments; + Saved->FirstArg = Info.FirstArg; + Saved->SecondArg = Info.SecondArg; + Result.Data = Saved; + break; + } + case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. @@ -592,7 +605,7 @@ static MakeDeductionFailureInfo(ASTContext &Context, Result.Data = Info.Expression; break; - case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -608,10 +621,12 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_FailedOverloadResolution: break; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: + case Sema::TDK_NonDeducedMismatch: // FIXME: Destroy the data? Data = 0; break; @@ -626,8 +641,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { break; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } } @@ -648,6 +662,8 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: return TemplateParameter(); case Sema::TDK_Incomplete: @@ -659,8 +675,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { return static_cast<DFIParamWithArguments*>(Data)->Param; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -670,24 +685,25 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { TemplateArgumentList * OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { - case Sema::TDK_Success: - case Sema::TDK_Invalid: - 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_Underqualified: - return 0; + case Sema::TDK_Success: + case Sema::TDK_Invalid: + 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_Underqualified: + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_FailedOverloadResolution: + return 0; - case Sema::TDK_SubstitutionFailure: - return static_cast<TemplateArgumentList*>(Data); + case Sema::TDK_SubstitutionFailure: + return static_cast<TemplateArgumentList*>(Data); - // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: - break; + // Unhandled + case Sema::TDK_MiscellaneousDeductionFailure: + break; } return 0; @@ -703,15 +719,16 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_FailedOverloadResolution: return 0; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: - return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; + case Sema::TDK_NonDeducedMismatch: + return &static_cast<DFIArguments*>(Data)->FirstArg; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -729,15 +746,16 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_SubstitutionFailure: + case Sema::TDK_FailedOverloadResolution: return 0; case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: - return &static_cast<DFIParamWithArguments*>(Data)->SecondArg; + case Sema::TDK_NonDeducedMismatch: + return &static_cast<DFIArguments*>(Data)->SecondArg; // Unhandled - case Sema::TDK_NonDeducedMismatch: - case Sema::TDK_FailedOverloadResolution: + case Sema::TDK_MiscellaneousDeductionFailure: break; } @@ -8463,9 +8481,16 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, return; } + case Sema::TDK_NonDeducedMismatch: + // FIXME: Provide a source location to indicate what we couldn't match. + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + return; + // TODO: diagnose these individually, then kill off // note_ovl_candidate_bad_deduction, which is uselessly vague. - case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_MiscellaneousDeductionFailure: S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); MaybeEmitInheritedConstructorNote(S, Fn); return; @@ -8643,6 +8668,7 @@ RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { case Sema::TDK_SubstitutionFailure: case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_MiscellaneousDeductionFailure: return 3; case Sema::TDK_InstantiationDepth: diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 003d0161e9..421633f389 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -488,13 +488,19 @@ DeduceTemplateArguments(Sema &S, // perform template argument deduction using its template // arguments. const RecordType *RecordArg = dyn_cast<RecordType>(Arg); - if (!RecordArg) + if (!RecordArg) { + Info.FirstArg = TemplateArgument(QualType(Param, 0)); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_NonDeducedMismatch; + } ClassTemplateSpecializationDecl *SpecArg = dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl()); - if (!SpecArg) + if (!SpecArg) { + Info.FirstArg = TemplateArgument(QualType(Param, 0)); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_NonDeducedMismatch; + } // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result @@ -708,7 +714,7 @@ DeduceTemplateArguments(Sema &S, if (NumParams != NumArgs && !(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) && !(NumArgs && isa<PackExpansionType>(Args[NumArgs - 1]))) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type @@ -725,14 +731,14 @@ DeduceTemplateArguments(Sema &S, // Make sure we have an argument. if (ArgIdx >= NumArgs) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; if (isa<PackExpansionType>(Args[ArgIdx])) { // C++0x [temp.deduct.type]p22: // If the original function parameter associated with A is a function // parameter pack and the function parameter associated with P is not // a function parameter pack, then template argument deduction fails. - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; } if (Sema::TemplateDeductionResult Result @@ -825,7 +831,7 @@ DeduceTemplateArguments(Sema &S, // Make sure we don't have any extra arguments. if (ArgIdx < NumArgs) - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; return Sema::TDK_Success; } @@ -1772,7 +1778,7 @@ DeduceTemplateArguments(Sema &S, if (Args[ArgIdx].isPackExpansion()) { // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here, // but applied to pack expansions that are template arguments. - return Sema::TDK_NonDeducedMismatch; + return Sema::TDK_MiscellaneousDeductionFailure; } // Perform deduction for this Pi/Ai pair. @@ -3365,7 +3371,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // specialization, template argument deduction fails. if (!ArgFunctionType.isNull() && !Context.hasSameType(ArgFunctionType, Specialization->getType())) - return TDK_NonDeducedMismatch; + return TDK_MiscellaneousDeductionFailure; return TDK_Success; } diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp index 90d29497f4..4f6dcc1105 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/basic.cpp @@ -15,8 +15,7 @@ void test_f1(int *ip, float fv) { f1(ip, fv); } -// TODO: this diagnostic can and should improve -template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: failed template argument deduction}} \ +template<typename T> void f2(T*, T*); // expected-note {{candidate template ignored: could not match 'T *' against 'ConvToIntPtr'}} \ // expected-note{{candidate template ignored: deduced conflicting types for parameter 'T' ('int' vs. 'float')}} struct ConvToIntPtr { diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp index 8b192fa547..cd1d9f15c7 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -53,8 +53,9 @@ void test_simple_ref_deduction(int *ip, float *fp, double *dp) { } +// FIXME: Use the template parameter names in this diagnostic. template<typename ...Args1, typename ...Args2> -typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: failed template argument deduction}} +typename get_nth_type<0, Args1...>::type first_arg_pair(pair<Args1, Args2>...); // expected-note{{candidate template ignored: could not match 'pair<type-parameter-0-0, type-parameter-0-1>' against 'int'}} template<typename ...Args1, typename ...Args2> typename get_nth_type<1, Args1...>::type second_arg_pair(pair<Args1, Args2>...); diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp index de9c11e565..bb620c71fa 100644 --- a/test/SemaCXX/c99-variable-length-array.cpp +++ b/test/SemaCXX/c99-variable-length-array.cpp @@ -64,8 +64,9 @@ X1<HasConstantValue> x1a; X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}} // Template argument deduction does not allow deducing a size from a VLA. +// FIXME: This diagnostic should make it clear that the two 'N's are different entities! template<typename T, unsigned N> -void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: failed template argument deduction}} +void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: could not match 'T [N]' against 'int [N]'}} void test_accept_array(int N) { int array[N]; // expected-warning{{variable length arrays are a C99 feature}} diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp index adcc06fa37..6a1a57ca65 100644 --- a/test/SemaTemplate/instantiate-init.cpp +++ b/test/SemaTemplate/instantiate-init.cpp @@ -78,7 +78,7 @@ namespace PR7985 { template<int N> struct integral_c { }; template <typename T, int N> - integral_c<N> array_lengthof(T (&x)[N]) { return integral_c<N>(); } // expected-note 2{{candidate template ignored: failed template argument deduction}} + integral_c<N> array_lengthof(T (&x)[N]) { return integral_c<N>(); } // expected-note 2{{candidate template ignored: could not match 'T [N]' against 'const Data<}} template<typename T> struct Data { diff --git a/test/SemaTemplate/operator-template.cpp b/test/SemaTemplate/operator-template.cpp index 777b0f5f42..30d6ccfb95 100644 --- a/test/SemaTemplate/operator-template.cpp +++ b/test/SemaTemplate/operator-template.cpp @@ -2,7 +2,7 @@ // Make sure we accept this template<class X>struct A{typedef X Y;}; -template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: failed template argument deduction}} +template<class X>bool operator==(A<X>,typename A<X>::Y); // expected-note{{candidate template ignored: could not match 'A<type-parameter-0-0>' against 'B<int> *'}} int a(A<int> x) { return operator==(x,1); } diff --git a/test/SemaTemplate/recursive-template-instantiation.cpp b/test/SemaTemplate/recursive-template-instantiation.cpp index d6a0b247dd..fe37060185 100644 --- a/test/SemaTemplate/recursive-template-instantiation.cpp +++ b/test/SemaTemplate/recursive-template-instantiation.cpp @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -template<typename T> void f(T* t) { // expected-note{{failed template argument deduction}} +template<typename T> void f(T* t) { // expected-note{{could not match 'T *' against 'int'}} f(*t); // expected-error{{no matching function}}\ // expected-note 3{{requested here}} } |