Diagnose the presence of storage-class-specifiers on explicit

instantiations and specializations. Fixes <rdar://problem/9126453> and PR8700.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131802 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-05-21 18:53:30 +00:00
Родитель 4337dc7760
Коммит e885e188b2
4 изменённых файлов: 59 добавлений и 3 удалений

Просмотреть файл

@ -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">;

Просмотреть файл

@ -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<CXXMethodDecl>(NewFD)) {
if (CheckMemberSpecialization(NewFD, Previous))
NewFD->setInvalidDecl();

Просмотреть файл

@ -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:

Просмотреть файл

@ -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<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}}