Hi Eigen folks, Clang (and GCC) recently implemented C++ DR 1495 (wg21.link/cwg1495), which says that a class template partial specialization is ill-formed if it is not more specialized than the primary template. (If we imagine the primary template had a corresponding partial specialization, we require that the partial specialization would always be chosen in any situation where both match.)
This causes Clang to reject some code in Eigen: https://bitbucket.org/eigen/eigen/src/e46c8246b284dea1690ac2 60dfe50851906138f0/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h?at= default&fileviewer=file-view-default#TensorStorage.h-38 One way to fix this is: -template<typename T, int Options_, typename FixedDimensions> -class TensorStorage<T, FixedDimensions, Options_> +template<typename T, typename FixedDimensions, int Options_> +class TensorStorage That is, define the primary template instead of defining a partial specialization that doesn't actually specialize anything. On 27 December 2016 at 10:41, Richard Smith <rich...@metafoo.co.uk> wrote: > On 27 Dec 2016 1:42 am, "Chandler Carruth via cfe-commits" < > cfe-commits@lists.llvm.org> wrote: > > I suspect that this commit is responsible for a regression parsing widely > used open source packages like Eigen. > > See the code in Eigen here: > https://bitbucket.org/eigen/eigen/src/e46c8246b284dea1690ac2 > 60dfe50851906138f0/unsupported/Eigen/CXX11/src/Tensor/TensorStorage.h?at= > default&fileviewer=file-view-default#TensorStorage.h-38 > > I'm not claiming this code is correct, but I'm worried about how much code > out there looks like this... Thoughts? Could we at least temporarily put > this DR fix behind a flag or make it a warning? > > > Sure, I'll downgrade it to an ExtWarn. We should also let the Eigen folks > know. > > On Tue, Dec 27, 2016 at 12:07 AM Richard Smith via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> Author: rsmith >> Date: Tue Dec 27 01:56:27 2016 >> New Revision: 290593 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=290593&view=rev >> Log: >> DR1495: A partial specialization is ill-formed if it is not (strictly) >> more >> specialized than the primary template. (Put another way, if we imagine >> there >> were a partial specialization matching the primary template, we should >> never >> select it if some other partial specialization also matches.) >> >> Modified: >> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> cfe/trunk/include/clang/Sema/Sema.h >> cfe/trunk/include/clang/Sema/TemplateDeduction.h >> cfe/trunk/lib/Sema/SemaTemplate.cpp >> cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp >> cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp >> cfe/trunk/test/CXX/drs/dr14xx.cpp >> cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp >> cfe/trunk/test/SemaTemplate/class-template-spec.cpp >> cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp >> cfe/trunk/www/cxx_dr_status.html >> >> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Basic/DiagnosticSemaKinds.td?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Dec 27 >> 01:56:27 2016 >> @@ -4043,6 +4043,10 @@ def err_partial_spec_args_match_primary_ >> "%select{class|variable}0 template partial specialization does not " >> "specialize any template argument; to %select{declare|define}1 the " >> "primary template, remove the template argument list">; >> +def err_partial_spec_not_more_specialized_than_primary : Error< >> + "%select{class|variable}0 template partial specialization is not " >> + "more specialized than the primary template">; >> +def note_partial_spec_not_more_specialized_than_primary : Note<"%0">; >> def warn_partial_specs_not_deducible : Warning< >> "%select{class|variable}0 template partial specialization contains " >> "%select{a template parameter|template parameters}1 that cannot be " >> @@ -4147,7 +4151,7 @@ def note_function_template_deduction_ins >> "%1">; >> def note_deduced_template_arg_substitution_here : Note< >> "during template argument deduction for %select{class|variable}0 >> template " >> - "partial specialization %1 %2">; >> + "%select{partial specialization |}1%2 %3">; >> def note_prior_template_arg_substitution : Note< >> "while substituting prior template arguments into >> %select{non-type|template}0" >> " template parameter%1 %2">; >> >> Modified: cfe/trunk/include/clang/Sema/Sema.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Sema/Sema.h?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Sema/Sema.h (original) >> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Dec 27 01:56:27 2016 >> @@ -6697,10 +6697,16 @@ public: >> ClassTemplatePartialSpecializationDecl >> *PS2, >> SourceLocation Loc); >> >> + bool isMoreSpecializedThanPrimary(ClassTemplatePartialSpecializationDecl >> *T, >> + sema::TemplateDeductionInfo &Info); >> + >> VarTemplatePartialSpecializationDecl *getMoreSpecializedPartialSpec >> ialization( >> VarTemplatePartialSpecializationDecl *PS1, >> VarTemplatePartialSpecializationDecl *PS2, SourceLocation Loc); >> >> + bool isMoreSpecializedThanPrimary(VarTemplatePartialSpecializationDecl >> *T, >> + sema::TemplateDeductionInfo &Info); >> + >> void MarkUsedTemplateParameters(const TemplateArgumentList >> &TemplateArgs, >> bool OnlyDeduced, >> unsigned Depth, >> @@ -6752,7 +6758,7 @@ public: >> /// template argument deduction for either a class template >> /// partial specialization or a function template. The >> /// Entity is either a {Class|Var}TemplatePartialSpecializationDecl >> or >> - /// a FunctionTemplateDecl. >> + /// a TemplateDecl. >> DeducedTemplateArgumentSubstitution, >> >> /// We are substituting prior template arguments into a new >> @@ -6973,6 +6979,14 @@ public: >> sema::TemplateDeductionInfo &DeductionInfo, >> SourceRange InstantiationRange = >> SourceRange()); >> >> + /// \brief Note that we are instantiating as part of template >> + /// argument deduction for a class template declaration. >> + InstantiatingTemplate(Sema &SemaRef, SourceLocation >> PointOfInstantiation, >> + TemplateDecl *Template, >> + ArrayRef<TemplateArgument> TemplateArgs, >> + sema::TemplateDeductionInfo &DeductionInfo, >> + SourceRange InstantiationRange = >> SourceRange()); >> + >> /// \brief Note that we are instantiating as part of template >> /// argument deduction for a class template partial >> /// specialization. >> >> Modified: cfe/trunk/include/clang/Sema/TemplateDeduction.h >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ >> Sema/TemplateDeduction.h?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/include/clang/Sema/TemplateDeduction.h (original) >> +++ cfe/trunk/include/clang/Sema/TemplateDeduction.h Tue Dec 27 01:56:27 >> 2016 >> @@ -79,6 +79,11 @@ public: >> assert(HasSFINAEDiagnostic); >> PD.first = SuppressedDiagnostics.front().first; >> PD.second.swap(SuppressedDiagnostics.front().second); >> + clearSFINAEDiagnostic(); >> + } >> + >> + /// \brief Discard any SFINAE diagnostics. >> + void clearSFINAEDiagnostic() { >> SuppressedDiagnostics.clear(); >> HasSFINAEDiagnostic = false; >> } >> >> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaT >> emplate.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Dec 27 01:56:27 2016 >> @@ -2624,6 +2624,36 @@ makeTemplateArgumentListInfo(Sema &S, Te >> return TemplateArgs; >> } >> >> +template<typename PartialSpecDecl> >> +static void checkMoreSpecializedThanPrimary(Sema &S, PartialSpecDecl >> *Partial) { >> + if (Partial->getDeclContext()->isDependentContext()) >> + return; >> + >> + // FIXME: Get the TDK from deduction in order to provide better >> diagnostics >> + // for non-substitution-failure issues? >> + TemplateDeductionInfo Info(Partial->getLocation()); >> + if (S.isMoreSpecializedThanPrimary(Partial, Info)) >> + return; >> + >> + auto *Template = Partial->getSpecializedTemplate(); >> + S.Diag(Partial->getLocation(), >> + diag::err_partial_spec_not_more_specialized_than_primary) >> + << /*variable template*/isa<VarTemplateDecl>(Template); >> + >> + if (Info.hasSFINAEDiagnostic()) { >> + PartialDiagnosticAt Diag = {SourceLocation(), >> + PartialDiagnostic::NullDiagnostic()}; >> + Info.takeSFINAEDiagnostic(Diag); >> + SmallString<128> SFINAEArgString; >> + Diag.second.EmitToString(S.getDiagnostics(), SFINAEArgString); >> + S.Diag(Diag.first, >> + diag::note_partial_spec_not_more_specialized_than_primary) >> + << SFINAEArgString; >> + } >> + >> + S.Diag(Template->getLocation(), diag::note_template_decl_here); >> +} >> + >> DeclResult Sema::ActOnVarTemplateSpecialization( >> Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation >> TemplateKWLoc, >> TemplateParameterList *TemplateParams, StorageClass SC, >> @@ -2749,6 +2779,11 @@ DeclResult Sema::ActOnVarTemplateSpecial >> if (PrevPartial && PrevPartial->getInstantiatedFromMember()) >> PrevPartial->setMemberSpecialization(); >> >> + // C++1z [temp.class.spec]p8: (DR1495) >> + // - The specialization shall be more specialized than the primary >> + // template (14.5.5.2). >> + checkMoreSpecializedThanPrimary(*this, Partial); >> + >> // Check that all of the template parameters of the variable template >> // partial specialization are deducible from the template >> // arguments. If not, this variable template partial specialization >> @@ -5041,7 +5076,7 @@ ExprResult Sema::CheckTemplateArgument(N >> >> if (CTAK == CTAK_Deduced && >> !Context.hasSameType(ParamType.getNonLValueExprType(Context), >> - Arg->getType().getNonLValueExprType(Context))) >> { >> + Arg->getType())) { >> // C++ [temp.deduct.type]p17: (DR1770) >> // If P has a form that contains <i>, and if the type of i differs >> from >> // the type of the corresponding template parameter of the >> template named >> @@ -5055,7 +5090,7 @@ ExprResult Sema::CheckTemplateArgument(N >> // itself, and so strip off references before comparing types. It's >> // not clear how this is supposed to work for references. >> Diag(StartLoc, diag::err_deduced_non_type_tem >> plate_arg_type_mismatch) >> - << Arg->getType().getUnqualifiedType() >> + << Arg->getType() >> << ParamType.getUnqualifiedType(); >> Diag(Param->getLocation(), diag::note_template_param_here); >> return ExprError(); >> @@ -6501,6 +6536,9 @@ Sema::ActOnClassTemplateSpecialization(S >> // >> // -- The argument list of the specialization shall not be >> identical >> // to the implicit argument list of the primary template. >> + // >> + // This rule has since been removed, because it's redundant given >> DR1495, >> + // but we keep it because it produces better diagnostics and >> recovery. >> Diag(TemplateNameLoc, diag::err_partial_spec_args_ma >> tch_primary_template) >> << /*class template*/0 << (TUK == TUK_Definition) >> << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); >> @@ -6543,6 +6581,11 @@ Sema::ActOnClassTemplateSpecialization(S >> if (PrevPartial && PrevPartial->getInstantiatedFromMember()) >> PrevPartial->setMemberSpecialization(); >> >> + // C++1z [temp.class.spec]p8: (DR1495) >> + // - The specialization shall be more specialized than the primary >> + // template (14.5.5.2). >> + checkMoreSpecializedThanPrimary(*this, Partial); >> + >> // Check that all of the template parameters of the class template >> // partial specialization are deducible from the template >> // arguments. If not, this class template partial specialization >> >> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaT >> emplateDeduction.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Dec 27 01:56:27 2016 >> @@ -1972,8 +1972,14 @@ DeduceTemplateArguments(Sema &S, >> >> /// \brief Determine whether two template arguments are the same. >> static bool isSameTemplateArg(ASTContext &Context, >> - const TemplateArgument &X, >> - const TemplateArgument &Y) { >> + TemplateArgument X, >> + const TemplateArgument &Y, >> + bool PackExpansionMatchesPack = false) { >> + // If we're checking deduced arguments (X) against original arguments >> (Y), >> + // we will have flattened packs to non-expansions in X. >> + if (PackExpansionMatchesPack && X.isPackExpansion() && >> !Y.isPackExpansion()) >> + X = X.getPackExpansionPattern(); >> + >> if (X.getKind() != Y.getKind()) >> return false; >> >> @@ -2016,7 +2022,7 @@ static bool isSameTemplateArg(ASTContext >> XPEnd = X.pack_end(), >> YP = Y.pack_begin(); >> XP != XPEnd; ++XP, ++YP) >> - if (!isSameTemplateArg(Context, *XP, *YP)) >> + if (!isSameTemplateArg(Context, *XP, *YP, >> PackExpansionMatchesPack)) >> return false; >> >> return true; >> @@ -2400,6 +2406,48 @@ FinishTemplateArgumentDeduction( >> return Sema::TDK_Success; >> } >> >> +/// Complete template argument deduction for a class or variable >> template, >> +/// when partial ordering against a partial specialization. >> +// FIXME: Factor out duplication with partial specialization version >> above. >> +Sema::TemplateDeductionResult FinishTemplateArgumentDeduction( >> + Sema &S, TemplateDecl *Template, bool PartialOrdering, >> + const TemplateArgumentList &TemplateArgs, >> + SmallVectorImpl<DeducedTemplateArgument> &Deduced, >> + TemplateDeductionInfo &Info) { >> + // Unevaluated SFINAE context. >> + EnterExpressionEvaluationContext Unevaluated(S, Sema::Unevaluated); >> + Sema::SFINAETrap Trap(S); >> + >> + Sema::ContextRAII SavedContext(S, getAsDeclContextOrEnclosing(Te >> mplate)); >> + >> + // C++ [temp.deduct.type]p2: >> + // [...] or if any template argument remains neither deduced nor >> + // explicitly specified, template argument deduction fails. >> + SmallVector<TemplateArgument, 4> Builder; >> + if (auto Result = ConvertDeducedTemplateArguments( >> + S, Template, /*IsDeduced*/PartialOrdering, Deduced, Info, >> Builder)) >> + return Result; >> + >> + // Check that we produced the correct argument list. >> + TemplateParameterList *TemplateParams = Template->getTemplateParameter >> s(); >> + for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) { >> + TemplateArgument InstArg = Builder[I]; >> + if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg, >> + /*PackExpansionMatchesPack*/true)) { >> + Info.Param = makeTemplateParameter(TemplateParams->getParam(I)); >> + Info.FirstArg = TemplateArgs[I]; >> + Info.SecondArg = InstArg; >> + return Sema::TDK_NonDeducedMismatch; >> + } >> + } >> + >> + if (Trap.hasErrorOccurred()) >> + return Sema::TDK_SubstitutionFailure; >> + >> + return Sema::TDK_Success; >> +} >> + >> + >> /// \brief Perform template argument deduction to determine whether >> /// the given template arguments match the given class template >> /// partial specialization per C++ [temp.class.spec.match]. >> @@ -4535,14 +4583,13 @@ UnresolvedSetIterator Sema::getMostSpeci >> /// specialized than another, P2. >> /// >> /// \tparam PartialSpecializationDecl The kind of P2, which must be a >> -/// {Class,Var}TemplatePartialSpecializationDecl. >> +/// {Class,Var}Template{PartialSpecialization,}Decl. >> /// \param T1 The injected-class-name of P1 (faked for a variable >> template). >> /// \param T2 The injected-class-name of P2 (faked for a variable >> template). >> -/// \param Loc The location at which the comparison is required. >> template<typename PartialSpecializationDecl> >> static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2, >> PartialSpecializationDecl *P2, >> - SourceLocation Loc) { >> + TemplateDeductionInfo &Info) { >> // C++ [temp.class.order]p1: >> // For two class template partial specializations, the first is at >> least as >> // specialized as the second if, given the following rewrite to two >> @@ -4568,7 +4615,6 @@ static bool isAtLeastAsSpecializedAs(Sem >> // template partial specialization's template arguments, for >> // example. >> SmallVector<DeducedTemplateArgument, 4> Deduced; >> - TemplateDeductionInfo Info(Loc); >> >> // Determine whether P1 is at least as specialized as P2. >> Deduced.resize(P2->getTemplateParameters()->size()); >> @@ -4579,7 +4625,8 @@ static bool isAtLeastAsSpecializedAs(Sem >> >> SmallVector<TemplateArgument, 4> DeducedArgs(Deduced.begin(), >> Deduced.end()); >> - Sema::InstantiatingTemplate Inst(S, Loc, P2, DeducedArgs, Info); >> + Sema::InstantiatingTemplate Inst(S, Info.getLocation(), P2, >> DeducedArgs, >> + Info); >> auto *TST1 = T1->castAs<TemplateSpecializationType>(); >> if (FinishTemplateArgumentDeduction( >> S, P2, /*PartialOrdering=*/true, >> @@ -4609,8 +4656,9 @@ Sema::getMoreSpecializedPartialSpecializ >> QualType PT1 = PS1->getInjectedSpecializationType(); >> QualType PT2 = PS2->getInjectedSpecializationType(); >> >> - bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Loc); >> - bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Loc); >> + TemplateDeductionInfo Info(Loc); >> + bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info); >> + bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info); >> >> if (Better1 == Better2) >> return nullptr; >> @@ -4618,6 +4666,20 @@ Sema::getMoreSpecializedPartialSpecializ >> return Better1 ? PS1 : PS2; >> } >> >> +bool Sema::isMoreSpecializedThanPrimary( >> + ClassTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo >> &Info) { >> + ClassTemplateDecl *Primary = Spec->getSpecializedTemplate(); >> + QualType PrimaryT = Primary->getInjectedClassNameSpecialization(); >> + QualType PartialT = Spec->getInjectedSpecializationType(); >> + if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, >> Info)) >> + return false; >> + if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) { >> + Info.clearSFINAEDiagnostic(); >> + return false; >> + } >> + return true; >> +} >> + >> VarTemplatePartialSpecializationDecl * >> Sema::getMoreSpecializedPartialSpecialization( >> VarTemplatePartialSpecializationDecl *PS1, >> @@ -4634,8 +4696,9 @@ Sema::getMoreSpecializedPartialSpecializ >> QualType PT2 = Context.getTemplateSpecializationType( >> CanonTemplate, PS2->getTemplateArgs().asArray()); >> >> - bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Loc); >> - bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Loc); >> + TemplateDeductionInfo Info(Loc); >> + bool Better1 = isAtLeastAsSpecializedAs(*this, PT1, PT2, PS2, Info); >> + bool Better2 = isAtLeastAsSpecializedAs(*this, PT2, PT1, PS1, Info); >> >> if (Better1 == Better2) >> return nullptr; >> @@ -4643,6 +4706,30 @@ Sema::getMoreSpecializedPartialSpecializ >> return Better1 ? PS1 : PS2; >> } >> >> +bool Sema::isMoreSpecializedThanPrimary( >> + VarTemplatePartialSpecializationDecl *Spec, TemplateDeductionInfo >> &Info) { >> + TemplateDecl *Primary = Spec->getSpecializedTemplate(); >> + // FIXME: Cache the injected template arguments rather than recomputing >> + // them for each partial specialization. >> + SmallVector<TemplateArgument, 8> PrimaryArgs; >> + Context.getInjectedTemplateArgs(Primary->getTemplateParameters(), >> + PrimaryArgs); >> + >> + TemplateName CanonTemplate = >> + Context.getCanonicalTemplateName(TemplateName(Primary)); >> + QualType PrimaryT = Context.getTemplateSpecializationType( >> + CanonTemplate, PrimaryArgs); >> + QualType PartialT = Context.getTemplateSpecializationType( >> + CanonTemplate, Spec->getTemplateArgs().asArray()); >> + if (!isAtLeastAsSpecializedAs(*this, PartialT, PrimaryT, Primary, >> Info)) >> + return false; >> + if (isAtLeastAsSpecializedAs(*this, PrimaryT, PartialT, Spec, Info)) { >> + Info.clearSFINAEDiagnostic(); >> + return false; >> + } >> + return true; >> +} >> + >> static void >> MarkUsedTemplateParameters(ASTContext &Ctx, >> const TemplateArgument &TemplateArg, >> >> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaT >> emplateInstantiate.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) >> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Dec 27 01:56:27 >> 2016 >> @@ -279,6 +279,17 @@ Sema::InstantiatingTemplate::Instantiati >> >> Sema::InstantiatingTemplate::InstantiatingTemplate( >> Sema &SemaRef, SourceLocation PointOfInstantiation, >> + TemplateDecl *Template, >> + ArrayRef<TemplateArgument> TemplateArgs, >> + sema::TemplateDeductionInfo &DeductionInfo, SourceRange >> InstantiationRange) >> + : InstantiatingTemplate( >> + SemaRef, >> + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitu >> tion, >> + PointOfInstantiation, InstantiationRange, Template, nullptr, >> + TemplateArgs, &DeductionInfo) {} >> + >> +Sema::InstantiatingTemplate::InstantiatingTemplate( >> + Sema &SemaRef, SourceLocation PointOfInstantiation, >> ClassTemplatePartialSpecializationDecl *PartialSpec, >> ArrayRef<TemplateArgument> TemplateArgs, >> sema::TemplateDeductionInfo &DeductionInfo, SourceRange >> InstantiationRange) >> @@ -497,8 +508,12 @@ void Sema::PrintInstantiationStack() { >> } else { >> bool IsVar = isa<VarTemplateDecl>(Active->Entity) || >> isa<VarTemplateSpecializationDecl>(Active->Entity); >> + bool IsTemplate = false; >> TemplateParameterList *Params; >> - if (auto *D = dyn_cast<ClassTemplatePartialSpecializationDecl>( >> + if (auto *D = dyn_cast<TemplateDecl>(Active->Entity)) { >> + IsTemplate = true; >> + Params = D->getTemplateParameters(); >> + } else if (auto *D = dyn_cast<ClassTemplatePartialS >> pecializationDecl>( >> Active->Entity)) { >> Params = D->getTemplateParameters(); >> } else if (auto *D = dyn_cast<VarTemplatePartialSpe >> cializationDecl>( >> @@ -510,7 +525,7 @@ void Sema::PrintInstantiationStack() { >> >> Diags.Report(Active->PointOfInstantiation, >> diag::note_deduced_template_arg_substitution_here) >> - << IsVar << cast<NamedDecl>(Active->Entity) >> + << IsVar << IsTemplate << cast<NamedDecl>(Active->Entity) >> << getTemplateArgumentBindingsText(Params, >> Active->TemplateArgs, >> Active->NumTemplateArgs) >> << Active->InstantiationRange; >> >> Modified: cfe/trunk/test/CXX/drs/dr14xx.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/ >> dr14xx.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/test/CXX/drs/dr14xx.cpp (original) >> +++ cfe/trunk/test/CXX/drs/dr14xx.cpp Tue Dec 27 01:56:27 2016 >> @@ -342,4 +342,32 @@ namespace dr1490 { // dr1490: 3.7 c++11 >> char s[4]{"abc"}; // Ok >> std::initializer_list<char>{"abc"}; // expected-error {{expected >> unqualified-id}}} >> } // dr190 >> + >> +namespace dr1495 { // dr1495: 4.0 >> + // Deduction succeeds in both directions. >> + template<typename T, typename U> struct A {}; // expected-note >> {{template is declared here}} >> + template<typename T, typename U> struct A<U, T> {}; // expected-error >> {{class template partial specialization is not more specialized}} >> + >> + // Primary template is more specialized. >> + template<typename, typename...> struct B {}; // expected-note >> {{template is declared here}} >> + template<typename ...Ts> struct B<Ts...> {}; // expected-error {{not >> more specialized}} >> + >> + // Deduction fails in both directions. >> + template<int, typename, typename ...> struct C {}; // expected-note >> {{template is declared here}} >> + template<typename ...Ts> struct C<0, Ts...> {}; // expected-error >> {{not more specialized}} >> + >> +#if __cplusplus >= 201402L >> + // Deduction succeeds in both directions. >> + template<typename T, typename U> int a; // expected-note {{template is >> declared here}} >> + template<typename T, typename U> int a<U, T>; // expected-error >> {{variable template partial specialization is not more specialized}} >> + >> + // Primary template is more specialized. >> + template<typename, typename...> int b; // expected-note {{template is >> declared here}} >> + template<typename ...Ts> int b<Ts...>; // expected-error {{not more >> specialized}} >> + >> + // Deduction fails in both directions. >> + template<int, typename, typename ...> int c; // expected-note >> {{template is declared here}} >> + template<typename ...Ts> int c<0, Ts...>; // expected-error {{not more >> specialized}} >> +#endif >> +} >> #endif >> >> Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/fixed-expan >> sion.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/ >> temp.decls/temp.variadic/fixed-expansion.cpp?rev=290593&r1= >> 290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp >> (original) >> +++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/fixed-expansion.cpp >> Tue Dec 27 01:56:27 2016 >> @@ -108,10 +108,10 @@ namespace PR9021b { >> >> namespace PartialSpecialization { >> template<typename T, typename U, typename V = U> >> - struct X0; // expected-note{{template is declared here}} >> + struct X0; // expected-note 2{{template is declared here}} >> >> template<typename ...Ts> >> - struct X0<Ts...> { >> + struct X0<Ts...> { // expected-error {{class template partial >> specialization is not more specialized than the primary template}} >> }; >> >> X0<int> x0i; // expected-error{{too few template arguments for class >> template 'X0'}} >> >> Modified: cfe/trunk/test/SemaTemplate/class-template-spec.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTempl >> ate/class-template-spec.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/test/SemaTemplate/class-template-spec.cpp (original) >> +++ cfe/trunk/test/SemaTemplate/class-template-spec.cpp Tue Dec 27 >> 01:56:27 2016 >> @@ -167,10 +167,16 @@ namespace PR16519 { >> // expected-warning@-2 {{variadic templates are a C++11 extension}} >> #endif >> >> - template<typename T, T ...N, T ...Extra> struct >> __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> { >> + // Note that the following seemingly-equivalent template parameter >> list is >> + // not OK; it would result in a partial specialization that is not more >> + // specialized than the primary template. (See NTTPTypeVsPartialOrder >> below.) >> + // >> + // template<typename T, T ...N, T ...Extra> >> + template<typename T, T ...N, typename integer_sequence<T, >> N...>::value_type ...Extra> >> #if __cplusplus <= 199711L >> - // expected-warning@-2 2 {{variadic templates are a C++11 extension}} >> + // expected-warning@-2 2{{variadic templates are a C++11 extension}} >> #endif >> + struct __make_integer_sequence_impl<integer_sequence<T, N...>, >> Extra...> { >> typedef integer_sequence<T, N..., sizeof...(N) + N..., Extra...> >> type; >> }; >> >> @@ -193,6 +199,25 @@ namespace PR16519 { >> #endif >> } >> >> +namespace NTTPTypeVsPartialOrder { >> + struct X { typedef int value_type; }; >> + template<typename T> struct Y { typedef T value_type; }; >> + >> + template<typename T, typename T::value_type N> struct A; // >> expected-note {{template}} >> + template<int N> struct A<X, N> {}; >> + template<typename T, T N> struct A<Y<T>, N> {}; // expected-error >> {{not more specialized}} expected-note {{'T' vs 'typename >> Y<type-parameter-0-0>::value_type'}} >> + A<X, 0> ax; >> + A<Y<int>, 0> ay; >> + >> + >> + template<int, typename T, typename T::value_type> struct B; // >> expected-note {{template}} >> + template<typename T, typename T::value_type N> struct B<0, T, N>; // >> expected-note {{matches}} >> + template<int N> struct B<0, X, N> {}; >> + template<typename T, T N> struct B<0, Y<T>, N> {}; // expected-error >> {{not more specialized}} expected-note {{'T' vs 'typename >> Y<type-parameter-0-0>::value_type'}} expected-note {{matches}} >> + B<0, X, 0> bx; >> + B<0, Y<int>, 0> by; // expected-error {{ambiguous}} >> +} >> + >> namespace DefaultArgVsPartialSpec { >> // Check that the diagnostic points at the partial specialization, not >> just at >> // the default argument. >> >> Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTempl >> ate/temp_arg_nontype.cpp?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original) >> +++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Tue Dec 27 01:56:27 >> 2016 >> @@ -367,11 +367,11 @@ namespace PR17696 { >> >> namespace partial_order_different_types { >> // These are unordered because the type of the final argument doesn't >> match. >> - // FIXME: The second partial specialization should actually be rejected >> - // because it's not more specialized than the primary template. >> - template<int, int, typename T, typename, T> struct A; >> + template<int, int, typename T, typename, T> struct A; // expected-note >> {{here}} >> template<int N, typename T, typename U, T V> struct A<0, N, T, U, V> >> {}; // expected-note {{matches}} >> template<typename T, typename U, U V> struct A<0, 0, T, U, V> {}; // >> expected-note {{matches}} >> + // expected-error@-1 {{not more specialized than the primary}} >> + // expected-note@-2 {{deduced non-type template argument does not >> have the same type as the corresponding template parameter ('U' vs >> 'type-parameter-0-0')}} >> A<0, 0, int, int, 0> a; // expected-error {{ambiguous partial >> specializations}} >> } >> >> @@ -389,18 +389,22 @@ namespace partial_order_references { >> int N; >> A<0, 0, N> a; >> >> - // FIXME: These should all be rejected as they are not more >> specialized than >> - // the primary template (they can never be used due to the type >> mismatch). >> - template<int, int &R> struct B; // expected-note {{template}} >> + template<int, int &R> struct B; // expected-note 2{{template}} >> template<const int &R> struct B<0, R> {}; >> + // expected-error@-1 {{not more specialized than the primary}} >> + // expected-note@-2 {{'const int' vs 'int &'}} >> B<0, N> b; // expected-error {{undefined}} >> >> - template<int, const int &R> struct C; // expected-note {{template}} >> + template<int, const int &R> struct C; // expected-note 2{{template}} >> template<int &R> struct C<0, R> {}; >> + // expected-error@-1 {{not more specialized than the primary}} >> + // expected-note@-2 {{'int' vs 'const int &'}} >> C<0, N> c; // expected-error {{undefined}} >> >> - template<int, const int &R> struct D; // expected-note {{template}} >> + template<int, const int &R> struct D; // expected-note 2{{template}} >> template<int N> struct D<0, N> {}; >> + // expected-error@-1 {{not more specialized than the primary}} >> + // expected-note@-2 {{'int' vs 'const int &'}} >> extern const int K = 5; >> D<0, K> d; // expected-error {{undefined}} >> } >> >> Modified: cfe/trunk/www/cxx_dr_status.html >> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_dr_sta >> tus.html?rev=290593&r1=290592&r2=290593&view=diff >> ============================================================ >> ================== >> --- cfe/trunk/www/cxx_dr_status.html (original) >> +++ cfe/trunk/www/cxx_dr_status.html Tue Dec 27 01:56:27 2016 >> @@ -4195,7 +4195,7 @@ and <I>POD class</I></td> >> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defect >> s.html#692">692</a></td> >> <td>C++11</td> >> <td>Partial ordering of variadic class template partial >> specializations</td> >> - <td class="none" align="center">Unknown</td> >> + <td class="none" align="center">No</td> >> </tr> >> <tr id="693"> >> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defect >> s.html#693">693</a></td> >> @@ -8785,7 +8785,7 @@ and <I>POD class</I></td> >> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defect >> s.html#1495">1495</a></td> >> <td>CD3</td> >> <td>Partial specialization of variadic class template</td> >> - <td class="none" align="center">Unknown</td> >> + <td class="svn" align="center">SVN</td> >> </tr> >> <tr id="1496"> >> <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defect >> s.html#1496">1496</a></td> >> >> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits