From: Douglas Gregor Date: Sat, 21 May 2011 18:53:30 +0000 (+0000) Subject: Diagnose the presence of storage-class-specifiers on explicit X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e885e188b25dc218132402d1f48fb35e175bfb2e;p=clang Diagnose the presence of storage-class-specifiers on explicit instantiations and specializations. Fixes and PR8700. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131802 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 92a8228f14..00cd81f7e3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1827,6 +1827,8 @@ def err_not_class_template_specialization : Error< "parameter}0">; def err_function_specialization_in_class : Error< "cannot specialize a function %0 within class scope">; +def err_explicit_specialization_storage_class : Error< + "explicit specialization cannot have a storage class">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -1983,6 +1985,8 @@ def err_explicit_instantiation_requires_name : Error< "explicit instantiation declaration requires a name">; def err_explicit_instantiation_of_typedef : Error< "explicit instantiation of typedef %0">; +def err_explicit_instantiation_storage_class : Error< + "explicit instantiation cannot have a storage class">; def err_explicit_instantiation_not_known : Error< "explicit instantiation of %0 does not refer to a function template, member " "function, member class, or static data member">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a5a494877f..3965a45171 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4595,6 +4595,16 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (HasExplicitTemplateArgs ? &TemplateArgs : 0), Previous)) NewFD->setInvalidDecl(); + + // C++ [dcl.stc]p1: + // A storage-class-specifier shall not be specified in an explicit + // specialization (14.7.3) + if (SC != SC_None) { + Diag(NewFD->getLocation(), + diag::err_explicit_specialization_storage_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + } + } else if (isExplicitSpecialization && isa(NewFD)) { if (CheckMemberSpecialization(NewFD, Previous)) NewFD->setInvalidDecl(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 9d8d7f608e..f3392e4183 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5377,7 +5377,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, SpecInfo->getPointOfInstantiation(), HasNoEffect)) return true; - + // Mark the prior declaration as an explicit specialization, so that later // clients know that this is an explicit specialization. if (!isFriend) { @@ -5397,7 +5397,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, TemplArgs, /*InsertPos=*/0, SpecInfo->getTemplateSpecializationKind(), TemplArgsAsWritten); - + FD->setStorageClass(Specialization->getStorageClass()); + // The "previous declaration" for this function template specialization is // the prior function template specialization. Previous.clear(); @@ -5998,11 +5999,20 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (R.isNull()) return true; + // C++ [dcl.stc]p1: + // A storage-class-specifier shall not be specified in [...] an explicit + // instantiation (14.7.2) directive. if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { - // Cannot explicitly instantiate a typedef. Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef) << Name; return true; + } else if (D.getDeclSpec().getStorageClassSpec() + != DeclSpec::SCS_unspecified) { + // Complain about then remove the storage class specifier. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_storage_class) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + + D.getMutableDeclSpec().ClearStorageClassSpecs(); } // C++0x [temp.explicit]p1: diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp new file mode 100644 index 0000000000..40917b8ae3 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p1.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// A storage-class-specifier shall not be specified in an explicit +// specialization (14.7.3) or an explicit instantiation (14.7.2) +// directive. +template void f(T) {} +template static void g(T) {} + + +template<> static void f(int); // expected-error{{explicit specialization cannot have a storage class}} +template static void f(float); // expected-error{{explicit instantiation cannot have a storage class}} + +template<> void f(double); +template void f(long); + +template<> static void g(int); // expected-error{{explicit specialization cannot have a storage class}} +template static void g(float); // expected-error{{explicit instantiation cannot have a storage class}} + +template<> void g(double); +template void g(long); + +template +struct X { + static int value; +}; + +template +int X::value = 17; + +template static int X::value; // expected-error{{explicit instantiation cannot have a storage class}} + +template<> static int X::value; // expected-error{{'static' can only be specified inside the class definition}}