"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<
"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">;
(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<CXXMethodDecl>(NewFD)) {
if (CheckMemberSpecialization(NewFD, Previous))
NewFD->setInvalidDecl();
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) {
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();
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:
--- /dev/null
+// 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<typename T> void f(T) {}
+template<typename T> static void g(T) {}
+
+
+template<> static void f<int>(int); // expected-error{{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-error{{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);
+template void g<long>(long);
+
+template<typename T>
+struct X {
+ static int value;
+};
+
+template<typename T>
+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-error{{'static' can only be specified inside the class definition}}