Author: Matheus Izvekov
Date: 2025-01-29T16:57:05-03:00
New Revision: 8a334af417ff2ef49e0bc74f9421b4f3aa479805

URL: 
https://github.com/llvm/llvm-project/commit/8a334af417ff2ef49e0bc74f9421b4f3aa479805
DIFF: 
https://github.com/llvm/llvm-project/commit/8a334af417ff2ef49e0bc74f9421b4f3aa479805.diff

LOG: [clang] Remove the deprecated flag `-frelaxed-template-template-args`. 
(#111894)

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.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/include/clang/Basic/DiagnosticGroups.td
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Driver/Options.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/SemaTemplate/cwg2398.cpp
    clang/www/cxx_status.html

Removed: 
    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_
diff erent_type;
-          if (TemplateArgLoc.isValid()) {
-            S.Diag(TemplateArgLoc,
-                   diag::err_template_arg_template_params_mismatch);
-            NextDiag = diag::note_template_nontype_parm_
diff erent_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_
diff erent_type;
+        if (TemplateArgLoc.isValid()) {
+          S.Diag(TemplateArgLoc,
+                 diag::err_template_arg_template_params_mismatch);
+          NextDiag = diag::note_template_nontype_parm_
diff erent_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 
diff erent 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 
diff erent 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 
diff erent 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 
diff erent 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 
diff erent 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 
diff erent 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 
diff erent 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 
diff erent 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 {{
diff erent types ('decltype(f(A<int>()))::type' (aka 'float *') vs 'int *')}}
-    // old-error@-2 {{no matching function for call}}
+    // expected-error@-1 {{
diff erent 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 
diff erent type 'char' in template argument}}
-
     template struct A<B>;
-    // new-note@-1 {{has 
diff erent template parameters}}
-    // old-error@-2 {{has 
diff erent template parameters}}
+    // expected-note@-1 {{has 
diff erent 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 
diff erent type 'int' in template argument}}
-
     template struct A<B>;
-    // old-error@-1 {{has 
diff erent 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 
diff erent type 'char' in template argument}}
-
     template struct A<B>;
-    // new-note@-1 {{has 
diff erent template parameters}}
-    // old-error@-2 {{has 
diff erent template parameters}}
+    // expected-note@-1 {{has 
diff erent 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 
diff erent type 'int' in template argument}}
-
     template struct A<B>;
-    // old-error@-1 {{has 
diff erent 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 
diff erent 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 
diff erent 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 {{
diff erent 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 {{
diff erent template parameters}}
-    // old-error@-2 {{
diff erent template parameters}}
+    // expected-note@-1 {{
diff erent 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 {{
diff erent template parameters}}
+    // expected-note@-1 {{
diff erent template parameters}}
   } // namespace t3
 } // namespace nttp_auto
 

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 575055117b35fa..0fc3b1d3146984 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 21, 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

Reply via email to