https://github.com/evelez7 created 
https://github.com/llvm/llvm-project/pull/94789

Deprecate the use of the template keyword before the qualified name of an alias 
or class template without a template argument list. Introduced in 
[P1787](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html), 
with current wording [here](https://eel.is/c++draft/depr.template.template).

>From 336f2667eecfcfa32afc3695c0dd27a08b302b8e Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvel...@gmail.com>
Date: Thu, 6 Jun 2024 11:13:14 -0700
Subject: [PATCH] [clang] deprecate alias, class templates without arg list
 after template kw

---
 clang/include/clang/Basic/DiagnosticParseKinds.td             | 4 ++++
 clang/lib/Parse/ParseTemplate.cpp                             | 4 ++++
 clang/test/CXX/drs/cwg0xx.cpp                                 | 1 +
 clang/test/CXX/drs/cwg10xx.cpp                                | 3 ++-
 clang/test/CXX/drs/cwg13xx.cpp                                | 4 ++++
 clang/test/CXX/drs/cwg17xx.cpp                                | 1 +
 clang/test/CXX/drs/cwg3xx.cpp                                 | 1 +
 .../test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp  | 1 +
 .../temp.decls/temp.variadic/multi-level-substitution.cpp     | 1 +
 clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp           | 2 +-
 clang/test/CXX/temp/temp.param/p15-cxx0x.cpp                  | 4 ++--
 clang/test/CXX/temp/temp.res/temp.local/p1.cpp                | 4 ++--
 clang/test/PCH/cxx-templates.cpp                              | 4 ----
 clang/test/PCH/cxx-templates.h                                | 3 ---
 clang/test/SemaCXX/nested-name-spec-locations.cpp             | 2 +-
 clang/test/SemaCXX/redeclared-alias-template.cpp              | 2 +-
 clang/test/SemaTemplate/alias-church-numerals.cpp             | 3 +--
 clang/test/SemaTemplate/alias-template-template-param.cpp     | 3 +--
 clang/test/SemaTemplate/concepts-GH53354.cpp                  | 3 +--
 clang/test/SemaTemplate/default-arguments.cpp                 | 2 +-
 clang/test/SemaTemplate/instantiate-self.cpp                  | 2 +-
 .../test/SemaTemplate/instantiate-template-template-parm.cpp  | 2 +-
 clang/test/SemaTemplate/temp-param-subst-linear.cpp           | 3 +--
 23 files changed, 33 insertions(+), 26 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index d8c3fee7841f4..661bb6059767b 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -891,6 +891,10 @@ def missing_template_arg_list_after_template_kw : 
Extension<
   "a template argument list is expected after a name prefixed by the template "
   "keyword">, 
InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
   DefaultError;
+def warn_missing_template_arg_list_after_template_kw_deprecated : Warning<
+  "the use of the keyword template before the qualified name of a class or "
+  "alias template without a template argument list is deprecated">,
+  
InGroup<DiagGroup<"warn-missing-template-arg-list-after-template-kw-deprecated-deprecated">>;
 
 def err_missing_dependent_template_keyword : Error<
   "use 'template' keyword to treat '%0' as a dependent template name">;
diff --git a/clang/lib/Parse/ParseTemplate.cpp 
b/clang/lib/Parse/ParseTemplate.cpp
index a5130f56600e5..e44a70ffda1af 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -1420,6 +1420,10 @@ ParsedTemplateArgument 
Parser::ParseTemplateTemplateArgument() {
       UnqualifiedId Name;
       Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
       ConsumeToken(); // the identifier
+      if (Tok.isNot(tok::less)) {
+        Diag(Tok.getLocation(),
+             
diag::warn_missing_template_arg_list_after_template_kw_deprecated);
+      }
 
       TryConsumeToken(tok::ellipsis, EllipsisLoc);
 
diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp
index fe3e0cfc1d421..3204327b8e670 100644
--- a/clang/test/CXX/drs/cwg0xx.cpp
+++ b/clang/test/CXX/drs/cwg0xx.cpp
@@ -1422,6 +1422,7 @@ namespace cwg96 { // cwg96: sup P1787
     // expected-error@-1 {{a template argument list is expected after a name 
prefixed by the template keyword}}
     A::template S<int> s;
     B<A::template S> b;
+    // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
   }
 }
 
diff --git a/clang/test/CXX/drs/cwg10xx.cpp b/clang/test/CXX/drs/cwg10xx.cpp
index 58d552942c77c..0db9ab3b3c267 100644
--- a/clang/test/CXX/drs/cwg10xx.cpp
+++ b/clang/test/CXX/drs/cwg10xx.cpp
@@ -40,7 +40,8 @@ namespace cwg1004 { // cwg1004: 5
   // This example (from the standard) is actually ill-formed, because
   // name lookup of "T::template A" names the constructor.
   template<class T, template<class> class U = T::template A> struct Third { };
-  // expected-error@-1 {{is a constructor name}}
+  // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
+  // expected-error@-2 {{is a constructor name}}
   //   expected-note@#cwg1004-t {{in instantiation of default argument}}
   Third<A<int> > t; // #cwg1004-t
 }
diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp
index 416de7c536b1a..560d3cf22dafb 100644
--- a/clang/test/CXX/drs/cwg13xx.cpp
+++ b/clang/test/CXX/drs/cwg13xx.cpp
@@ -109,10 +109,12 @@ namespace cwg1310 { // cwg1310: 5
     TT<W<int>::template W> tt2;
     // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' 
is a constructor name rather than a template name in this context, despite 
preceding 'template' keyword}}
     // cxx98-error@-2 {{'template' keyword outside of a template}}
+    // expected-warning@-3 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
     TT<W<int>::WBase> tt3;
     TTy<W<int>::WBase> tt3a;
     TT<W<int>::template WBase> tt4;
     // cxx98-error@-1 {{'template' keyword outside of a template}}
+    // expected-warning@-2 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
 
     W<int> w;
     (void)w.W::W::n;
@@ -134,6 +136,7 @@ namespace cwg1310 { // cwg1310: 5
     // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' 
is a constructor name rather than a type in this context, despite preceding 
'typename' keyword}}
     TT<W::template W> tt3;
     // expected-error@-1 {{ISO C++ specifies that qualified reference to 'W' 
is a constructor name rather than a template name in this context, despite 
preceding 'template' keyword}}
+    // expected-warning@-2 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
   }
   template<typename W>
   void wt_test_good() {
@@ -141,6 +144,7 @@ namespace cwg1310 { // cwg1310: 5
     typename W::template W<int>::X w4x;
     TTy<typename W::WBase> tt4;
     TT<W::template WBase> tt5;
+    // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
 
     W w;
     (void)w.W::W::n;
diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp
index fb53a56923b10..6991477221102 100644
--- a/clang/test/CXX/drs/cwg17xx.cpp
+++ b/clang/test/CXX/drs/cwg17xx.cpp
@@ -237,5 +237,6 @@ using Instantiate = Template<Arg>;
 
 template <template <typename> class Template, typename Argument>
 using Bind = Instantiate<Internal<Template>::template Bind, Argument>;
+// expected-warning@-1 {{the use of the keyword template before the qualified 
name of a class or alias template without a template argument list is 
deprecated}}
 #endif
 } // namespace cwg1794
diff --git a/clang/test/CXX/drs/cwg3xx.cpp b/clang/test/CXX/drs/cwg3xx.cpp
index 94227dc031c6a..4aef7167efd03 100644
--- a/clang/test/CXX/drs/cwg3xx.cpp
+++ b/clang/test/CXX/drs/cwg3xx.cpp
@@ -1673,6 +1673,7 @@ namespace cwg398 { // cwg398: yes
     template <class T> void f(typename T::Y *) {} // #cwg398-f
     template <class T> void g(X<T::N> *) {} // #cwg398-g
     template <class T> void h(Z<T::template TT> *) {} // #cwg398-h
+    // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
     struct A {};
     struct B {
       int Y;
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp 
b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
index f1231f61111e3..94732a48e251d 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/metafunctions.cpp
@@ -204,6 +204,7 @@ namespace TemplateTemplateApply {
   template<typename T, typename ...Meta>
   struct apply_each_nested {
     typedef typename apply_each<T, Meta::template apply...>::type type;
+    // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
   };
 
   struct add_reference_meta {
diff --git 
a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp 
b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
index 30e7c65dac91c..34dbd5bc4bd1c 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/multi-level-substitution.cpp
@@ -118,6 +118,7 @@ namespace PacksAtDifferentLevels {
     template<typename ...Types2>
     struct Inner<tuple<pair<Types1, Types2>...>,
                  metafun_tuple<some_function_object<Types1, Types2>::template 
result_of...> > {
+    // expected-warning@-1 {{the use of the keyword template before the 
qualified name of a class or alias template without a template argument list is 
deprecated}}
       static const unsigned value = 1;
     };
   };
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp 
b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 3c500c2c4dc4a..7033bd35cc627 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -207,7 +207,7 @@ struct alignas(Types) TestUnexpandedDecls : T{ // 
expected-error{{expression con
     struct default_template_args_1;
   template<int = static_cast<Types>(0)> // expected-error{{default argument 
contains unexpanded parameter pack 'Types'}}
     struct default_template_args_2;
-  template<template<typename> class = Types::template apply> // 
expected-error{{default argument contains unexpanded parameter pack 'Types'}}
+  template<template<typename> class = Types::template apply> // 
expected-error{{default argument contains unexpanded parameter pack 'Types'}} 
// expected-warning{{the use of the keyword template before the qualified name 
of a class or alias template without a template argument list is deprecated}}
     struct default_template_args_3;
 
   template<Types value> // expected-error{{non-type template parameter type 
contains unexpanded parameter pack 'Types'}}
diff --git a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp 
b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
index 83144a494937b..dc43f82e36091 100644
--- a/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
+++ b/clang/test/CXX/temp/temp.param/p15-cxx0x.cpp
@@ -87,11 +87,11 @@ template<place...X> struct takedrop_impl<places<X...>> {
 
 template<unsigned N, typename...Ts> struct take {
   using type = typename takedrop_impl<typename make_places<N>::type>::
-    template inner<wrap<Ts>::template inner...>::take; // expected-error {{too 
few template arguments}}
+    template inner<wrap<Ts>::template inner...>::take; // expected-error {{too 
few template arguments}} // expected-warning {{the use of the keyword template 
before the qualified name of a class or alias template without a template 
argument list is deprecated}}
 };
 template<unsigned N, typename...Ts> struct drop {
   using type = typename takedrop_impl<typename make_places<N>::type>::
-    template inner<wrap<Ts>::template inner...>::drop; // expected-error {{too 
few template arguments}}
+    template inner<wrap<Ts>::template inner...>::drop; // expected-error {{too 
few template arguments}} // expected-warning {{the use of the keyword template 
before the qualified name of a class or alias template without a template 
argument list is deprecated}}
 };
 
 using T1 = take<3, int, char, double, long>::type; // expected-note 
{{previous}}
diff --git a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp 
b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
index faa85cb5fce30..27bad6847b67e 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p1.cpp
@@ -23,7 +23,7 @@ template<typename T> struct A {
 
     //   as a template-argument for a template template-parameter,
     TempTemp<A> a_as_temp;
-    TempTemp<B::template C> c_as_temp;
+    TempTemp<B::template C> c_as_temp; // expected-warning {{the use of the 
keyword template before the qualified name of a class or alias template without 
a template argument list is deprecated}}
 
     //   or as the final identifier in the elaborated-type-specifier of a 
friend
     //   class template declaration,
