Skip to content

[Clang][Sema] Convert warning for extraneous template parameter lists to an extension warning #82277

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

Merged
merged 1 commit into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ Improvements to Clang's diagnostics
`WG14 N3029 <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3029.htm>`_.
Fixes `#69352 <https://github.com/llvm/llvm-project/issues/69352>`_.

- Clang now diagnoses extraneous template parameter lists as a language extension.

Improvements to Clang's time-trace
----------------------------------

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5325,7 +5325,7 @@ def err_alias_template_extra_headers : Error<
def err_template_spec_extra_headers : Error<
"extraneous template parameter list in template specialization or "
"out-of-line template definition">;
def warn_template_spec_extra_headers : Warning<
def ext_template_spec_extra_headers : ExtWarn<
"extraneous template parameter list in template specialization">;
def note_explicit_template_spec_does_not_need_header : Note<
"'template<>' header not required for explicitly-specialized class %0 "
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3667,7 +3667,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(

if (!SuppressDiagnostic)
Diag(ParamLists[ParamIdx]->getTemplateLoc(),
AllExplicitSpecHeaders ? diag::warn_template_spec_extra_headers
AllExplicitSpecHeaders ? diag::ext_template_spec_extra_headers
: diag::err_template_spec_extra_headers)
<< SourceRange(ParamLists[ParamIdx]->getTemplateLoc(),
ParamLists[ParamLists.size() - 2]->getRAngleLoc());
Expand Down
6 changes: 2 additions & 4 deletions clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p23.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// RUN: %clang_cc1 -std=c++20 -pedantic-errors -verify %s

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

template<typename>
Expand All @@ -18,7 +17,6 @@ void A<T>::g(auto) { }
template<>
void A<int>::g(auto) { }

// FIXME: This should be an error with -pedantic-errors.
template<>
template<> // expected-warning {{extraneous template parameter list in template specialization}}
template<> // expected-error {{extraneous template parameter list in template specialization}}
void A<long>::g(auto) { }
10 changes: 4 additions & 6 deletions clang/test/CXX/drs/dr5xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,17 +354,15 @@ namespace dr531 { // dr531: partial

template<> void A<char>::f(char) {}
// expected-error@-1 {{no function template matches function template specialization 'f'}}
// FIXME: This is ill-formed; -pedantic-errors should reject.
template<> template<typename U> void A<char>::g(char, U) {}
// expected-warning@-1 {{extraneous template parameter list in template specialization}}
// expected-error@-1 {{extraneous template parameter list in template specialization}}
// expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A<char>' declared here}}
template<> struct A<char>::B {};
// expected-error@-1 {{extraneous 'template<>' in declaration of struct 'B'}}
// expected-error@-2 {{specialization of member 'dr531::bad::A<char>::B' does not specialize an instantiated member}}
// expected-note@#dr531-B {{attempt to specialize declaration here}}
// FIXME: This is ill-formed; -pedantic-errors should reject.
template<> template<typename U> struct A<char>::C {};
// expected-warning@-1 {{extraneous template parameter list in template specialization}}
// expected-error@-1 {{extraneous template parameter list in template specialization}}
// expected-note@#dr531-A-char {{'template<>' header not required for explicitly-specialized class 'dr531::bad::A<char>' declared here}}
template<> char A<char>::n = 0;
// expected-error@-1 {{extraneous 'template<>' in declaration of variable 'n'}}
Expand Down Expand Up @@ -808,7 +806,7 @@ namespace dr571 { // dr571 unknown
int n;
// FIXME: Test if this has internal linkage.
const ir r = n;
// expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
// expected-warning@-1 {{'const' qualifier on reference type 'ir' (aka 'int &') has no effect}}
}

namespace dr572 { // dr572: yes
Expand Down Expand Up @@ -990,7 +988,7 @@ namespace dr580 { // dr580: partial
// FIXME: We incorrectly accept this
// because we think C2::Y::A<...> might
// instantiate to C2::X::A
template<X::I> struct A {};
template<X::I> struct A {};
};
};

Expand Down
96 changes: 95 additions & 1 deletion clang/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -pedantic-errors -verify %s
template<class T> struct A {
void f(T);
template<class X1> void g1(T, X1);
Expand Down Expand Up @@ -36,3 +36,97 @@ namespace PR10024 {
template <>
void Test<T>::get<double>(double i) {} // expected-error{{cannot specialize (with 'template<>') a member of an unspecialized template}}
}

namespace extraneous {
template<typename T> struct A;

template<typename T> int x;

template<typename T> void f();

template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
struct A<int>;

template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
int x<int>;

template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
void f<int>();

template<typename T>
struct B {
struct C;

template<typename U>
struct D;

static int y;

template<typename U>
static int z;

void g();

template<typename U>
void h();

enum class E;

enum F : int;
};

template<>
template<> // expected-error{{extraneous 'template<>' in declaration of struct 'C'}}
struct B<int>::C;

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
struct B<int>::D<int>;

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<typename U>
struct B<int>::D;

template<>
template<> // expected-error{{extraneous 'template<>' in declaration of variable 'y'}}
int B<int>::y;

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
int B<int>::z<int>;

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<typename U>
int B<int>::z;

template<>
template<>
void B<int>::g(); // expected-error{{no function template matches function template specialization 'g'}}

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<>
void B<int>::h<int>();

template<>
template<> // expected-error{{extraneous template parameter list in template specialization}}
template<typename U>
void B<int>::h<int>(); // expected-error{{function template partial specialization is not allowed}}

// FIXME: We should diagnose this as having an extraneous 'template<>'
template<>
template<>
enum class B<int>::E; // expected-error{{enumeration cannot be a template}}

// FIXME: We should diagnose this as having an extraneous 'template<>'
template<>
template<>
enum B<int>::F : int; // expected-error{{enumeration cannot be a template}}
}
2 changes: 1 addition & 1 deletion clang/test/Misc/warning-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ CHECK-NEXT: ext_missing_whitespace_after_macro_name
CHECK-NEXT: ext_new_paren_array_nonconst
CHECK-NEXT: ext_plain_complex
CHECK-NEXT: ext_template_arg_extra_parens
CHECK-NEXT: ext_template_spec_extra_headers
CHECK-NEXT: ext_typecheck_cond_incompatible_operands
CHECK-NEXT: ext_typecheck_ordered_comparison_of_pointer_integer
CHECK-NEXT: ext_using_undefined_std
Expand Down Expand Up @@ -78,7 +79,6 @@ CHECK-NEXT: warn_register_objc_catch_parm
CHECK-NEXT: warn_related_result_type_compatibility_class
CHECK-NEXT: warn_related_result_type_compatibility_protocol
CHECK-NEXT: warn_template_export_unsupported
CHECK-NEXT: warn_template_spec_extra_headers
CHECK-NEXT: warn_tentative_incomplete_array
CHECK-NEXT: warn_typecheck_function_qualifiers
CHECK-NEXT: warn_undef_interface
Expand Down