Skip to content

Commit

Permalink
Clang: Add warning flag for storage class specifiers on explicit spec…
Browse files Browse the repository at this point in the history
…ializations (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)
  • Loading branch information
dwblaikie authored Jun 27, 2024
1 parent aa24e36 commit a1bce0b
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 7 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -1539,3 +1539,7 @@ def BitIntExtension : DiagGroup<"bit-int-extension">;

// Warnings about misuse of ExtractAPI options.
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;

// Warnings about using the non-standard extension having an explicit specialization
// with a storage class specifier.
def ExplicitSpecializationStorageClass : DiagGroup<"explicit-specialization-storage-class">;
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5389,7 +5389,7 @@ def err_not_class_template_specialization : Error<
"cannot specialize a %select{dependent template|template template "
"parameter}0">;
def ext_explicit_specialization_storage_class : ExtWarn<
"explicit specialization cannot have a storage class">;
"explicit specialization cannot have a storage class">, InGroup<ExplicitSpecializationStorageClass>;
def err_dependent_function_template_spec_no_match : Error<
"no candidate function template was found for dependent"
" %select{member|friend}0 function template specialization">;
Expand Down
16 changes: 12 additions & 4 deletions clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify=expected,spec %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-explicit-specialization-storage-class %s

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


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

template<> void f<double>(double);
template void f<long>(long);

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

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

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

template<> static int X<float>::value; // expected-warning{{explicit specialization cannot have a storage class}}
template<> static int X<float>::value; // spec-warning{{explicit specialization cannot have a storage class}}
// expected-error@-1{{'static' can only be specified inside the class definition}}

struct t1 {
template<typename>
static void f1();
template<>
static void f1<int>(); // spec-warning{{explicit specialization cannot have a storage class}}
};
3 changes: 1 addition & 2 deletions clang/test/Misc/warning-flags.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ This test serves two purposes:

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

CHECK: Warnings without flags (66):
CHECK: Warnings without flags (65):

CHECK-NEXT: ext_expected_semi_decl_list
CHECK-NEXT: ext_explicit_specialization_storage_class
CHECK-NEXT: ext_missing_whitespace_after_macro_name
CHECK-NEXT: ext_new_paren_array_nonconst
CHECK-NEXT: ext_plain_complex
Expand Down
18 changes: 18 additions & 0 deletions clang/test/SemaCXX/warn-explicit-specialization-storage-class.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -verify %s
// RUN: %clang_cc1 -triple i686-pc-linux-gnu -fsyntax-only -Wno-explicit-specialization-storage-class -verify=expnone %s

// expnone-no-diagnostics

struct A {
template<typename T>
static constexpr int x = 0;

template<>
static constexpr int x<void> = 1; // expected-warning{{explicit specialization cannot have a storage class}}
};

template<typename T>
static constexpr int x = 0;

template<>
static constexpr int x<void> = 1; // expected-warning{{explicit specialization cannot have a storage class}}

0 comments on commit a1bce0b

Please sign in to comment.