@@ -42,7 +42,7 @@ template<typename T> struct A {
     void f(T &t) {
       use<A>(t); // expected-error {{no matching function}}
       if constexpr (&id<T> != &id<int>)
-        use<B::template C>(t); // expected-error {{no matching function}}
+        use<B::template C>(t); // expected-error {{no matching function}} // 
expected-warning {{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
     }
   };
 };
diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp
index 11ad401de23a8..0e518d24d8597 100644
--- a/clang/test/PCH/cxx-templates.cpp
+++ b/clang/test/PCH/cxx-templates.cpp
@@ -176,10 +176,6 @@ namespace DependentTemplateName {
   struct HasMember {
     template <class T> struct Member;
   };
-
-  void test() {
-    getWithIdentifier<HasMember>();
-  }
 }
 
 namespace ClassTemplateCycle {
diff --git a/clang/test/PCH/cxx-templates.h b/clang/test/PCH/cxx-templates.h
index 95d684e4a92db..367664237fcb0 100644
--- a/clang/test/PCH/cxx-templates.h
+++ b/clang/test/PCH/cxx-templates.h
@@ -451,9 +451,6 @@ namespace DependentMemberExpr {
 namespace DependentTemplateName {
   template <template <class> class Template>
   struct TakesClassTemplate {};
-
-  template <class T>
-  TakesClassTemplate<T::template Member> getWithIdentifier();
 }
 
 namespace ClassTemplateCycle {
diff --git a/clang/test/SemaCXX/nested-name-spec-locations.cpp 
b/clang/test/SemaCXX/nested-name-spec-locations.cpp
index 048d4baf135bf..90a6b5ec222da 100644
--- a/clang/test/SemaCXX/nested-name-spec-locations.cpp
+++ b/clang/test/SemaCXX/nested-name-spec-locations.cpp
@@ -141,7 +141,7 @@ struct DependentTemplateTemplateArgumentTester {
               typename add_reference<U>::type
               * // expected-error{{declared as a pointer to a reference of 
type}}
             >::
-            template X>
+            template X> // expected-warning{{the use of the keyword template 
before the qualified name of a class or alias template without a template 
argument list is deprecated}}
     type;
 };
 
