-
Notifications
You must be signed in to change notification settings - Fork 11.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[clang] require template arg list after template kw #80801
Conversation
@llvm/pr-subscribers-clang Author: Erick Velez (evelez7) ChangesRequire a template argument list after an identifier prefixed by the template keyword. Introduced by [CWG 96](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#96). Current wording of [temp.names] introduced in P1787R6. Fixes #53095 Full diff: https://github.com/llvm/llvm-project/pull/80801.diff 8 Files Affected:
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you picking this up!
Since this patch seems to implement current take of the Standard on CWG96, you should change // dr96: no
to // dr96: sup P1787
at dr0xx.cpp:1403
, and then run clang/www/make_cxx_dr_status
script to regenerate cxx_dr_status.html
. While this status is not officially recognized (at least yet), it's the only one that makes sense for CWG96 now.
You should also mention in the description that CWG96 resolution from Feb 2010 is superseded by changes to [temp.names]/5 introduced by P1787R6, to make it easier for people to find exact wording in that gigantic paper.
clang/test/CXX/drs/dr0xx.cpp
Outdated
@@ -1414,7 +1414,7 @@ namespace dr96 { // dr96: no | |||
// FIXME: This is ill-formed, because 'f' is not a template-id and does not |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this FIXME is superseded by P1787R6, the same way 2010 resolution is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what direction of "superseded" you mean here, but (except for the separable alias-template bit) the comment is simply correct (since CWG96; before that any template would do). All that P1787R6 did here was correct the strange use of "name" to refer to (among other things) a template-id and deprecate the T::template NestedTypeTemplate
case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@opensdh Thank you for the clarification. I guess I read N1528 the wrong way.
Would it be a correct statement to make that you deprecated the following case described in that paper?
Consequently, the recommendation of this paper is: If the template keyword is followed by a name that does not have a template-argument-list, the name must refer to a class template and be used in a context in which a class template is valid, otherwise the program is ill-formed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, P1787R6 deprecated that use case; you're supposed to just not use template
there. This is consistent with the recommendation in N1528, but of course we now reject the premise that template
is needed for a template template argument. The reasoning, if it helps, is that compilers already have to deal with ambiguity there:
template<auto> void f(); // #1
template<class> void f(int=0); // #2
template<template<class> class> void f(void*=nullptr); // #3
template<class T> void g() {
// in C++20, [temp.res]/6 and [temp.arg.template]/1 contradict each other here:
f<T::Q>(); // could be #1 or #3
}
template<class T> struct X {
// OK per [temp.local]/1
void h() {f<X>(T());} // could be #2 or #3
void i() {T::template R<X>();} // could be anything
}
Accordingly, CWG1478's question was answered in the negative, and template
(is to be) restricted to the case where it influences the interpretation of a <
.
clang/test/CXX/drs/dr0xx.cpp
Outdated
@@ -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? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, what about alias templates? My guess is that new rules work for them as well: no template argument list — no template
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of 'template' before an alias template is deprecated, along with before a class template. I wasn't sure how to interpret this for clang, they aren't errors yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alias template case was aligned with the class-template case as part of CWG1710.
I was wondering why the Windows CI was failing but seems to be bugged according to Discourse. Handled the pedantic warning properly by putting it in its own diagnostic group as an extension. Thanks to Aaron Ballman. |
ping |
ping @Endilll |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this! The changes should also come with a release note in clang/docs/ReleaseNotes.rst so users know about the change.
// 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 || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about type templates: https://godbolt.org/z/1coGTT38P (hmm we may have a wider issue there, from looking at Clang's current behavior, so a FIXME would be reasonable too).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this case isn't covered here. The error fires before reaching this method. I can try to diagnose it for this patch if needed, or I can do a followup patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's reasonable to handle in a follow-up, thanks!
Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96. Fixes llvm#53095
2375746
to
1e0ecee
Compare
Co-authored-by: Shafik Yaghmour <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the changes are reasonable, but I'd like to wait a bit before landing to give @erichkeane a chance to review as templates code owner.
// 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 || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's reasonable to handle in a follow-up, thanks!
These were made invalid with P1787, and Clang (19) trunk started warning on them with llvm/llvm-project#80801.
llvm/llvm-project#80801 started requiring template arg list after template keyword, which caused issues in our codebase. This patch suppresses that warning to fix the Clang toolchain canary builders. Bug: 344080745 Change-Id: I328d05f3e504b8806dae417142a109504441bf66 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1058727 Reviewed-by: Haowei Wu <[email protected]> Reviewed-by: Roland McGrath <[email protected]> Commit-Queue: Gulfem Savrun Yeniceri <[email protected]> Fuchsia-Auto-Submit: Gulfem Savrun Yeniceri <[email protected]> Reviewed-by: Petr Hosek <[email protected]>
…#36805) Clang now requires a template argument list after the use of the template keyword. Edit this instance to remove the template keyword since there are no template arguments. See llvm/llvm-project#80801. Closes #36805 COPYBARA_INTEGRATE_REVIEW=#36805 from amykhuang:master 6f385be PiperOrigin-RevId: 640554705
llvm/llvm-project#80801 started requiring template arg list after template keyword, which caused issues in our codebase. This patch suppresses that warning to fix the Clang toolchain canary builders. Original-Bug: 344080745 Original-Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1058727 Original-Revision: 2c1c8eaca7c381db7f69eee2106d52661d5614a3 GitOrigin-RevId: d4729713f48a946712ebcced6e4dfc27d432b1f6 Change-Id: I7cf4e3655e33366c23673f0cf3f11852975c960b
These were made invalid with P1787, and Clang (19) trunk started warning on them with llvm/llvm-project#80801.
These were made invalid with P1787, and Clang (19) trunk started warning on them with llvm/llvm-project#80801.
These were made invalid with P1787, and Clang (19) trunk started warning on them with llvm/llvm-project#80801. (cherry picked from commit 397774d42272fff8dbc6d8d53616d79667d6608a)
These were made invalid with P1787, and Clang (19) trunk started warning on them with llvm/llvm-project#80801. (cherry picked from commit 397774d42272fff8dbc6d8d53616d79667d6608a)
Require a template argument list after a name prefixed by the template keyword in nested name specifiers. Addresses [CWG 96](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#96) which was superseded by [P1787](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html). Followup to #80801.
llvm/llvm-project#80801 updates clang to require a list of template arguments after an identifier prefixed by the template keyword. This change updates a call in `multi_ptr_comparison_op.h` to ensure it compiles with the latest clang. Signed-off-by: Michael Aziz <[email protected]>
…4674) Require a template argument list after a name prefixed by the template keyword in nested name specifiers. Addresses [CWG 96](https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#96) which was superseded by [P1787](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html). Followup to llvm#80801.
llvm/llvm-project#80801 started requiring template arg list after template keyword, which caused issues in generated SDK code. patch suppresses that warning unblock clang roll. Bug: 344080745 Change-Id: I7830d4622011cf57f8858f648cd3af2fd397af33 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1080723 Commit-Queue: Haowei Wu <[email protected]> Reviewed-by: David Fang <[email protected]>
llvm/llvm-project#80801 started requiring template arg list after template keyword, which caused issues in generated SDK code. patch suppresses that warning unblock clang roll. Original-Bug: 344080745 Original-Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1080723 Original-Revision: 1c36efd0796795a1ccb526d851dab0fc4a4f0b26 GitOrigin-RevId: 5b7936f1377bb24c35e0d1b122356f37a5a6d57b Change-Id: Idab55f3610bf451acd01fd81e97392c315a13fb8
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801 This patch has also been submitted to upstream TinyDeflate as bisqwit/TinyDeflate#9
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801
…grpc#36805) Clang now requires a template argument list after the use of the template keyword. Edit this instance to remove the template keyword since there are no template arguments. See llvm/llvm-project#80801. Closes grpc#36805 COPYBARA_INTEGRATE_REVIEW=grpc#36805 from amykhuang:master 6f385be PiperOrigin-RevId: 640554705
Require a template argument list after an identifier prefixed by the template keyword. Introduced by CWG 96, but the current wording of [temp.names]p5 was introduced in P1787R6, and became [temp.names]p6 somewhere else.
Fixes #53095