https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/111894
>From c15f2faaa2cdc2c6516899c1c0e3c0d90f74f1eb Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <mizve...@gmail.com> Date: Thu, 10 Oct 2024 15:40:48 -0300 Subject: [PATCH] [clang] Remove the deprecated flag `-frelaxed-template-template-args`. This flag has been deprecated since Clang 19, having been the default since then. It has remained because its negation was still useful to work around backwards compatibility breaking changes from P0522. However, in Clang 20 we have landed various changes which implemented P3310R2 and beyond, which solve almost all of the expected issues, the known remaining few being a bit obscure. So this change removes the flag completely and all of its implementation and support code. Hopefully any remaining users can just stop using the flag. If there are still important issues remaining, this removal will also shake the tree and help us know. --- clang/docs/ReleaseNotes.rst | 5 + .../clang/Basic/DiagnosticDriverKinds.td | 3 - clang/include/clang/Basic/DiagnosticGroups.td | 2 - clang/include/clang/Basic/LangOptions.def | 1 - clang/include/clang/Driver/Options.td | 5 - clang/include/clang/Sema/Sema.h | 11 -- clang/lib/Driver/ToolChains/Clang.cpp | 14 -- clang/lib/Frontend/InitPreprocessor.cpp | 4 +- clang/lib/Sema/SemaTemplate.cpp | 108 ++++------ .../frelaxed-template-template-args.cpp | 9 - clang/test/Lexer/cxx-features.cpp | 5 +- clang/test/SemaTemplate/cwg2398.cpp | 185 +++++++----------- clang/www/cxx_status.html | 4 +- 13 files changed, 113 insertions(+), 243 deletions(-) delete mode 100644 clang/test/Driver/frelaxed-template-template-args.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7fafe2807bd388..6397d43616fdde 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -73,6 +73,11 @@ C++17 Feature Support Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- The flag `-frelaxed-template-template-args` + and its negation have been removed, having been deprecated since the previous + two releases. The improvements to template template parameter matching implemented + in the previous release, as described in P3310 and P3579, made this flag unnecessary. + C Language Changes ------------------ diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 288786b8ce9399..8d599c96eb4fbf 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -445,9 +445,6 @@ def warn_drv_clang_unsupported : Warning< "the clang compiler does not support '%0'">; def warn_drv_deprecated_arg : Warning< "argument '%0' is deprecated%select{|, use '%2' instead}1">, InGroup<Deprecated>; -def warn_drv_deprecated_arg_no_relaxed_template_template_args : Warning< - "argument '-fno-relaxed-template-template-args' is deprecated">, - InGroup<DeprecatedNoRelaxedTemplateTemplateArgs>; def warn_drv_deprecated_arg_ofast : Warning< "argument '-Ofast' is deprecated; use '-O3 -ffast-math' for the same behavior," " or '-O3' to enable only conforming optimizations">, diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 209792f851b6ae..527e588d46a049 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -102,7 +102,6 @@ def EnumConversion : DiagGroup<"enum-conversion", [EnumEnumConversion, EnumFloatConversion, EnumCompareConditional]>; -def DeprecatedNoRelaxedTemplateTemplateArgs : DiagGroup<"deprecated-no-relaxed-template-template-args">; def DeprecatedOFast : DiagGroup<"deprecated-ofast">; def ObjCSignedCharBoolImplicitIntConversion : DiagGroup<"objc-signed-char-bool-implicit-int-conversion">; @@ -230,7 +229,6 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion, DeprecatedLiteralOperator, DeprecatedPragma, DeprecatedRegister, - DeprecatedNoRelaxedTemplateTemplateArgs, DeprecatedOFast, DeprecatedThisCapture, DeprecatedType, diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 1bcec212fd332e..cb55f09acc076c 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -160,7 +160,6 @@ LANGOPT(GNUAsm , 1, 1, "GNU-style inline assembly") LANGOPT(Coroutines , 1, 0, "C++20 coroutines") LANGOPT(CoroAlignedAllocation, 1, 0, "prefer Aligned Allocation according to P2014 Option 2") LANGOPT(DllExportInlines , 1, 1, "dllexported classes dllexport inline methods") -LANGOPT(RelaxedTemplateTemplateArgs, 1, 1, "C++17 relaxed matching of template template arguments") LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features") LANGOPT(RetainSubstTemplateTypeParmTypeAstNodes, 1, 0, "retain SubstTemplateTypeParmType nodes in the AST's representation of alias template specializations") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1af633e59d0bba..ba5600e1912a63 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3557,11 +3557,6 @@ defm application_extension : BoolFOption<"application-extension", PosFlag<SetTrue, [], [ClangOption, CC1Option], "Restrict code to those available for App Extensions">, NegFlag<SetFalse>>; -defm relaxed_template_template_args : BoolFOption<"relaxed-template-template-args", - LangOpts<"RelaxedTemplateTemplateArgs">, DefaultTrue, - PosFlag<SetTrue, [], [], "Enable">, - NegFlag<SetFalse, [], [CC1Option], "Disable">, - BothFlags<[], [ClangOption], " C++17 relaxed template template argument matching">>; defm retain_subst_template_type_parm_type_ast_nodes : BoolFOption<"retain-subst-template-type-parm-type-ast-nodes", LangOpts<"RetainSubstTemplateTypeParmTypeAstNodes">, DefaultFalse, PosFlag<SetTrue, [], [CC1Option], "Enable">, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d0fc735be5f763..6b4959f972cfe5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11837,17 +11837,6 @@ class Sema final : public SemaBase { /// \endcode TPL_TemplateTemplateParmMatch, - /// We are matching the template parameter lists of a template - /// template argument against the template parameter lists of a template - /// template parameter. - /// - /// \code - /// template<template<int Value> class Metafun> struct X; - /// template<int Value> struct integer_c; - /// X<integer_c> xic; - /// \endcode - TPL_TemplateTemplateArgumentMatch, - /// We are determining whether the template-parameters are equivalent /// according to C++ [temp.over.link]/6. This comparison does not consider /// constraints. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 589de953be5be1..70e5e9847dff6f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7502,20 +7502,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.addOptOutFlag(CmdArgs, options::OPT_fassume_unique_vtables, options::OPT_fno_assume_unique_vtables); - // -frelaxed-template-template-args is deprecated. - if (Arg *A = - Args.getLastArg(options::OPT_frelaxed_template_template_args, - options::OPT_fno_relaxed_template_template_args)) { - if (A->getOption().matches( - options::OPT_fno_relaxed_template_template_args)) { - D.Diag(diag::warn_drv_deprecated_arg_no_relaxed_template_template_args); - CmdArgs.push_back("-fno-relaxed-template-template-args"); - } else { - D.Diag(diag::warn_drv_deprecated_arg) - << A->getAsString(Args) << /*hasReplacement=*/false; - } - } - // -fsized-deallocation is on by default in C++14 onwards and otherwise off // by default. Args.addLastArg(CmdArgs, options::OPT_fsized_deallocation, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 542e26b6a129b4..77833f5d1defb2 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -729,8 +729,8 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, } if (LangOpts.AlignedAllocation && !LangOpts.AlignedAllocationUnavailable) Builder.defineMacro("__cpp_aligned_new", "201606L"); - if (LangOpts.RelaxedTemplateTemplateArgs) - Builder.defineMacro("__cpp_template_template_args", "201611L"); + + Builder.defineMacro("__cpp_template_template_args", "201611L"); // C++20 features. if (LangOpts.CPlusPlus20) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3944c4f67bab9a..35ece88c603ddd 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -7399,11 +7399,6 @@ bool Sema::CheckTemplateTemplateArgument( << Template; } - if (!getLangOpts().RelaxedTemplateTemplateArgs) - return !TemplateParameterListsAreEqual( - Template->getTemplateParameters(), Params, /*Complain=*/true, - TPL_TemplateTemplateArgumentMatch, Arg.getLocation()); - // 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. @@ -7775,9 +7770,7 @@ static bool MatchTemplateParameterKind( // 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. - if (Old->isTemplateParameterPack() != New->isTemplateParameterPack() && - !(Kind == Sema::TPL_TemplateTemplateArgumentMatch && - Old->isTemplateParameterPack())) { + if (Old->isTemplateParameterPack() != New->isTemplateParameterPack()) { if (Complain) { unsigned NextDiag = diag::err_template_parameter_pack_non_pack; if (TemplateArgLoc.isValid()) { @@ -7803,37 +7796,28 @@ static bool MatchTemplateParameterKind( = dyn_cast<NonTypeTemplateParmDecl>(Old)) { NonTypeTemplateParmDecl *NewNTTP = cast<NonTypeTemplateParmDecl>(New); - // If we are matching a template template argument to a template - // template parameter and one of the non-type template parameter types - // is dependent, then we must wait until template instantiation time - // to actually compare the arguments. - if (Kind != Sema::TPL_TemplateTemplateArgumentMatch || - (!OldNTTP->getType()->isDependentType() && - !NewNTTP->getType()->isDependentType())) { - // C++20 [temp.over.link]p6: - // Two [non-type] template-parameters are equivalent [if] they have - // equivalent types ignoring the use of type-constraints for - // placeholder types - QualType OldType = S.Context.getUnconstrainedType(OldNTTP->getType()); - QualType NewType = S.Context.getUnconstrainedType(NewNTTP->getType()); - if (!S.Context.hasSameType(OldType, NewType)) { - if (Complain) { - unsigned NextDiag = diag::err_template_nontype_parm_different_type; - if (TemplateArgLoc.isValid()) { - S.Diag(TemplateArgLoc, - diag::err_template_arg_template_params_mismatch); - NextDiag = diag::note_template_nontype_parm_different_type; - } - S.Diag(NewNTTP->getLocation(), NextDiag) - << NewNTTP->getType() - << (Kind != Sema::TPL_TemplateMatch); - S.Diag(OldNTTP->getLocation(), - diag::note_template_nontype_parm_prev_declaration) - << OldNTTP->getType(); + // C++20 [temp.over.link]p6: + // Two [non-type] template-parameters are equivalent [if] they have + // equivalent types ignoring the use of type-constraints for + // placeholder types + QualType OldType = S.Context.getUnconstrainedType(OldNTTP->getType()); + QualType NewType = S.Context.getUnconstrainedType(NewNTTP->getType()); + if (!S.Context.hasSameType(OldType, NewType)) { + if (Complain) { + unsigned NextDiag = diag::err_template_nontype_parm_different_type; + if (TemplateArgLoc.isValid()) { + S.Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_nontype_parm_different_type; } - - return false; + S.Diag(NewNTTP->getLocation(), NextDiag) + << NewNTTP->getType() << (Kind != Sema::TPL_TemplateMatch); + S.Diag(OldNTTP->getLocation(), + diag::note_template_nontype_parm_prev_declaration) + << OldNTTP->getType(); } + + return false; } } // For template template parameters, check the template parameter types. @@ -7853,7 +7837,6 @@ static bool MatchTemplateParameterKind( } if (Kind != Sema::TPL_TemplateParamsEquivalent && - Kind != Sema::TPL_TemplateTemplateArgumentMatch && !isa<TemplateTemplateParmDecl>(Old)) { const Expr *NewC = nullptr, *OldC = nullptr; @@ -7924,7 +7907,7 @@ bool Sema::TemplateParameterListsAreEqual( const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New, const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain, TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) { - if (Old->size() != New->size() && Kind != TPL_TemplateTemplateArgumentMatch) { + if (Old->size() != New->size()) { if (Complain) DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, TemplateArgLoc); @@ -7941,40 +7924,18 @@ bool Sema::TemplateParameterListsAreEqual( TemplateParameterList::iterator NewParm = New->begin(); TemplateParameterList::iterator NewParmEnd = New->end(); for (TemplateParameterList::iterator OldParm = Old->begin(), - OldParmEnd = Old->end(); - OldParm != OldParmEnd; ++OldParm) { - if (Kind != TPL_TemplateTemplateArgumentMatch || - !(*OldParm)->isTemplateParameterPack()) { - if (NewParm == NewParmEnd) { - if (Complain) - DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, - TemplateArgLoc); - - return false; - } - - if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, - OldInstFrom, Complain, Kind, - TemplateArgLoc)) - return false; - - ++NewParm; - continue; - } - - // C++0x [temp.arg.template]p3: - // [...] When P's template- parameter-list contains a template parameter - // pack (14.5.3), the template parameter pack will match zero or more - // template parameters or template parameter packs in the - // template-parameter-list of A with the same type and form as the - // template parameter pack in P (ignoring whether those template - // parameters are template parameter packs). - for (; NewParm != NewParmEnd; ++NewParm) { - if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, - OldInstFrom, Complain, Kind, - TemplateArgLoc)) - return false; + OldParmEnd = Old->end(); + OldParm != OldParmEnd; ++OldParm, ++NewParm) { + if (NewParm == NewParmEnd) { + if (Complain) + DiagnoseTemplateParameterListArityMismatch(*this, New, Old, Kind, + TemplateArgLoc); + return false; } + if (!MatchTemplateParameterKind(*this, *NewParm, NewInstFrom, *OldParm, + OldInstFrom, Complain, Kind, + TemplateArgLoc)) + return false; } // Make sure we exhausted all of the arguments. @@ -7986,8 +7947,7 @@ bool Sema::TemplateParameterListsAreEqual( return false; } - if (Kind != TPL_TemplateTemplateArgumentMatch && - Kind != TPL_TemplateParamsEquivalent) { + if (Kind != TPL_TemplateParamsEquivalent) { const Expr *NewRC = New->getRequiresClause(); const Expr *OldRC = Old->getRequiresClause(); diff --git a/clang/test/Driver/frelaxed-template-template-args.cpp b/clang/test/Driver/frelaxed-template-template-args.cpp deleted file mode 100644 index 7a7fd6f0bbc8f9..00000000000000 --- a/clang/test/Driver/frelaxed-template-template-args.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang -fsyntax-only -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEF %s -// RUN: %clang -fsyntax-only -frelaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-ON %s -// RUN: %clang -fsyntax-only -fno-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-OFF %s -// RUN: %clang -fsyntax-only -fno-relaxed-template-template-args -Wno-deprecated-no-relaxed-template-template-args %s 2>&1 | FileCheck --check-prefix=CHECK-DIS --allow-empty %s - -// CHECK-DEF-NOT: "-cc1"{{.*}} "-fno-relaxed-template-template-args" -// CHECK-ON: warning: argument '-frelaxed-template-template-args' is deprecated [-Wdeprecated] -// CHECK-OFF: warning: argument '-fno-relaxed-template-template-args' is deprecated [-Wdeprecated-no-relaxed-template-template-args] -// CHECK-DIS-NOT: warning: argument '-fno-relaxed-template-template-args' is deprecated diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index 3a60318d3f2317..b423e94b26acad 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -7,7 +7,6 @@ // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify %s // -// RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -fno-relaxed-template-template-args -DNO_RELAXED_TEMPLATE_TEMPLATE_ARGS=1 -verify %s // RUN: %clang_cc1 -std=c++17 -fcxx-exceptions -DCONCEPTS_TS=1 -verify %s // RUN: %clang_cc1 -std=c++14 -fno-rtti -fno-threadsafe-statics -verify %s -DNO_EXCEPTIONS -DNO_RTTI -DNO_THREADSAFE_STATICS // RUN: %clang_cc1 -std=c++14 -fchar8_t -DNO_EXCEPTIONS -DCHAR8_T -verify %s @@ -239,9 +238,7 @@ #error "wrong value for __cpp_nontype_template_args" #endif -#if !defined(NO_RELAXED_TEMPLATE_TEMPLATE_ARGS) \ - ? check(template_template_args, 201611, 201611, 201611, 201611, 201611, 201611, 201611) \ - : check(template_template_args, 0, 0, 0, 0, 0, 0, 0) +#if check(template_template_args, 201611, 201611, 201611, 201611, 201611, 201611, 201611) #error "wrong value for __cpp_template_template_args" #endif diff --git a/clang/test/SemaTemplate/cwg2398.cpp b/clang/test/SemaTemplate/cwg2398.cpp index dccb17c48d3256..1728f90af287b0 100644 --- a/clang/test/SemaTemplate/cwg2398.cpp +++ b/clang/test/SemaTemplate/cwg2398.cpp @@ -1,14 +1,12 @@ -// RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -verify=expected,new -// RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -fno-relaxed-template-template-args -verify=expected,old +// RUN: %clang_cc1 %s -fsyntax-only -std=c++23 -verify namespace issue1 { template<class T, class U = T> class B {}; template<template<class> class P, class T> void f(P<T>); - // new-note@-1 {{deduced type 'B<[...], (default) int>' of 1st parameter does not match adjusted type 'B<[...], float>' of argument [with P = B, T = int]}} - // old-note@-2 2{{template template argument has different template parameters}} + // expected-note@-1 {{deduced type 'B<[...], (default) int>' of 1st parameter does not match adjusted type 'B<[...], float>' of argument [with P = B, T = int]}} void g() { - f(B<int>()); // old-error {{no matching function for call}} + f(B<int>()); f(B<int,float>()); // expected-error {{no matching function for call}} } } // namespace issue1 @@ -116,41 +114,32 @@ namespace gcc_issue { template<class T1, class T2> struct A; template<template<class T1> class TT1, class T2> struct A<TT1<T2>, typename TT1<T2>::type>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class T3, class T4> class TT2, class T5, class T6> struct A<TT2<T5, T6>, typename TT2<T5, T5>::type>; - // new-note@-1 {{partial specialization matches}} - // old-note@-2 {{template is declared here}} + // expected-note@-1 {{partial specialization matches}} template <class T7, class T8 = T7> struct B { using type = int; }; template struct A<B<int>, int>; - // new-error@-1 {{ambiguous partial specializations}} - // old-error@-2 {{explicit instantiation of undefined template}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace gcc_issue namespace ttp_defaults { template <template <class T1> class TT1> struct A {}; - // old-note@-1 2{{previous template template parameter}} template <template <class T2> class TT2> void f(A<TT2>); - // new-note@-1 {{explicit instantiation candidate}} - // old-note@-2 {{invalid explicitly-specified argument for template parameter 'TT2'}} + // expected-note@-1 {{explicit instantiation candidate}} // FIXME: The default arguments on the TTP are not available during partial ordering. template <template <class T3, class T4 = float> class TT3> void f(A<TT3>) {}; - // new-note@-1 {{explicit instantiation candidate}} - // old-error@-2 {{template template argument has different template parameters}} - // old-note@-3 {{too many template parameters}} + // expected-note@-1 {{explicit instantiation candidate}} template <class T5, class T6 = int> struct B; - // old-note@-1 {{too many template parameters}} template void f<B>(A<B>); - // new-error@-1 {{partial ordering for explicit instantiation of 'f' is ambiguous}} - // old-error@-2 {{template template argument has different template parameters}} - // old-error@-3 {{explicit instantiation of 'f' does not refer to a function template}} + // expected-error@-1 {{partial ordering for explicit instantiation of 'f' is ambiguous}} } // namespace ttp_defaults namespace ttp_only { @@ -193,16 +182,16 @@ namespace consistency { template<template<class, class> class TT1, class T1, class T2, class T3, class T4> struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T4>>::type> {}; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class> class UU1, template<class> class UU2, class U1, class U2> struct A<UU1<U1>, UU2<U2>, typename nondeduced<UU1<U1>>::type>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template struct A<B<int>, B<int>, B<int>>; - // new-error@-1 {{ambiguous partial specializations}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace t2 namespace t3 { template<class T1, class T2, class T3> struct A; @@ -210,15 +199,15 @@ namespace consistency { template<template<class, class> class TT1, class T1, class T2, class T3, class T4> struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T2>>::type> {}; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class> class UU1, class U1, class U2> struct A<UU1<U1>, UU1<U2>, typename nondeduced<UU1<U1>>::type>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template struct A<B<int>, B<int>, B<int>>; - // new-error@-1 {{ambiguous partial specializations}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace t3 namespace t4 { template<class T1, class T2, class T3> struct A; @@ -226,15 +215,15 @@ namespace consistency { template<template<class, class> class TT1, class T1, class T2, class T3, class T4> struct A<TT1<T1, T2>, TT1<T3, T4>, typename nondeduced<TT1<T1, T4>>::type> {}; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class> class UU1, class U1, class U2> struct A<UU1<U1>, UU1<U2>, typename nondeduced<UU1<U1>>::type>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template struct A<B<int>, B<int>, B<int>>; - // new-error@-1 {{ambiguous partial specializations}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace t4 namespace t5 { template<class T1, class T2> struct A; @@ -242,15 +231,15 @@ namespace consistency { template<template<class, class> class TT1, class T1, class T2, class T3, class T4> struct A<TT1<T1, T2>, TT1<T3, T4>> {}; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class> class UU1, class U1, class U2> struct A<UU1<U1>, UU1<U2>>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template struct A<B<int>, B<int>>; - // new-error@-1 {{ambiguous partial specializations}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace t5 namespace t6 { template<class T1, class T2> struct A; @@ -258,15 +247,15 @@ namespace consistency { template<template<class, class> class TT1, class T1, class T2, class T3> struct A<TT1<T1, T2>, TT1<T1, T3>> {}; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template<template<class> class UU1, class U1, class U2> struct A<UU1<U1>, UU1<U2>>; - // new-note@-1 {{partial specialization matches}} + // expected-note@-1 {{partial specialization matches}} template struct A<B<int>, B<int>>; - // new-error@-1 {{ambiguous partial specializations}} + // expected-error@-1 {{ambiguous partial specializations}} } // namespace t6 } // namespace consistency @@ -275,8 +264,7 @@ namespace classes { template<class T, class U> struct A {}; template<template<class> class TT> auto f(TT<int> a) { return a; } - // old-note@-1 2{{template template argument has different template parameters}} - // new-note@-2 2{{substitution failure: too few template arguments}} + // expected-note@-1 2{{substitution failure: too few template arguments}} A<int, float> v1; A<int, double> v2; @@ -292,8 +280,7 @@ namespace classes { static constexpr auto val = E1; }; template <template <class T3> class TT> void f(TT<int> v) { - // old-note@-1 {{template template argument has different template parameters}} - // new-note@-2 {{substitution failure: too few template arguments}} + // expected-note@-1 {{substitution failure: too few template arguments}} static_assert(v.val == 3); }; void test() { @@ -307,8 +294,7 @@ namespace classes { }; template <template <class T3> class TT> void f(TT<int> v) { - // old-note@-1 {{template template argument has different template parameters}} - // new-note@-2 {{deduced type 'A<[...], (no argument), (no argument), (no argument)>' of 1st parameter does not match adjusted type 'A<[...], void, void, void>' of argument [with TT = A]}} + // expected-note@-1 {{deduced type 'A<[...], (no argument), (no argument), (no argument)>' of 1st parameter does not match adjusted type 'A<[...], void, void, void>' of argument [with TT = A]}} static_assert(v.val == 3); }; void test() { @@ -327,8 +313,7 @@ namespace classes { } template <template <class T2, int V3> class TT2> auto g(TT2<double, 1>) { - // new-note@-1 {{too few template arguments for class template 'A'}} - // old-note@-2 {{template template argument has different template parameters}} + // expected-note@-1 {{too few template arguments for class template 'A'}} return f(TT2<int, 2>()); } @@ -346,13 +331,11 @@ namespace classes { }; template <template <class> class TT> TT<float> f(TT<int>); - // new-note@-1 {{deduced type 'A<[...], (default) int *>' of 1st parameter does not match adjusted type 'A<[...], double *>' of argument [with TT = A]}} - // old-note@-2 2{{template template argument has different template parameters}} + // expected-note@-1 {{deduced type 'A<[...], (default) int *>' of 1st parameter does not match adjusted type 'A<[...], double *>' of argument [with TT = A]}} - using X = int*; // new-note {{previous definition is here}} + using X = int*; // expected-note {{previous definition is here}} using X = decltype(f(A<int>()))::type; - // new-error@-1 {{different types ('decltype(f(A<int>()))::type' (aka 'float *') vs 'int *')}} - // old-error@-2 {{no matching function for call}} + // expected-error@-1 {{different types ('decltype(f(A<int>()))::type' (aka 'float *') vs 'int *')}} using Y = double*; using Y = decltype(f(A<int, double*>()))::type; @@ -363,59 +346,39 @@ namespace classes { namespace packs { namespace t1 { template<template<int, int...> class> struct A {}; - // new-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}} - // new-note@-2 {{previous template template parameter is here}} - // old-note@-3 {{previous non-type template parameter with type 'int' is here}} + // expected-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}} + // expected-note@-2 {{previous template template parameter is here}} template<char> struct B; - // old-note@-1 {{template non-type parameter has a different type 'char' in template argument}} - template struct A<B>; - // new-note@-1 {{has different template parameters}} - // old-error@-2 {{has different template parameters}} + // expected-note@-1 {{has different template parameters}} } // namespace t1 namespace t2 { template<template<char, int...> class> struct A {}; - // old-note@-1 {{previous non-type template parameter with type 'char' is here}} - template<int> struct B; - // old-note@-1 {{template non-type parameter has a different type 'int' in template argument}} - template struct A<B>; - // old-error@-1 {{has different template parameters}} } // namespace t2 namespace t3 { template<template<int...> class> struct A {}; - // new-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}} - // new-note@-2 {{previous template template parameter is here}} - // old-note@-3 {{previous non-type template parameter with type 'int' is here}} + // expected-error@-1 {{non-type parameter of template template parameter cannot be narrowed from type 'int' to 'char'}} + // expected-note@-2 {{previous template template parameter is here}} template<char> struct B; - // old-note@-1 {{template non-type parameter has a different type 'char' in template argument}} - template struct A<B>; - // new-note@-1 {{has different template parameters}} - // old-error@-2 {{has different template parameters}} + // expected-note@-1 {{has different template parameters}} } // namespace t3 namespace t4 { template<template<char...> class> struct A {}; - // old-note@-1 {{previous non-type template parameter with type 'char' is here}} - template<int> struct B; - // old-note@-1 {{template non-type parameter has a different type 'int' in template argument}} - template struct A<B>; - // old-error@-1 {{has different template parameters}} } // namespace t4 } // namespace packs namespace fun_tmpl_call { namespace match_func { template <template <class> class TT> void f(TT<int>) {}; - // old-note@-1 {{has different template parameters}} template <class...> struct A {}; void test() { f(A<int>()); } - // old-error@-1 {{no matching function for call to 'f'}} } // namespace match_func namespace order_func_nonpack { template <template <class> class TT> void f(TT<int>) {} @@ -427,26 +390,21 @@ namespace fun_tmpl_call { namespace order_func_pack { template <template <class> class TT> void f(TT<int>) = delete; template <template <class...> class TT> void f(TT<int>) {} - template <class...> struct A {}; void test() { f(A<int>()); } } // namespace order_func_pack namespace match_enum { enum A {}; template<template<A> class TT1> void f(TT1<{}>) {} - // old-note@-1 {{invalid explicitly-specified argument}} template<int> struct B {}; template void f<B>(B<{}>); - // old-error@-1 {{does not refer to a function template}} } // namespace match_enum namespace match_method { struct A { template <template <class> class TT> void f(TT<int>) {}; - // old-note@-1 {{has different template parameters}} }; template <class...> struct B {}; void test() { A().f(B<int>()); } - // old-error@-1 {{no matching member function for call to 'f'}} } // namespace match_method namespace order_method_nonpack { struct A { @@ -467,12 +425,9 @@ namespace fun_tmpl_call { namespace match_conv { struct A { template <template <class> class TT> operator TT<int>() { return {}; } - // old-note@-1 {{different template parameters}} }; template <class...> struct B {}; - // old-note@-1 2{{not viable}} void test() { B<int> b = A(); } - // old-error@-1 {{no viable conversion from 'A' to 'B<int>'}} } // namespace match_conv namespace order_conv_nonpack { struct A { @@ -536,21 +491,21 @@ namespace regression1 { namespace constraints { template <class T> concept C1 = true; - // new-note@-1 {{similar constraint expression here}} - // new-note@-2 2{{similar constraint expressions not considered equivalent}} + // expected-note@-1 {{similar constraint expression here}} + // expected-note@-2 2{{similar constraint expressions not considered equivalent}} template <class T> concept C2 = C1<T> && true; - // new-note@-1 2{{similar constraint expression here}} + // expected-note@-1 2{{similar constraint expression here}} template <class T> concept D1 = true; - // new-note@-1 {{similar constraint expressions not considered equivalent}} + // expected-note@-1 {{similar constraint expressions not considered equivalent}} namespace t1 { - template<template<C1, class... T1s> class TT1> // new-note {{TT1' declared here}} + template<template<C1, class... T1s> class TT1> // expected-note {{TT1' declared here}} struct A {}; - template<D1, class T2> struct B {}; // new-note {{'B' declared here}} + template<D1, class T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t1 namespace t2 { template<template<C2, class... T1s> class TT1> struct A {}; @@ -558,34 +513,34 @@ namespace constraints { template struct A<B>; } // namespace t2 namespace t3 { - template<template<C1, class... T1s> class TT1> // new-note {{'TT1' declared here}} + template<template<C1, class... T1s> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<C2, class T2> struct B {}; // new-note {{'B' declared here}} + template<C2, class T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t2 namespace t4 { // FIXME: This should be accepted. - template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}} + template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<C1 T2> struct B {}; // new-note {{'B' declared here}} + template<C1 T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t4 namespace t5 { // FIXME: This should be accepted - template<template<C2... T1s> class TT1> // new-note {{'TT1' declared here}} + template<template<C2... T1s> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<C1 T2> struct B {}; // new-note {{'B' declared here}} + template<C1 T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t5 namespace t6 { - template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}} + template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<C2 T2> struct B {}; // new-note {{'B' declared here}} + template<C2 T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t6 namespace t7 { template<template<class... T1s> class TT1> @@ -600,19 +555,19 @@ namespace constraints { template struct A<B>; } // namespace t8 namespace t9 { - template<template<C1... T1s> class TT1> // new-note {{'TT1' declared here}} + template<template<C1... T1s> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<D1 T2> struct B {}; // new-note {{'B' declared here}} + template<D1 T2> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t9 namespace t10 { - template<template<class...> requires C1<int> class TT1> // new-note {{'TT1' declared here}} + template<template<class...> requires C1<int> class TT1> // expected-note {{'TT1' declared here}} struct A {}; - template<class> requires C2<int> struct B {}; // new-note {{'B' declared here}} + template<class> requires C2<int> struct B {}; // expected-note {{'B' declared here}} template struct A<B>; - // new-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} + // expected-error@-1 {{'B' is more constrained than template template parameter 'TT1'}} } // namespace t10 namespace t11 { template<template<class...> requires C2<int> class TT1> struct A {}; @@ -640,24 +595,22 @@ namespace nttp_auto { namespace t2 { // FIXME: Shouldn't accept parameters after a parameter pack. template<template<auto... Va1, auto Va2> class> struct A {}; - // new-error@-1 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('auto' vs 'int')}} + // expected-error@-1 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('auto' vs 'int')}} // expected-note@-2 {{previous template template parameter is here}} template<int... Vi> struct B; - // new-note@-1 {{template parameter is declared here}} - // old-note@-2 {{too few template parameters}} + // expected-note@-1 {{template parameter is declared here}} template struct A<B>; - // new-note@-1 {{different template parameters}} - // old-error@-2 {{different template parameters}} + // expected-note@-1 {{different template parameters}} } // namespace t2 namespace t3 { // FIXME: Shouldn't accept parameters after a parameter pack. template<template<auto... Va1, auto... Va2> class> struct A {}; - // new-error@-1 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('auto' vs 'int')}} - // new-note@-2 {{previous template template parameter is here}} + // expected-error@-1 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('auto' vs 'int')}} + // expected-note@-2 {{previous template template parameter is here}} template<int... Vi> struct B; - // new-note@-1 {{template parameter is declared here}} + // expected-note@-1 {{template parameter is declared here}} template struct A<B>; - // new-note@-1 {{different template parameters}} + // expected-note@-1 {{different template parameters}} } // namespace t3 } // namespace nttp_auto diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 575055117b35fa..cd9fb6b6f2178c 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1204,8 +1204,8 @@ <h2 id="cxx17">C++17 implementation status</h2> <span id="p0522">(10): While this feature was initially implemented in Clang 4, it was not enabled by default prior to clang 19, but could be enabled with <tt>-frelaxed-template-template-args</tt>. -Starting from Clang 19, the flag is deprecated and will be removed in a future -version. +In Clang 19, the flag was deprecated. +In Clang 20, the flag was removed altogether. </span> </p> </details> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits