-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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.
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
cherry-picked: 9e1f1cf [email protected] Tue Jul 9 16:40:53 2024 -0400 [Clang][Sema] Handle class member access expressions with valid nested-name-specifiers that become invalid after lookup (llvm#98167) 584e431 [email protected] Wed Jul 3 12:12:53 2024 -0400 [Clang][Sema] Treat explicit specializations of static data member templates declared without 'static' as static data members when diagnosing uses of 'auto' (llvm#97425) a1bce0b [email protected] Thu Jun 27 08:17:40 2024 -0700 Clang: Add warning flag for storage class specifiers on explicit specializations (llvm#96699) f46d146 [email protected] Fri May 31 11:02:21 2024 -0700 [clang] require template arg list after template kw (llvm#80801) 033ec09 [email protected] Fri Dec 22 09:00:41 2023 +0800 [Clang][Sema] Fix Wswitch-default bad warning in template (llvm#76007) c281782 [email protected] Thu Dec 7 09:03:15 2023 +0800 [clang][Sema] Add -Wswitch-default warning option (llvm#73077) Change-Id: Ib2582201b01cc62c3bf62011347925556e8531f7
…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
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801 Obtained from: Bernhard Rosenkränzer, via bisqwit/TinyDeflate@68ced8b PR: 259331 (comment #6) Reported by: Tamaoki Aoki Approved by: portmgr@ (blanket approval for fixing broken builds) (cherry picked from commit 4bd9003)
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801 Obtained from: Bernhard Rosenkränzer, via bisqwit/TinyDeflate@68ced8b PR: 259331 (comment #6) Reported by: Tamaoki Aoki Approved by: portmgr@ (blanket approval for fixing broken builds)
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801 Obtained from: Bernhard Rosenkränzer, via bisqwit/TinyDeflate@68ced8b PR: 259331 (comment freebsd#6) Reported by: Tamaoki Aoki Approved by: portmgr@ (blanket approval for fixing broken builds)
Clang >= 19.0 requires a template argument list after the template keyword for CWG96 compliance, see llvm/llvm-project#80801 Obtained from: Bernhard Rosenkränzer, via bisqwit/TinyDeflate@68ced8b PR: 259331 (comment freebsd#6) Reported by: Tamaoki Aoki Approved by: portmgr@ (blanket approval for fixing broken builds)
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