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/e46c8246b284dea1690ac260dfe508 51906138f0/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 *getMoreSpecializedPartialSpeci > alization( > 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/ > SemaTemplate.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_template_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_ > match_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/ > SemaTemplateDeduction.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( > Template)); > + > + // 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-> > getTemplateParameters(); > + 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/ > SemaTemplateInstantiate.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::DeducedTemplateArgumentSubstit > ution, > + 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<ClassTemplatePartialSpecializa > tionDecl>( > Active->Entity)) { > Params = D->getTemplateParameters(); > } else if (auto *D = dyn_cast<VarTemplatePartialSpecializati > onDecl>( > @@ -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- > expansion.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/ > SemaTemplate/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/ > SemaTemplate/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_ > status.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_ > defects.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_ > defects.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_ > defects.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_ > defects.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