Skip to content

Commit 8302cef

Browse files
authored
[Clang][Sema] Convert warning for extraneous template parameter lists to an extension warning (#82277)
We currently accept the following explicit specialization with a warning for the extraneous template parameter list: ``` template<typename T> void f(); template<> template<> void f<int>(); // warning: extraneous template parameter list in template specialization ``` This should really be an extension warning so we reject with `-pedantic-errors`. This patch converts the warning to an extension warning.
1 parent d2173d8 commit 8302cef

File tree

7 files changed

+106
-14
lines changed

7 files changed

+106
-14
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ Improvements to Clang's diagnostics
209209
`WG14 N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm>`_.
210210
Fixes `#69352 <https://github.com/llvm/llvm-project/issues/69352>`_.
211211

212+
- Clang now diagnoses extraneous template parameter lists as a language extension.
213+
212214
Improvements to Clang's time-trace
213215
----------------------------------
214216

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5325,7 +5325,7 @@ def err_alias_template_extra_headers : Error<
53255325
def err_template_spec_extra_headers : Error<
53265326
"extraneous template parameter list in template specialization or "
53275327
"out-of-line template definition">;
5328-
def warn_template_spec_extra_headers : Warning<
5328+
def ext_template_spec_extra_headers : ExtWarn<
53295329
"extraneous template parameter list in template specialization">;
53305330
def note_explicit_template_spec_does_not_need_header : Note<
53315331
"'template<>' header not required for explicitly-specialized class %0 "

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3667,7 +3667,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
36673667

36683668
if (!SuppressDiagnostic)
36693669
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
3670-
AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
3670+
AllExplicitSpecHeaders ? diag::ext_template_spec_extra_headers
36713671
: diag::err_template_spec_extra_headers)
36723672
<< SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
36733673
ParamLists[ParamLists.size() - 2]->getRAngleLoc());

clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify %s
22

3-
// FIXME: This should be an error with -pedantic-errors.
4-
template<> // expected-warning {{extraneous template parameter list in template specialization}}
3+
template<> // expected-error {{extraneous template parameter list in template specialization}}
54
void f(auto);
65

76
template<typename>
@@ -18,7 +17,6 @@ void A<T>::g(auto) { }
1817
template<>
1918
void A<int>::g(auto) { }
2019

21-
// FIXME: This should be an error with -pedantic-errors.
2220
template<>
23-
template<> // expected-warning {{extraneous template parameter list in template specialization}}
21+
template<> // expected-error {{extraneous template parameter list in template specialization}}
2422
void A<long>::g(auto) { }

