Skip to content

Commit a1bce0b

Browse files
authored
Clang: Add warning flag for storage class specifiers on explicit specializations (llvm#96699)
With the recent fix for this situation in class members (llvm#93873) (for which the fixed code is invalid prior to this patch - making migrating code difficult as it must be in lock-step with the compiler migration, if building with -Werror) it'd be really useful to be able to disable this warning during the compiler migration/decouple the compiler migration from the source fixes. In theory this approach will regress the codebase to the previous non-member cases of this issue that were already being held back by the warning (as opposed to if we carved out the new cases into a separate warning from the existing cases) but I think this'll be so rare and the cleanup so simple, that the extra regressions of disabling the warning broadly won't be too much of a problem. (but if folks disagree, I'm open to making the warning more fine-grained)
1 parent aa24e36 commit a1bce0b

File tree

5 files changed

+36
-7
lines changed

5 files changed

+36
-7
lines changed

clang/include/clang/Basic/DiagnosticGroups.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,3 +1539,7 @@ def BitIntExtension : DiagGroup<"bit-int-extension">;
15391539

15401540
// Warnings about misuse of ExtractAPI options.
15411541
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
1542+
1543+
// Warnings about using the non-standard extension having an explicit specialization
1544+
// with a storage class specifier.
1545+
def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-storage-class">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5389,7 +5389,7 @@ def err_not_class_template_specialization : Error<
53895389
"cannot specialize a %select{dependent template|template template "
53905390
"parameter}0">;
53915391
def ext_explicit_specialization_storage_class : ExtWarn<
5392-
"explicit specialization cannot have a storage class">;
5392+
"explicit specialization cannot have a storage class">, InGroup<ExplicitSpecializationStorageClass>;
53935393
def err_dependent_function_template_spec_no_match : Error<
53945394
"no candidate function template was found for dependent"
53955395
" %select{member|friend}0 function template specialization">;

clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -fsyntax-only -verify %s
1+
// RUN: %clang_cc1 -fsyntax-only -verify=expected,spec %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-explicit-specialization-storage-class %s
23

34
// A storage-class-specifier shall not be specified in an explicit
45
// specialization (14.7.3) or an explicit instantiation (14.7.2)
@@ -7,13 +8,13 @@ template<typename T> void f(T) {}
78
template<typename T> static void g(T) {}
89

910

10-
template<> static void f<int>(int); // expected-warning{{explicit specialization cannot have a storage class}}
11+
template<> static void f<int>(int); // spec-warning{{explicit specialization cannot have a storage class}}
1112
template static void f<float>(float); // expected-error{{explicit instantiation cannot have a storage class}}
1213

1314
template<> void f<double>(double);
1415
template void f<long>(long);
1516

16-
template<> static void g<int>(int); // expected-warning{{explicit specialization cannot have a storage class}}
17+
template<> static void g<int>(int); // spec-warning{{explicit specialization cannot have a storage class}}
1718
template static void g<float>(float); // expected-error{{explicit instantiation cannot have a storage class}}
1819

1920
template<> void g<double>(double);
@@ -29,5 +30,12 @@ int X<T>::value = 17;
2930

3031
template static int X<int>::value; // expected-error{{explicit instantiation cannot have a storage class}}
3132

32-
template<> static int X<float>::value; // expected-warning{{explicit specialization cannot have a storage class}}
33+
template<> static int X<float>::value; // spec-warning{{explicit specialization cannot have a storage class}}
3334
// expected-error@-1{{'static' can only be specified inside the class definition}}
35+
36+
struct t1 {
37+
template<typename>
38+
static void f1();
39+
template<>
40+
static void f1<int>(); // spec-warning{{explicit specialization cannot have a storage class}}
41+
};

clang/test/Misc/warning-flags.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ This test serves two purposes:
1818

1919
The list of warnings below should NEVER grow. It should gradually shrink to 0.
2020

21-
CHECK: Warnings without flags (66):
21+
CHECK: Warnings without flags (65):
2222

2323
CHECK-NEXT: ext_expected_semi_decl_list
24-
CHECK-NEXT: ext_explicit_specialization_storage_class
2524
CHECK-NEXT: ext_missing_whitespace_after_macro_name
2625
CHECK-NEXT: ext_new_paren_array_nonconst
2726
CHECK-NEXT: ext_plain_complex
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -verify %s
2+
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-explicit-specialization-storage-class -verify=expnone %s
3+
4+
// expnone-no-diagnostics
5+
6+
struct A {
7+
template<typename T>
8+
static constexpr int x = 0;
9+
10+
template<>
11+
static constexpr int x<void> = 1; // expected-warning{{explicit specialization cannot have a storage class}}
12+
};
13+
14+
template<typename T>
15+
static constexpr int x = 0;
16+
17+
template<>
18+
static constexpr int x<void> = 1; // expected-warning{{explicit specialization cannot have a storage class}}

0 commit comments

Comments
 (0)