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