[clang] [clang] require template arg list after template kw (PR #80801)
Erick Velez via cfe-commits
cfe-commits at lists.llvm.org
Thu Feb 8 08:59:43 PST 2024
https://github.com/evelez7 updated https://github.com/llvm/llvm-project/pull/80801
>From fd07c0a15eb45c3e7eb400026ea7702ae909a11e Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvelez7 at gmail.com>
Date: Mon, 5 Feb 2024 21:26:07 -0800
Subject: [PATCH 1/4] [clang] require template arg list after template kw
Require a template argument list after an identifier prefixed by the
template keyword. Introduced by CWG 96.
Fixes #53095
---
.../clang/Basic/DiagnosticParseKinds.td | 3 ++
clang/lib/Parse/ParseExprCXX.cpp | 23 ++++++++----
clang/test/CXX/drs/dr0xx.cpp | 2 +-
.../cxx1y-variable-templates_in_class.cpp | 6 ++--
.../test/SemaCXX/template-specialization.cpp | 2 +-
clang/test/SemaTemplate/dependent-names.cpp | 6 ++--
clang/test/SemaTemplate/template-id-expr.cpp | 36 +++++++++----------
.../SemaTemplate/template-id-printing.cpp | 13 -------
8 files changed, 46 insertions(+), 45 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index a30ab27566ec3e..159600f3e26dc0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -868,6 +868,9 @@ def err_requires_expr_in_simple_requirement : Error<
"requires expression in requirement body; did "
"you intend to place it in a nested requirement? (add another 'requires' "
"before the expression)">;
+def err_missing_template_arg_list_after_template_kw : Error<
+ "a template argument list is expected after a name prefixed by the template "
+ "keyword">;
def err_missing_dependent_template_keyword : Error<
"use 'template' keyword to treat '%0' as a dependent template name">;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index fd262ff31e661a..b3a1a6f6cf80d0 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/PrettyStackTrace.h"
+#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TokenKinds.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Parse/ParseDiagnostic.h"
@@ -2995,13 +2996,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
SS, ObjectType, ObjectHadErrors,
TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc,
EnteringContext, Result, TemplateSpecified);
- else if (TemplateSpecified &&
- Actions.ActOnTemplateName(
- getCurScope(), SS, *TemplateKWLoc, Result, ObjectType,
- EnteringContext, Template,
- /*AllowInjectedClassName*/ true) == TNK_Non_template)
- return true;
+ if (TemplateSpecified) {
+ TemplateNameKind TNK =
+ Actions.ActOnTemplateName(getCurScope(), SS, *TemplateKWLoc, Result,
+ ObjectType, EnteringContext, Template,
+ /*AllowInjectedClassName*/ true);
+ if (TNK == TNK_Non_template)
+ return true;
+
+ // C++ [template.names]p6
+ // A name prefixed by the keyword template shall be followed by a template
+ // argument list or refer to a class template or an alias template.
+ if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name ||
+ TNK == TNK_Var_template) &&
+ !Tok.is(tok::less))
+ Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw);
+ }
return false;
}
diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp
index 5959f0a0c8dd65..127d45be5bda97 100644
--- a/clang/test/CXX/drs/dr0xx.cpp
+++ b/clang/test/CXX/drs/dr0xx.cpp
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no
// FIXME: This is ill-formed, because 'f' is not a template-id and does not
// name a class template.
// FIXME: What about alias templates?
- int k2 = a.template f(1);
+ int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
A::template S<int> s;
B<A::template S> b;
}
diff --git a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index af121a8b75d512..37dbe0b212eb6a 100644
--- a/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/clang/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -384,16 +384,16 @@ namespace dependent_static_var_template {
struct A {
template<int = 0> static int n; // expected-note 2{{here}}
};
- int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}}
+ int &r = A::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
template<typename T>
- int &f() { return T::template n; } // expected-error {{use of variable template 'n' requires template arguments}}
+ int &f() { return T::template n; } // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
int &s = f<A>(); // expected-note {{instantiation of}}
namespace B {
template<int = 0> static int n; // expected-note {{here}}
}
- int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}}
+ int &t = B::template n; // expected-error {{use of variable template 'n' requires template arguments}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
struct C {
template <class T> static T G;
diff --git a/clang/test/SemaCXX/template-specialization.cpp b/clang/test/SemaCXX/template-specialization.cpp
index 7b26ff9f5c5ba4..c57ca51538d8f9 100644
--- a/clang/test/SemaCXX/template-specialization.cpp
+++ b/clang/test/SemaCXX/template-specialization.cpp
@@ -11,7 +11,7 @@ struct B {
template <int i>
static void foo() {
int array[i];
- A::template bar(array[0]); // expected-error {{no matching function for call to 'bar'}}
+ A::template bar(array[0]); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{no matching function for call to 'bar'}}
}
};
diff --git a/clang/test/SemaTemplate/dependent-names.cpp b/clang/test/SemaTemplate/dependent-names.cpp
index 641ec950054f57..5026004cdcc0c2 100644
--- a/clang/test/SemaTemplate/dependent-names.cpp
+++ b/clang/test/SemaTemplate/dependent-names.cpp
@@ -418,7 +418,7 @@ template <typename> struct CT2 {
template <typename T> int CT2<int>::X<>; // expected-error {{template parameter list matching the non-templated nested type 'CT2<int>' should be empty}}
namespace DependentTemplateIdWithNoArgs {
- template<typename T> void f() { T::template f(); }
+ template<typename T> void f() { T::template f(); } // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
struct X {
template<int = 0> static void f();
};
@@ -429,7 +429,7 @@ namespace DependentUnresolvedUsingTemplate {
template<typename T>
struct X : T {
using T::foo;
- void f() { this->template foo(); } // expected-error {{does not refer to a template}}
+ void f() { this->template foo(); } // expected-error {{does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
void g() { this->template foo<>(); } // expected-error {{does not refer to a template}}
void h() { this->template foo<int>(); } // expected-error {{does not refer to a template}}
};
@@ -448,7 +448,7 @@ namespace DependentUnresolvedUsingTemplate {
namespace PR37680 {
template <class a> struct b : a {
using a::add;
- template<int> int add() { return this->template add(0); }
+ template<int> int add() { return this->template add(0); } // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
};
struct a {
template<typename T = void> int add(...);
diff --git a/clang/test/SemaTemplate/template-id-expr.cpp b/clang/test/SemaTemplate/template-id-expr.cpp
index 0555d8b94504fb..3f1e889d78eeec 100644
--- a/clang/test/SemaTemplate/template-id-expr.cpp
+++ b/clang/test/SemaTemplate/template-id-expr.cpp
@@ -65,11 +65,11 @@ struct Y0 {
template<typename U>
void f() {
Y0::template f1<U>(0);
- Y0::template f1(0);
- this->template f1(0);
+ Y0::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+ this->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
Y0::template f2<U>(0);
- Y0::template f2(0);
+ Y0::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
@@ -77,11 +77,11 @@ struct Y0 {
int x;
x = Y0::f4(0);
x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
- x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y0::template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
x = this->f4(0);
x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
- x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = this->template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
}
};
@@ -109,11 +109,11 @@ struct Y1 {
template<typename U>
void f() {
Y1::template f1<U>(0);
- Y1::template f1(0);
- this->template f1(0);
+ Y1::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+ this->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
Y1::template f2<U>(0);
- Y1::template f2(0);
+ Y1::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
@@ -121,11 +121,11 @@ struct Y1 {
int x;
x = Y1::f4(0);
x = Y1::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
- x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y1::template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
x = this->f4(0);
x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
- x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = this->template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
}
};
@@ -138,23 +138,23 @@ struct Y2 : Y1<T> {
template<typename U>
void f(Y1 *p) {
Y1::template f1<U>(0);
- Y1::template f1(0);
- p->template f1(0);
+ Y1::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+ p->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
Y1::template f2<U>(0);
- Y1::template f2(0);
+ Y1::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
- Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
- Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+ Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+ Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
int x;
x = Y1::f4(0);
x = Y1::f4<int>(0); // expected-error {{use 'template'}} expected-error {{assigning to 'int' from incompatible type 'void'}}
- x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
x = p->f4(0);
x = p->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{use 'template'}}
- x = p->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = p->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
}
};
@@ -169,7 +169,7 @@ struct A {
template<int I>
void f5() {
- A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
+ A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
}
template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
diff --git a/clang/test/SemaTemplate/template-id-printing.cpp b/clang/test/SemaTemplate/template-id-printing.cpp
index 047589b1ce4333..e004bd35e5a0c3 100644
--- a/clang/test/SemaTemplate/template-id-printing.cpp
+++ b/clang/test/SemaTemplate/template-id-printing.cpp
@@ -99,8 +99,6 @@ template <typename T>
void test() {
// CHECK: S<T>::foo;
S<T>::foo;
- // CHECK: S<T>::template foo;
- S<T>::template foo;
// CHECK: S<T>::template foo<>;
S<T>::template foo<>;
// CHECK: S<T>::template foo<T>;
@@ -121,8 +119,6 @@ void test() {
S<T> s;
// CHECK: s.foo;
s.foo;
- // CHECK: s.template foo;
- s.template foo;
// CHECK: s.template foo<>;
s.template foo<>;
// CHECK: s.template foo<T>;
@@ -130,12 +126,3 @@ void test() {
}
} // namespace DSME
-
-namespace DSDRE_withImplicitTemplateArgs {
-
-template <typename T> void foo() {
- // CHECK: T::template bar();
- T::template bar();
-}
-
-} // namespace DSDRE_withImplicitTemplateArgs
>From 4115b127b941028a6160cd1bbc9a7f77d667afbe Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvelez7 at gmail.com>
Date: Wed, 7 Feb 2024 11:35:47 -0800
Subject: [PATCH 2/4] change error to pedenatic warn, regen DR html
---
clang/include/clang/Basic/DiagnosticParseKinds.td | 4 ++--
clang/lib/Parse/ParseExprCXX.cpp | 2 +-
clang/test/CXX/drs/dr0xx.cpp | 5 +++--
clang/test/Misc/warning-flags.c | 2 +-
clang/www/cxx_dr_status.html | 2 +-
5 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 159600f3e26dc0..58492169b261ee 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -868,9 +868,9 @@ def err_requires_expr_in_simple_requirement : Error<
"requires expression in requirement body; did "
"you intend to place it in a nested requirement? (add another 'requires' "
"before the expression)">;
-def err_missing_template_arg_list_after_template_kw : Error<
+def warn_missing_template_arg_list_after_template_kw : Warning<
"a template argument list is expected after a name prefixed by the template "
- "keyword">;
+ "keyword">, InGroup<Pedantic>, DefaultError;
def err_missing_dependent_template_keyword : Error<
"use 'template' keyword to treat '%0' as a dependent template name">;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index b3a1a6f6cf80d0..29fbd275efa8a6 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3011,7 +3011,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name ||
TNK == TNK_Var_template) &&
!Tok.is(tok::less))
- Diag(IdLoc, diag::err_missing_template_arg_list_after_template_kw);
+ Diag(IdLoc, diag::warn_missing_template_arg_list_after_template_kw);
}
return false;
}
diff --git a/clang/test/CXX/drs/dr0xx.cpp b/clang/test/CXX/drs/dr0xx.cpp
index 127d45be5bda97..7352e1d79ac65f 100644
--- a/clang/test/CXX/drs/dr0xx.cpp
+++ b/clang/test/CXX/drs/dr0xx.cpp
@@ -1400,7 +1400,7 @@ namespace dr95 { // dr95: 3.3
// expected-note@#dr95-C-f {{implicitly declared private here}}
}
-namespace dr96 { // dr96: no
+namespace dr96 { // dr96: sup P1787
struct A {
void f(int);
template<typename T> int f(T);
@@ -1414,7 +1414,8 @@ namespace dr96 { // dr96: no
// FIXME: This is ill-formed, because 'f' is not a template-id and does not
// name a class template.
// FIXME: What about alias templates?
- int k2 = a.template f(1); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
+ int k2 = a.template f(1);
+ // expected-error at -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;
}
diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index c587337da5933a..0e6d45419cd249 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -88,4 +88,4 @@ CHECK-NEXT: warn_weak_import
The list of warnings in -Wpedantic should NEVER grow.
-CHECK: Number in -Wpedantic (not covered by other -W flags): 26
+CHECK: Number in -Wpedantic (not covered by other -W flags): 27
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 3e13a4d89ef989..bbad3ce3ad533d 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -614,7 +614,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/96.html">96</a></td>
<td>C++11</td>
<td>Syntactic disambiguation using the <TT>template</TT> keyword</td>
- <td class="none" align="center">No</td>
+ <td class="na" align="center">Superseded by <a href="https://wg21.link/P1787">P1787</a></td>
</tr>
<tr id="97">
<td><a href="https://cplusplus.github.io/CWG/issues/97.html">97</a></td>
>From c33b4cafc0180caaba68abefe07fcf77e68b1b72 Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvelez7 at gmail.com>
Date: Wed, 7 Feb 2024 23:35:34 -0800
Subject: [PATCH 3/4] do not modify warning-flags.c
---
clang/include/clang/Basic/DiagnosticParseKinds.td | 5 +++--
clang/lib/Parse/ParseExprCXX.cpp | 2 +-
clang/test/Misc/warning-flags.c | 2 +-
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 58492169b261ee..93d5160a1589af 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -868,9 +868,10 @@ def err_requires_expr_in_simple_requirement : Error<
"requires expression in requirement body; did "
"you intend to place it in a nested requirement? (add another 'requires' "
"before the expression)">;
-def warn_missing_template_arg_list_after_template_kw : Warning<
+def missing_template_arg_list_after_template_kw : Extension<
"a template argument list is expected after a name prefixed by the template "
- "keyword">, InGroup<Pedantic>, DefaultError;
+ "keyword">, InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
+ DefaultError;
def err_missing_dependent_template_keyword : Error<
"use 'template' keyword to treat '%0' as a dependent template name">;
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index 29fbd275efa8a6..de2810fa145941 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3011,7 +3011,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType,
if ((TNK == TNK_Function_template || TNK == TNK_Dependent_template_name ||
TNK == TNK_Var_template) &&
!Tok.is(tok::less))
- Diag(IdLoc, diag::warn_missing_template_arg_list_after_template_kw);
+ Diag(IdLoc, diag::missing_template_arg_list_after_template_kw);
}
return false;
}
diff --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index 0e6d45419cd249..c587337da5933a 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -88,4 +88,4 @@ CHECK-NEXT: warn_weak_import
The list of warnings in -Wpedantic should NEVER grow.
-CHECK: Number in -Wpedantic (not covered by other -W flags): 27
+CHECK: Number in -Wpedantic (not covered by other -W flags): 26
>From 2375746bb32541dd6ba7d3858e704ec571040152 Mon Sep 17 00:00:00 2001
From: Erick Velez <erickvelez7 at gmail.com>
Date: Thu, 8 Feb 2024 08:59:29 -0800
Subject: [PATCH 4/4] remove trailing whitespace in diagnostic
---
clang/include/clang/Basic/DiagnosticParseKinds.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 93d5160a1589af..2a4302d5dab8d7 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -870,7 +870,7 @@ def err_requires_expr_in_simple_requirement : Error<
"before the expression)">;
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">>,
+ "keyword">, InGroup<DiagGroup<"missing-template-arg-list-after-template-kw">>,
DefaultError;
def err_missing_dependent_template_keyword : Error<
More information about the cfe-commits
mailing list