From 84265a09d6251eb68d7ab98ee9befcef3a98a68e Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 17 Jun 2011 05:09:08 +0000 Subject: [PATCH] When an explicit specialization has a storage specifier, error if that storage specifier is different from the storage specifier on the template. If that storage specifier is the same, then we only warn. Thanks to John for the prodding. llvm-svn: 133236 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ clang/lib/Sema/SemaDecl.cpp | 15 ++++++++++++--- clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7cffa3c3b906..66d940cab919 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1914,6 +1914,9 @@ def err_function_specialization_in_class : Error< "cannot specialize a function %0 within class scope">; def ext_explicit_specialization_storage_class : ExtWarn< "explicit specialization cannot have a storage class">; +def err_explicit_specialization_inconsistent_storage_class : Error< + "explicit specialization has extraneous, inconsistent storage class " + "'%select{none|extern|static|__private_extern__|auto|register}0'">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1d92c162a4ec..897b01d09319 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4662,9 +4662,18 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // A storage-class-specifier shall not be specified in an explicit // specialization (14.7.3) if (SC != SC_None) { - Diag(NewFD->getLocation(), - diag::ext_explicit_specialization_storage_class) - << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + if (SC != NewFD->getStorageClass()) + Diag(NewFD->getLocation(), + diag::err_explicit_specialization_inconsistent_storage_class) + << SC + << FixItHint::CreateRemoval( + D.getDeclSpec().getStorageClassSpecLoc()); + + else + Diag(NewFD->getLocation(), + diag::ext_explicit_specialization_storage_class) + << FixItHint::CreateRemoval( + D.getDeclSpec().getStorageClassSpecLoc()); } } else if (isExplicitSpecialization && isa(NewFD)) { diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp index 52e8ed6d99a9..cbb439ef5fec 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp @@ -7,7 +7,7 @@ template void f(T) {} template static void g(T) {} -template<> static void f(int); // expected-warning{{explicit specialization cannot have a storage class}} +template<> static void f(int); // expected-error{{explicit specialization has extraneous, inconsistent storage class 'static'}} template static void f(float); // expected-error{{explicit instantiation cannot have a storage class}} template<> void f(double);