clang/test/CXX/drs/dr5xx.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -354,17 +354,15 @@ namespace dr531 { // dr531: partial
354354

355355
template<> void A<char>::f(char) {}
356356
// expected-error@-1 {{no function template matches function template specialization 'f'}}
357-
// FIXME: This is ill-formed; -pedantic-errors should reject.
358357
template<> template<typename U> void A<char>::g(char, U) {}
359-
// expected-warning@-1 {{extraneous template parameter list in template specialization}}
358+
// expected-error@-1 {{extraneous template parameter list in template specialization}}
360359
// expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A<char>' declared here}}
361360
template<> struct A<char>::B {};
362361
// expected-error@-1 {{extraneous 'template<>' in declaration of struct 'B'}}
363362
// expected-error@-2 {{specialization of member 'dr531::bad::A<char>::B' does not specialize an instantiated member}}
364363
// expected-note@#dr531-B {{attempt to specialize declaration here}}
365-
// FIXME: This is ill-formed; -pedantic-errors should reject.
366364
template<> template<typename U> struct A<char>::C {};
367-
// expected-warning@-1 {{extraneous template parameter list in template specialization}}
365+
// expected-error@-1 {{extraneous template parameter list in template specialization}}
368366
// expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A<char>' declared here}}
369367
template<> char A<char>::n = 0;
370368
// expected-error@-1 {{extraneous 'template<>' in declaration of variable 'n'}}
@@ -808,7 +806,7 @@ namespace dr571 { // dr571 unknown
808806
int n;
809807
// FIXME: Test if this has internal linkage.
810808
const ir r = n;
811-
// expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
809+
// expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
812810
}
813811

814812
namespace dr572 { // dr572: yes
@@ -990,7 +988,7 @@ namespace dr580 { // dr580: partial
990988
// FIXME: We incorrectly accept this
991989
// because we think C2::Y::A<...> might
992990
// instantiate to C2::X::A
993-
template<X::I> struct A {};
991+
template<X::I> struct A {};
994992
};
995993
};
996994

clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -fsyntax-only -pedantic-errors -verify %s
22
template<class T> struct A {
33
void f(T);
44
template<class X1> void g1(T, X1);
@@ -36,3 +36,97 @@ namespace PR10024 {
3636
template <>
3737
void Test<T>::get<double>(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}}
3838
}
39+
40+
namespace extraneous {
41+
template<typename T> struct A;
42+
43+
template<typename T> int x;
44+
45+
template<typename T> void f();
46+
47+
template<> // expected-error{{extraneous template parameter list in template specialization}}
48+
template<>
49+
struct A<int>;
50+
51+
template<> // expected-error{{extraneous template parameter list in template specialization}}
52+
template<>
53+
int x<int>;
54+
55+
template<> // expected-error{{extraneous template parameter list in template specialization}}
56+
template<>
57+
void f<int>();
58+
59+
template<typename T>
60+
struct B {
61+
struct C;
62+
63+
template<typename U>
64+
struct D;
65+
66+
static int y;
67+
68+
template<typename U>
69+
static int z;
70+
71+
void g();
72+
73+
template<typename U>
74+
void h();
75+
76+
enum class E;
77+
78+
enum F : int;
79+
};
80+
81+
template<>
82+
template<> // expected-error{{extraneous 'template<>' in declaration of struct 'C'}}
83+
struct B<int>::C;
84+
85+
template<>
86+
template<> // expected-error{{extraneous template parameter list in template specialization}}
87+
template<>
88+
struct B<int>::D<int>;
89+
90+
template<>
91+
template<> // expected-error{{extraneous template parameter list in template specialization}}
92+
template<typename U>
93+
struct B<int>::D;
94+
95+
template<>
96+
template<> // expected-error{{extraneous 'template<>' in declaration of variable 'y'}}
97+
int B<int>::y;
98+
99+
template<>
100+
template<> // expected-error{{extraneous template parameter list in template specialization}}
101+
template<>
102+
int B<int>::z<int>;
103+
104+
template<>
105+
template<> // expected-error{{extraneous template parameter list in template specialization}}
106+
template<typename U>
107+
int B<int>::z;
108+
109+
template<>
110+
template<>
111+
void B<int>::g(); // expected-error{{no function template matches function template specialization 'g'}}
112+
113+
template<>
114+
template<> // expected-error{{extraneous template parameter list in template specialization}}
115+
template<>
116+
void B<int>::h<int>();
117+
118+
template<>
119+
template<> // expected-error{{extraneous template parameter list in template specialization}}
120+
template<typename U>
121+
void B<int>::h<int>(); // expected-error{{function template partial specialization is not allowed}}
122+
123+
// FIXME: We should diagnose this as having an extraneous 'template<>'
124+
template<>
125+
template<>
126+
enum class B<int>::E; // expected-error{{enumeration cannot be a template}}
127+
128+
// FIXME: We should diagnose this as having an extraneous 'template<>'
129+
template<>
130+
template<>
131+
enum B<int>::F : int; // expected-error{{enumeration cannot be a template}}
132+
}

clang/test/Misc/warning-flags.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ CHECK-NEXT: ext_missing_whitespace_after_macro_name
2626
CHECK-NEXT: ext_new_paren_array_nonconst
2727
CHECK-NEXT: ext_plain_complex
2828
CHECK-NEXT: ext_template_arg_extra_parens
29+
CHECK-NEXT: ext_template_spec_extra_headers
2930
CHECK-NEXT: ext_typecheck_cond_incompatible_operands
3031
CHECK-NEXT: ext_typecheck_ordered_comparison_of_pointer_integer
3132
CHECK-NEXT: ext_using_undefined_std
@@ -78,7 +79,6 @@ CHECK-NEXT: warn_register_objc_catch_parm
7879
CHECK-NEXT: warn_related_result_type_compatibility_class
7980
CHECK-NEXT: warn_related_result_type_compatibility_protocol
8081
CHECK-NEXT: warn_template_export_unsupported
81-
CHECK-NEXT: warn_template_spec_extra_headers
8282
CHECK-NEXT: warn_tentative_incomplete_array
8383
CHECK-NEXT: warn_typecheck_function_qualifiers
8484
CHECK-NEXT: warn_undef_interface

0 commit comments

Comments
 (0)