<div dir="ltr">Thanks both of you, r<span style="color:rgb(0,0,0)">290807.</span></div><div class="gmail_extra"><br><div class="gmail_quote">On 1 January 2017 at 07:28, Erik Pilkington <span dir="ltr"><<a href="mailto:erik.pilkington@gmail.com" target="_blank">erik.pilkington@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br>
> On Dec 31, 2016, at 4:41 PM, Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
><br>
> Author: rsmith<br>
> Date: Sat Dec 31 15:41:23 2016<br>
> New Revision: 290792<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=290792&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=290792&view=rev</a><br>
> Log:<br>
> [c++17] Implement P0522R0 as written. This allows a template template argument<br>
> to be specified for a template template parameter whenever the parameter is at<br>
> least as specialized as the argument (when there's an obvious and correct<br>
> mapping from uses of the parameter to uses of the argument). For example, a<br>
> template with more parameters can be passed to a template template parameter<br>
> with fewer, if those trailing parameters have default arguments.<br>
><br>
> This is disabled by default, despite being a DR resolution, as it's fairly<br>
> broken in its current state: there are no partial ordering rules to cope with<br>
> template template parameters that have different parameter lists, meaning that<br>
> code that attempts to decompose template-ids based on arity can hit unavoidable<br>
> ambiguity issues.<br>
><br>
> The diagnostics produced on a non-matching argument are also pretty bad right<br>
> now, but I aim to improve them in a subsequent commit.<br>
><br>
> Added:<br>
> cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template_cxx1z.cpp<br>
> Modified:<br>
> cfe/trunk/include/clang/Basic/<wbr>LangOptions.def<br>
> cfe/trunk/include/clang/<wbr>Driver/Options.td<br>
> cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
> cfe/trunk/lib/Driver/Tools.cpp<br>
> cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp<br>
> cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
> cfe/trunk/lib/Sema/<wbr>SemaTemplateDeduction.cpp<br>
> cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template.cpp<br>
> cfe/trunk/www/cxx_status.html<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/<wbr>LangOptions.def<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/LangOptions.def?<wbr>rev=290792&r1=290791&r2=<wbr>290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/Basic/<wbr>LangOptions.def (original)<br>
> +++ cfe/trunk/include/clang/Basic/<wbr>LangOptions.def Sat Dec 31 15:41:23 2016<br>
> @@ -134,6 +134,7 @@ LANGOPT(NoBuiltin , 1, 0, "disab<br>
> LANGOPT(NoMathBuiltin , 1, 0, "disable math builtin functions")<br>
> LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly")<br>
> LANGOPT(CoroutinesTS , 1, 0, "C++ coroutines TS")<br>
> +LANGOPT(<wbr>RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of tempalte template arguments")<br>
><br>
> BENIGN_LANGOPT(<wbr>ThreadsafeStatics , 1, 1, "thread-safe static initializers")<br>
> LANGOPT(POSIXThreads , 1, 0, "POSIX thread support")<br>
><br>
> Modified: cfe/trunk/include/clang/<wbr>Driver/Options.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Driver/Options.td?rev=<wbr>290792&r1=290791&r2=290792&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/<wbr>Driver/Options.td (original)<br>
> +++ cfe/trunk/include/clang/<wbr>Driver/Options.td Sat Dec 31 15:41:23 2016<br>
> @@ -1088,6 +1088,11 @@ def fapplication_extension : Flag<["-"],<br>
> HelpText<"Restrict code to those available for App Extensions">;<br>
> def fno_application_extension : Flag<["-"], "fno-application-extension">,<br>
> Group<f_Group>;<br>
> +def frelaxed_template_template_<wbr>args : Flag<["-"], "frelaxed-template-template-<wbr>args">,<br>
> + Flags<[CC1Option]>, HelpText<"Enable C++17 relaxed template template argument matching">,<br>
> + Group<f_Group>;<br>
> +def fno_relaxed_template_template_<wbr>args : Flag<["-"], "fno-relaxed-template-<wbr>template-args">,<br>
> + Group<f_Group>;<br>
> def fsized_deallocation : Flag<["-"], "fsized-deallocation">, Flags<[CC1Option]>,<br>
> HelpText<"Enable C++14 sized global deallocation functions">, Group<f_Group>;<br>
> def fno_sized_deallocation: Flag<["-"], "fno-sized-deallocation">, Group<f_Group>;<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=290792&<wbr>r1=290791&r2=290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Sat Dec 31 15:41:23 2016<br>
> @@ -6719,6 +6719,9 @@ public:<br>
> bool isMoreSpecializedThanPrimary(<wbr>VarTemplatePartialSpecializati<wbr>onDecl *T,<br>
> sema::TemplateDeductionInfo &Info);<br>
><br>
> + bool isTemplateTemplateParameterAtL<wbr>eastAsSpecializedAs(<br>
> + TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc);<br>
> +<br>
> void MarkUsedTemplateParameters(<wbr>const TemplateArgumentList &TemplateArgs,<br>
> bool OnlyDeduced,<br>
> unsigned Depth,<br>
><br>
> Modified: cfe/trunk/lib/Driver/Tools.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Driver/<wbr>Tools.cpp?rev=290792&r1=<wbr>290791&r2=290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Driver/Tools.cpp (original)<br>
> +++ cfe/trunk/lib/Driver/Tools.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -6020,6 +6020,13 @@ void Clang::ConstructJob(<wbr>Compilation &C,<br>
> options::OPT_fno_assume_sane_<wbr>operator_new))<br>
> CmdArgs.push_back("-fno-<wbr>assume-sane-operator-new");<br>
><br>
> + // -frelaxed-template-template-<wbr>args is off by default, as it is a severe<br>
> + // breaking change until a corresponding change to template partial ordering<br>
> + // is provided.<br>
> + if (Args.hasFlag(options::OPT_<wbr>frelaxed_template_template_<wbr>args,<br>
> + options::OPT_fno_relaxed_<wbr>template_template_args, false))<br>
> + CmdArgs.push_back("-frelaxed-<wbr>template-template-args");<br>
> +<br>
> // -fsized-deallocation is off by default, as it is an ABI-breaking change for<br>
> // most platforms.<br>
> if (Args.hasFlag(options::OPT_<wbr>fsized_deallocation,<br>
><br>
> Modified: cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Frontend/CompilerInvocation.<wbr>cpp?rev=290792&r1=290791&r2=<wbr>290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp (original)<br>
> +++ cfe/trunk/lib/Frontend/<wbr>CompilerInvocation.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -1960,6 +1960,8 @@ static void ParseLangArgs(LangOptions &O<br>
> if (!Opts.NoBuiltin)<br>
> getAllNoBuiltinFuncValues(<wbr>Args, Opts.NoBuiltinFuncs);<br>
> Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_<wbr>builtin);<br>
> + Opts.<wbr>RelaxedTemplateTemplateArgs =<br>
> + Args.hasArg(OPT_frelaxed_<wbr>template_template_args);<br>
> Opts.SizedDeallocation = Args.hasArg(OPT_fsized_<wbr>deallocation);<br>
> Opts.AlignedAllocation =<br>
> Args.hasFlag(OPT_faligned_<wbr>allocation, OPT_fno_aligned_allocation,<br>
><br>
> Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp?rev=290792&<wbr>r1=290791&r2=290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -5585,6 +5585,10 @@ ExprResult Sema::CheckTemplateArgument(N<br>
> return Arg;<br>
> }<br>
><br>
> +static void DiagnoseTemplateParameterListA<wbr>rityMismatch(<br>
> + Sema &S, TemplateParameterList *New, TemplateParameterList *Old,<br>
> + Sema::<wbr>TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc);<br>
> +<br>
> /// \brief Check a template argument against its corresponding<br>
> /// template template parameter.<br>
> ///<br>
> @@ -5601,6 +5605,9 @@ bool Sema::CheckTemplateArgument(<wbr>Templat<br>
> return false;<br>
> }<br>
><br>
> + if (Template->isInvalidDecl())<br>
> + return true;<br>
> +<br>
> // C++0x [temp.arg.template]p1:<br>
> // A template-argument for a template template-parameter shall be<br>
> // the name of a class template or an alias template, expressed as an<br>
> @@ -5628,6 +5635,25 @@ bool Sema::CheckTemplateArgument(<wbr>Templat<br>
> if (Param-><wbr>isExpandedParameterPack())<br>
> Params = Param-><wbr>getExpansionTemplateParameters<wbr>(ArgumentPackIndex);<br>
><br>
> + // C++1z [temp.arg.template]p3: (DR 150)<br>
> + // A template-argument matches a template template-parameter P when P<br>
> + // is at least as specialized as the template-argument A.<br>
> + if (getLangOpts().<wbr>RelaxedTemplateTemplateArgs) {<br>
> + // Quick check for the common case:<br>
> + // If P contains a parameter pack, then A [...] matches P if each of A's<br>
> + // template parameters matches the corresponding template parameter in<br>
> + // the template-parameter-list of P.<br>
> + if (<wbr>TemplateParameterListsAreEqual<wbr>(<br>
> + Template-><wbr>getTemplateParameters(), Params, false,<br>
> + TPL_<wbr>TemplateTemplateArgumentMatch, Arg.getLocation()))<br>
> + return false;<br>
> +<br>
> + if (<wbr>isTemplateTemplateParameterAtL<wbr>eastAsSpecializedAs(Params, Template,<br>
> + Arg.getLocation()))<br>
> + return false;<br>
> + // FIXME: Produce better diagnostics for deduction failures.<br>
> + }<br>
> +<br>
> return !<wbr>TemplateParameterListsAreEqual<wbr>(Template-><wbr>getTemplateParameters(),<br>
> Params,<br>
> true,<br>
> @@ -5839,7 +5865,7 @@ static bool MatchTemplateParameterKind(S<br>
> return false;<br>
> }<br>
><br>
> - // Check that both are parameter packs are neither are parameter packs.<br>
> + // Check that both are parameter packs or neither are parameter packs.<br>
> // However, if we are matching a template template argument to a<br>
> // template template parameter, the template template parameter can have<br>
> // a parameter pack where the template template argument does not.<br>
><br>
> Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplateDeduction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplateDeduction.cpp?rev=<wbr>290792&r1=290791&r2=290792&<wbr>view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/lib/Sema/<wbr>SemaTemplateDeduction.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/<wbr>SemaTemplateDeduction.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -1898,11 +1898,11 @@ DeduceTemplateArguments(Sema &S, Templat<br>
> return NumberOfArgumentsMustMatch ? Sema::TDK_TooFewArguments<br>
> : Sema::TDK_Success;<br>
><br>
> - if (Args[ArgIdx].isPackExpansion(<wbr>)) {<br>
> - // FIXME: We follow the logic of C++0x [temp.deduct.type]p22 here,<br>
> - // but applied to pack expansions that are template arguments.<br>
> + // C++1z [temp.deduct.type]p9:<br>
> + // During partial ordering, if Ai was originally a pack expansion [and]<br>
> + // Pi is not a pack expansion, template argument deduction fails.<br>
> + if (Args[ArgIdx].isPackExpansion(<wbr>))<br>
> return Sema::TDK_<wbr>MiscellaneousDeductionFailure;<br>
> - }<br>
><br>
> // Perform deduction for this Pi/Ai pair.<br>
> if (Sema::TemplateDeductionResult Result<br>
> @@ -1965,7 +1965,8 @@ DeduceTemplateArguments(Sema &S,<br>
> TemplateDeductionInfo &Info,<br>
> SmallVectorImpl<<wbr>DeducedTemplateArgument> &Deduced) {<br>
> return DeduceTemplateArguments(S, TemplateParams, ParamList.asArray(),<br>
> - ArgList.asArray(), Info, Deduced, false);<br>
> + ArgList.asArray(), Info, Deduced,<br>
> + /*NumberOfArgumentsMustMatch*/<wbr>false);<br>
> }<br>
><br>
> /// \brief Determine whether two template arguments are the same.<br>
> @@ -4581,13 +4582,13 @@ UnresolvedSetIterator Sema::getMostSpeci<br>
> /// Determine whether one partial specialization, P1, is at least as<br>
> /// specialized than another, P2.<br>
> ///<br>
> -/// \tparam PartialSpecializationDecl The kind of P2, which must be a<br>
> -/// {Class,Var}Template{<wbr>PartialSpecialization,}Decl.<br>
> +/// \tparam TemplateLikeDecl The kind of P2, which must be a<br>
> +/// TemplateDecl or {Class,Var}<wbr>TemplatePartialSpecializationD<wbr>ecl.<br>
> /// \param T1 The injected-class-name of P1 (faked for a variable template).<br>
> /// \param T2 The injected-class-name of P2 (faked for a variable template).<br>
> -template<typename PartialSpecializationDecl><br>
> +template<typename TemplateLikeDecl><br>
> static bool isAtLeastAsSpecializedAs(Sema &S, QualType T1, QualType T2,<br>
> - PartialSpecializationDecl *P2,<br>
> + TemplateLikeDecl *P2,<br>
> TemplateDeductionInfo &Info) {<br>
> // C++ [temp.class.order]p1:<br>
> // For two class template partial specializations, the first is at least as<br>
> @@ -4729,6 +4730,72 @@ bool Sema::<wbr>isMoreSpecializedThanPrimary(<br>
> return true;<br>
> }<br>
><br>
> +bool Sema::<wbr>isTemplateTemplateParameterAtL<wbr>eastAsSpecializedAs(<br>
> + TemplateParameterList *P, TemplateDecl *AArg, SourceLocation Loc) {<br>
> + // C++1z [temp.arg.template]p4: (DR 150)<br>
> + // A template template-parameter P is at least as specialized as a<br>
> + // template template-argument A if, given the following rewrite to two<br>
> + // function templates...<br>
> +<br>
> + // Rather than synthesize function templates, we merely perform the<br>
> + // equivalent partial ordering by performing deduction directly on<br>
> + // the template parameter lists of the template template parameters.<br>
> + //<br>
> + // Given an invented class template X with the template parameter list of<br>
> + // A (including default arguments):<br>
> + TemplateName X = Context.<wbr>getCanonicalTemplateName(<wbr>TemplateName(AArg));<br>
> + TemplateParameterList *A = AArg->getTemplateParameters();<br>
> +<br>
> + // - Each function template has a single function parameter whose type is<br>
> + // a specialization of X with template arguments corresponding to the<br>
> + // template parameters from the respective function template<br>
> + SmallVector<TemplateArgument, 8> AArgs;<br>
> + Context.<wbr>getInjectedTemplateArgs(A, AArgs);<br>
> +<br>
> + // Check P's arguments against A's parameter list. This will fill in default<br>
> + // template arguments as needed. AArgs are already correct by construction.<br>
> + // We can't just use CheckTemplateIdType because that will expand alias<br>
> + // templates.<br>
> + SmallVector<TemplateArgument, 4> PArgs;<br>
> + {<br>
> + SFINAETrap Trap(*this);<br>
> +<br>
> + Context.<wbr>getInjectedTemplateArgs(P, PArgs);<br>
> + TemplateArgumentListInfo PArgList(P->getLAngleLoc(), P->getRAngleLoc());<br>
> + for (unsigned I = 0, N = P->size(); I != N; ++I) {<br>
> + // Unwrap packs that getInjectedTemplateArgs wrapped around pack<br>
> + // expansions, to form an "as written" argument list.<br>
> + TemplateArgument Arg = PArgs[I];<br>
> + if (Arg.getKind() == TemplateArgument::Pack) {<br>
> + assert(Arg.pack_size() == 1 && Arg.pack_begin()-><wbr>isPackExpansion());<br>
> + Arg = *Arg.pack_begin();<br>
> + }<br>
> + PArgList.addArgument(<wbr>getTrivialTemplateArgumentLoc(<br>
> + Arg, QualType(), P->getParam(I)->getLocation())<wbr>);<br>
> + }<br>
> + PArgs.clear();<br>
> +<br>
> + // C++1z [temp.arg.template]p3:<br>
> + // If the rewrite produces an invalid type, then P is not at least as<br>
> + // specialized as A.<br>
> + if (CheckTemplateArgumentList(<wbr>AArg, Loc, PArgList, false, PArgs) ||<br>
> + Trap.hasErrorOccurred())<br>
> + return false;<br>
> + }<br>
> +<br>
> + QualType AType = Context.<wbr>getTemplateSpecializationType(<wbr>X, AArgs);<br>
> + QualType PType = Context.<wbr>getTemplateSpecializationType(<wbr>X, PArgs);<br>
> +<br>
> + SmallVector<<wbr>DeducedTemplateArgument, 4> Deduced;<br>
> + Deduced.resize(A->size());<br>
<br>
</div></div>Looks like Deduced is unused here!<br>
<div class="HOEnZb"><div class="h5"><br>
> +<br>
> + // ... the function template corresponding to P is at least as specialized<br>
> + // as the function template corresponding to A according to the partial<br>
> + // ordering rules for function templates.<br>
> + TemplateDeductionInfo Info(Loc, A->getDepth());<br>
> + return isAtLeastAsSpecializedAs(*<wbr>this, PType, AType, AArg, Info);<br>
> +}<br>
> +<br>
> static void<br>
> MarkUsedTemplateParameters(<wbr>ASTContext &Ctx,<br>
> const TemplateArgument &TemplateArg,<br>
><br>
> Modified: cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template.cpp?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaTemplate/temp_arg_<wbr>template.cpp?rev=290792&r1=<wbr>290791&r2=290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template.cpp (original)<br>
> +++ cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -6,11 +6,12 @@ template<template<typename T> class X> s<br>
><br>
> template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}<br>
><br>
> -template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}}<br>
> +template<template<int I> class X> struct C; // expected-note 2{{previous non-type template parameter with type 'int' is here}}<br>
><br>
> template<class> struct X; // expected-note{{too few template parameters in template template argument}}<br>
> template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}}<br>
> template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}}<br>
> +template<const int &N> struct Yref; // expected-note{{template non-type parameter has a different type 'const int &' in template argument}}<br>
><br>
> namespace N {<br>
> template<class> struct Z;<br>
> @@ -27,6 +28,7 @@ A<TooMany> *a5; // expected-error{{templ<br>
> B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}<br>
> C<Y> *a7;<br>
> C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}<br>
> +C<Yref> *a9; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}<br>
><br>
> template<typename T> void f(int);<br>
><br>
><br>
> Added: cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template_cxx1z.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template_cxx1z.cpp?rev=290792&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaTemplate/temp_arg_<wbr>template_cxx1z.cpp?rev=290792&<wbr>view=auto</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template_cxx1z.cpp (added)<br>
> +++ cfe/trunk/test/SemaTemplate/<wbr>temp_arg_template_cxx1z.cpp Sat Dec 31 15:41:23 2016<br>
> @@ -0,0 +1,102 @@<br>
> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -frelaxed-template-template-<wbr>args %s<br>
> +<br>
> +// expected-note@temp_arg_<wbr>template_cxx1z.cpp:* 1+{{}}<br>
> +<br>
> +template<template<int> typename> struct Ti;<br>
> +template<template<int...> typename> struct TPi;<br>
> +template<template<int, int...> typename> struct TiPi;<br>
> +template<template<int..., int...> typename> struct TPiPi; // FIXME: Why is this not ill-formed?<br>
> +<br>
> +template<typename T, template<T> typename> struct tT0;<br>
> +template<template<typename T, T> typename> struct Tt0;<br>
> +<br>
> +template<template<typename> typename> struct Tt;<br>
> +template<template<typename, typename...> typename> struct TtPt;<br>
> +<br>
> +template<int> struct i;<br>
> +template<int, int = 0> struct iDi;<br>
> +template<int, int> struct ii;<br>
> +template<int...> struct Pi;<br>
> +template<int, int, int...> struct iiPi;<br>
> +<br>
> +template<int, typename = int> struct iDt;<br>
> +template<int, typename> struct it;<br>
> +<br>
> +template<typename T, T v> struct t0;<br>
> +<br>
> +template<typename...> struct Pt;<br>
> +<br>
> +namespace IntParam {<br>
> + using ok = Pt<Ti<i>,<br>
> + Ti<iDi>,<br>
> + Ti<Pi>,<br>
> + Ti<iDt>>;<br>
> + using err1 = Ti<ii>; // expected-error {{different template parameters}}<br>
> + using err2 = Ti<iiPi>; // expected-error {{different template parameters}}<br>
> + using err3 = Ti<t0>; // expected-error {{different template parameters}}<br>
> + using err4 = Ti<it>; // expected-error {{different template parameters}}<br>
> +}<br>
> +<br>
> +// These are accepted by the backwards-compatibility "parameter pack in<br>
> +// parameter matches any number of parameters in arguments" rule.<br>
> +namespace IntPackParam {<br>
> + using ok = TPi<Pi>;<br>
> + using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;<br>
> + using err1 = TPi<t0>; // expected-error {{different template parameters}}<br>
> + using err2 = TPi<iDt>; // expected-error {{different template parameters}}<br>
> + using err3 = TPi<it>; // expected-error {{different template parameters}}<br>
> +}<br>
> +<br>
> +namespace IntAndPackParam {<br>
> + using ok = TiPi<Pi>;<br>
> + using ok_compat = Pt<TiPi<ii>, TiPi<iDi>, TiPi<iiPi>>;<br>
> + using err = TiPi<iDi>;<br>
> +}<br>
> +<br>
> +namespace DependentType {<br>
> + using ok = Pt<tT0<int, i>, tT0<int, iDi>>;<br>
> + using err1 = tT0<int, ii>; // expected-error {{different template parameters}}<br>
> + using err2 = tT0<short, i>; // FIXME: should this be OK?<br>
> + using err2a = tT0<long long, i>; // FIXME: should this be OK (if long long is larger than int)?<br>
> + using err2b = tT0<void*, i>; // expected-error {{different template parameters}}<br>
> + using err3 = tT0<short, t0>; // expected-error {{different template parameters}}<br>
> +<br>
> + using ok2 = Tt0<t0>;<br>
> + using err4 = Tt0<it>; // expected-error {{different template parameters}}<br>
> +}<br>
> +<br>
> +namespace Auto {<br>
> + template<template<int> typename T> struct TInt {};<br>
> + template<template<int*> typename T> struct TIntPtr {};<br>
> + template<template<auto> typename T> struct TAuto {};<br>
> + template<template<auto*> typename T> struct TAutoPtr {};<br>
> + template<auto> struct Auto;<br>
> + template<auto*> struct AutoPtr;<br>
> + template<int> struct Int;<br>
> + template<int*> struct IntPtr;<br>
> +<br>
> + TInt<Auto> ia;<br>
> + TInt<AutoPtr> iap; // FIXME: ill-formed<br>
> + TInt<Int> ii;<br>
> + TInt<IntPtr> iip; // expected-error {{different template parameters}}<br>
> +<br>
> + TIntPtr<Auto> ipa;<br>
> + TIntPtr<AutoPtr> ipap;<br>
> + TIntPtr<Int> ipi; // expected-error {{different template parameters}}<br>
> + TIntPtr<IntPtr> ipip;<br>
> +<br>
> + TAuto<Auto> aa;<br>
> + TAuto<AutoPtr> aap; // FIXME: ill-formed<br>
> + TAuto<Int> ai; // FIXME: ill-formed<br>
> + TAuto<IntPtr> aip; // FIXME: ill-formed<br>
> +<br>
> + TAutoPtr<Auto> apa;<br>
> + TAutoPtr<AutoPtr> apap;<br>
> + TAutoPtr<Int> api; // FIXME: ill-formed<br>
> + TAutoPtr<IntPtr> apip; // FIXME: ill-formed<br>
> +<br>
> + int n;<br>
> + template<auto A, decltype(A) B = &n> struct SubstFailure;<br>
> + TInt<SubstFailure> isf; // expected-error {{different template parameters}}<br>
> + TIntPtr<SubstFailure> ipsf; // expected-error {{different template parameters}}<br>
> +}<br>
><br>
> Modified: cfe/trunk/www/cxx_status.html<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=290792&r1=290791&r2=290792&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/www/cxx_<wbr>status.html?rev=290792&r1=<wbr>290791&r2=290792&view=diff</a><br>
> ==============================<wbr>==============================<wbr>==================<br>
> --- cfe/trunk/www/cxx_status.html (original)<br>
> +++ cfe/trunk/www/cxx_status.html Sat Dec 31 15:41:23 2016<br>
> @@ -733,7 +733,7 @@ as the draft C++1z standard evolves.<br>
> <tr><br>
> <td>Matching template template parameters to compatible arguments</td><br>
> <td><a href="<a href="http://wg21.link/p0522r0" rel="noreferrer" target="_blank">http://wg21.link/p0522r0</a><wbr>">P0522R0</a></td><br>
> - <td class="none" align="center">No <a href="#p0522">(12)</a></td><br>
> + <td class="partial" align="center">Partial <a href="#p0522">(12)</a></td><br>
> </tr><br>
> <tr><br>
> <td>Removing deprecated dynamic exception specifications</td><br>
> @@ -763,8 +763,12 @@ left to right in the callee. As a result<br>
> functions using expression syntax are no longer guaranteed to be destroyed in<br>
> reverse construction order in that ABI.<br>
> </span><br><br>
> -<span id="p0522">(12): This is the resolution to a Defect Report, so will be<br>
> -applied to all language versions.<br>
> +<span id="p0522">(12): Despite being the the resolution to a Defect Report, this<br>
> +feature is disabled by default in all language versions, and can be enabled<br>
> +explicitly with the flag <tt>-frelaxed-template-<wbr>template-args</tt>. The change<br>
> +to the standard lacks a corresponding change for template partial ordering,<br>
> +resulting in ambiguity errors for reasonable and previously-valid code. This<br>
> +issue is expected to be rectified soon.<br>
> </span><br>
> </p><br>
> </details><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
<br>
</div></div></blockquote></div><br></div>