r290593 - DR1495: A partial specialization is ill-formed if it is not (strictly) more
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 27 10:41:23 PST 2016
On 27 Dec 2016 1:42 am, "Chandler Carruth via cfe-commits" <
cfe-commits at 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 at 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 at -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 at -2 2 {{variadic templates are a C++11 extension}}
> + // expected-warning at -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 at -1 {{not more specialized than the primary}}
> + // expected-note at -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 at -1 {{not more specialized than the primary}}
> + // expected-note at -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 at -1 {{not more specialized than the primary}}
> + // expected-note at -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 at -1 {{not more specialized than the primary}}
> + // expected-note at -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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161227/b42f9272/attachment-0001.html>
More information about the cfe-commits
mailing list