diff --git a/clang/test/SemaCXX/redeclared-alias-template.cpp 
b/clang/test/SemaCXX/redeclared-alias-template.cpp
index 4828986f96a61..c833a69d98b17 100644
--- a/clang/test/SemaCXX/redeclared-alias-template.cpp
+++ b/clang/test/SemaCXX/redeclared-alias-template.cpp
@@ -10,7 +10,7 @@ template<typename T2, typename T1> using B = T1; // 
expected-error {{type alias
 
 template<typename> struct S;
 template<template<typename> class F> using FInt = F<int>;
-template<typename X> using SXRInt = FInt<S<X>::template R>;
+template<typename X> using SXRInt = FInt<S<X>::template R>; // 
expected-warning {{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
 template<typename X> using SXRInt = typename S<X>::template R<int>; // ok, 
redeclaration.
 
 template<template<typename> class> struct TT;
diff --git a/clang/test/SemaTemplate/alias-church-numerals.cpp 
b/clang/test/SemaTemplate/alias-church-numerals.cpp
index a1613230ac0d1..c574484b9f988 100644
--- a/clang/test/SemaTemplate/alias-church-numerals.cpp
+++ b/clang/test/SemaTemplate/alias-church-numerals.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 template<template<template<typename> class, typename> class T, 
template<typename> class V> struct PartialApply {
   template<typename W> using R = T<V, W>;
@@ -20,7 +19,7 @@ template<template<template<typename> class, typename> class A,
 template<template<template<typename> class, typename> class A,
          template<template<typename> class, typename> class B,
          template<typename> class F,
-         typename X> using Mul = A<PartialApply<B,F>::template R, X>;
+         typename X> using Mul = A<PartialApply<B,F>::template R, X>; // 
expected-warning {{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
 
 template<template<typename> class F, typename X> using Four = Add<Two, Two, F, 
X>;
 template<template<typename> class F, typename X> using Sixteen = Mul<Four, 
Four, F, X>;
diff --git a/clang/test/SemaTemplate/alias-template-template-param.cpp 
b/clang/test/SemaTemplate/alias-template-template-param.cpp
index 0b17d10d0cb66..a98b692b577a1 100644
--- a/clang/test/SemaTemplate/alias-template-template-param.cpp
+++ b/clang/test/SemaTemplate/alias-template-template-param.cpp
@@ -1,8 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// expected-no-diagnostics
 
 template<template<typename> class D> using C = D<int>;
 
 // Substitution of the alias template transforms the TemplateSpecializationType
 // 'D<int>' into the DependentTemplateSpecializationType 'T::template U<int>'.
-template<typename T> void f(C<T::template U>);
+template<typename T> void f(C<T::template U>); // expected-warning {{the use 
of the keyword template before the qualified name of a class or alias template 
without a template argument list is deprecated}}
diff --git a/clang/test/SemaTemplate/concepts-GH53354.cpp 
b/clang/test/SemaTemplate/concepts-GH53354.cpp
index 4fdf8bdd712a4..0d26abbefd333 100644
--- a/clang/test/SemaTemplate/concepts-GH53354.cpp
+++ b/clang/test/SemaTemplate/concepts-GH53354.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++20 -verify %s
-// expected-no-diagnostics
 
 template <template <class> class>
 struct S
@@ -8,7 +7,7 @@ struct S
 template <class T>
 concept C1 = requires
 {
-  typename S<T::template value_types>;
+  typename S<T::template value_types>; // expected-warning {{the use of the 
keyword template before the qualified name of a class or alias template without 
a template argument list is deprecated}}
 };
 
 template <class T>
diff --git a/clang/test/SemaTemplate/default-arguments.cpp 
b/clang/test/SemaTemplate/default-arguments.cpp
index d5d9687cc90f4..8db8468389ea6 100644
--- a/clang/test/SemaTemplate/default-arguments.cpp
+++ b/clang/test/SemaTemplate/default-arguments.cpp
@@ -107,7 +107,7 @@ struct add_pointer {
   };
 };
 
-template<typename T, template<typename> class X = T::template apply>
+template<typename T, template<typename> class X = T::template apply> // 
expected-warning{{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
   struct X4;
 int array4[is_same<X4<add_pointer>, 
                    X4<add_pointer, add_pointer::apply> >::value? 1 : -1];
diff --git a/clang/test/SemaTemplate/instantiate-self.cpp 
b/clang/test/SemaTemplate/instantiate-self.cpp
index 4999a4ad3784d..f095125f06516 100644
--- a/clang/test/SemaTemplate/instantiate-self.cpp
+++ b/clang/test/SemaTemplate/instantiate-self.cpp
@@ -137,7 +137,7 @@ namespace test13 {
     // Cycle via default template argument.
     template<typename T, typename U = typename T::template X<T>> struct X {};
     template<typename T, int U = T::template Y<T>::value> struct Y { static 
const int value = 0; };
-    template<typename T, template<typename> typename U = T::template 
Z<T>::template nested> struct Z { template<typename> struct nested; };
+    template<typename T, template<typename> typename U = T::template 
Z<T>::template nested> struct Z { template<typename> struct nested; }; // 
expected-warning {{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
   };
   template<typename T> struct Wrap {
     template<typename U> struct W : A::W<T> {};
diff --git a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp 
b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
index 39aeeb1c1a6a3..b2a4725e6b62f 100644
--- a/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
+++ b/clang/test/SemaTemplate/instantiate-template-template-parm.cpp
@@ -73,7 +73,7 @@ namespace PR8629 {
     template<class U> void g()
     {
       typedef Inner<U> Init;
-      X0<Init::template VeryInner>::apply();
+      X0<Init::template VeryInner>::apply(); // expected-warning{{the use of 
the keyword template before the qualified name of a class or alias template 
without a template argument list is deprecated}}
     }
     template<int N> void f ()
     {
diff --git a/clang/test/SemaTemplate/temp-param-subst-linear.cpp 
b/clang/test/SemaTemplate/temp-param-subst-linear.cpp
index fd93aa568553f..7df6677a6e2bf 100644
--- a/clang/test/SemaTemplate/temp-param-subst-linear.cpp
+++ b/clang/test/SemaTemplate/temp-param-subst-linear.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++17 %s -verify
-// expected-no-diagnostics
 
 // This test attempts to ensure that the below template parameter pack
 // splitting technique executes in linear time in the number of template
@@ -33,7 +32,7 @@ struct SplitAtIndex;
 template<typename ...T, unsigned N, typename ...NUnsigneds>
 struct SplitAtIndex<TypeList<T...>, N, TypeList<NUnsigneds...>> :
   detail::Splitter<NUnsigneds...>::
-    template Split<detail::TypeWrapper<T>::template AsTemplate...> {};
+    template Split<detail::TypeWrapper<T>::template AsTemplate...> {}; // 
expected-warning {{the use of the keyword template before the qualified name of 
a class or alias template without a template argument list is deprecated}}
 
 template<typename T, int N> struct Rep : Rep<typename Rep<T, N-1>::type, 1> {};
 template<typename ...T> struct Rep<TypeList<T...>, 1> { typedef TypeList<T..., 
T...> type; };

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to