Skip to content

Commit

Permalink
[FOLD]
Browse files Browse the repository at this point in the history
  • Loading branch information
sdkrystian committed May 29, 2024
1 parent 107f8f7 commit e870dc2
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 56 deletions.
94 changes: 46 additions & 48 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7654,9 +7654,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
"should have a 'template<>' for this decl");
}

if (SCSpec != DeclSpec::SCS_unspecified && ((IsVariableTemplateSpecialization && !IsPartialSpecialization) || IsMemberSpecialization)) {
bool IsExplicitSpecialization =
IsVariableTemplateSpecialization && !IsPartialSpecialization;

// C++ [temp.expl.spec]p2:
// The declaration in an explicit-specialization shall not be an
// export-declaration. An explicit specialization shall not use a
// storage-class-specifier other than thread_local.
//
// We use the storage-class-specifier from DeclSpec because we may have
// added implicit 'extern' for declarations with __declspec(dllimport)!
if (SCSpec != DeclSpec::SCS_unspecified &&
(IsExplicitSpecialization || IsMemberSpecialization)) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::ext_explicit_specialization_storage_class)
diag::ext_explicit_specialization_storage_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
}

Expand All @@ -7679,8 +7690,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}
}
if (FunctionOrMethod) {
// C++ [class.static.data]p5: A local class shall not have static data
// members.
// C++ [class.static.data]p5: A local class shall not have static
// data members.
Diag(D.getIdentifierLoc(),
diag::err_static_data_member_not_allowed_in_local_class)
<< Name << RD->getDeclName()
Expand All @@ -7698,8 +7709,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// the program is ill-formed. C++11 drops this restriction.
Diag(D.getIdentifierLoc(),
getLangOpts().CPlusPlus11
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union) << Name;
? diag::warn_cxx98_compat_static_data_member_in_union
: diag::ext_static_data_member_in_union)
<< Name;
}
}
} else if (IsVariableTemplate || IsPartialSpecialization) {
Expand All @@ -7717,7 +7729,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
case SC_Static:
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
break;
case SC_Auto:
case SC_Register:
Expand All @@ -7729,7 +7742,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(

Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::err_storage_class_for_static_member)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
break;
case SC_PrivateExtern:
llvm_unreachable("C storage class in c++!");
Expand Down Expand Up @@ -7781,8 +7795,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// the variable (matching the scope specifier), store them.
// An explicit variable template specialization does not own any template
// parameter lists.
bool IsExplicitSpecialization =
IsVariableTemplateSpecialization && !IsPartialSpecialization;
unsigned VDTemplateParamLists =
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
if (TemplateParamLists.size() > VDTemplateParamLists)
Expand Down Expand Up @@ -10213,12 +10225,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}

if (!isFriend && SC != SC_None) {
// C++ [temp.expl.spec]p2:
// The declaration in an explicit-specialization shall not be an
// export-declaration. An explicit specialization shall not use a
// storage-class-specifier other than thread_local.
//
// We diagnose friend declarations with storage-class-specifiers
// elsewhere.
if (isFunctionTemplateSpecialization || isMemberSpecialization) {
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
diag::ext_explicit_specialization_storage_class)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
} else if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
assert(isa<CXXMethodDecl>(NewFD) && "Out-of-line member function should be a CXXMethodDecl");
diag::ext_explicit_specialization_storage_class)
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
}

if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
assert(isa<CXXMethodDecl>(NewFD) &&
"Out-of-line member function should be a CXXMethodDecl");
// C++ [class.static]p1:
// A data or function member of a class may be declared static
// in a class definition, in which case it is a static member of
Expand All @@ -10227,22 +10250,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Complain about the 'static' specifier if it's on an out-of-line
// member function definition.

// MSVC permits the use of a 'static' storage specifier on an out-of-line
// member function template declaration and class member template
// declaration (MSVC versions before 2015), warn about this.
// MSVC permits the use of a 'static' storage specifier on an
// out-of-line member function template declaration and class member
// template declaration (MSVC versions before 2015), warn about this.
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
(getLangOpts().MSVCCompat && NewFD->getDescribedFunctionTemplate()))
? diag::ext_static_out_of_line : diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
(getLangOpts().MSVCCompat &&
NewFD->getDescribedFunctionTemplate()))
? diag::ext_static_out_of_line
: diag::err_static_out_of_line)
<< FixItHint::CreateRemoval(
D.getDeclSpec().getStorageClassSpecLoc());
}
}
#if 0
if (SC != SC_None && !isFriend && ) {
} else if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) {
}
#endif

// C++11 [except.spec]p15:
// A deallocation function with no exception-specification is treated
Expand Down Expand Up @@ -10609,29 +10630,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
Previous))
NewFD->setInvalidDecl();
}

#if 0
// C++ [dcl.stc]p1:
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
// FIXME: We should be checking this for dependent specializations.
FunctionTemplateSpecializationInfo *Info =
NewFD->getTemplateSpecializationInfo();
if (Info && SC != SC_None) {
if (SC != Info->getTemplate()->getTemplatedDecl()->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());
}
#endif
} else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
if (CheckMemberSpecialization(NewFD, Previous))
NewFD->setInvalidDecl();
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3490,8 +3490,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
}

bool isInstField = (DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc && TemplateParameterLists.empty();
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
!isFunc && TemplateParameterLists.empty();

if (DS.hasConstexprSpecifier() && isInstField) {
SemaDiagnosticBuilder B =
Expand Down Expand Up @@ -3541,7 +3541,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,

IdentifierInfo *II = Name.getAsIdentifierInfo();

#if 0
#if 0
// Member field could not be with "template" keyword.
// So TemplateParameterLists should be empty in this case.
if (TemplateParameterLists.size()) {
Expand All @@ -3562,7 +3562,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
}
return nullptr;
}
#endif
#endif

if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
Diag(D.getIdentifierLoc(), diag::err_member_with_template_arguments)
Expand Down
7 changes: 4 additions & 3 deletions clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void B::f<unsigned>();

template<>
static void B::g<unsigned>(); // expected-warning {{explicit specialization cannot have a storage class}}

// expected-error@-1 {{'static' can only be specified inside the class definition}}

template<typename T>
struct C {
Expand Down Expand Up @@ -159,7 +159,7 @@ void C<int>::f();

template<>
static void C<int>::g(); // expected-warning {{explicit specialization cannot have a storage class}}

// expected-error@-1 {{'static' can only be specified inside the class definition}}
template<typename T>
struct D {
template<typename U>
Expand Down Expand Up @@ -263,11 +263,12 @@ void D<int>::f();
template<>
template<typename U>
static void D<int>::g(); // expected-warning {{explicit specialization cannot have a storage class}}

// expected-error@-1 {{'static' can only be specified inside the class definition}}
template<>
template<>
void D<int>::f<unsigned>();

template<>
template<>
static void D<int>::g<unsigned>(); // expected-warning {{explicit specialization cannot have a storage class}}
// expected-error@-1 {{'static' can only be specified inside the class definition}}
5 changes: 4 additions & 1 deletion clang/test/Modules/redecl-templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,7 @@ int &x = w<1>;
// instantiation of this specialization.
template<> struct A<1> {};
template<> constexpr void f<1>() {}
template<> int v<1>; // expected-error{{redefinition of 'v<1>'}}
// Variable template explicit specializations are always definitions unless they
// are static data members declared without an initializer.
template<> int v<1>; // expected-error {{redefinition of 'v<1>'}}
// expected-note@Inputs/redecl-templates/a.h:8 {{previous definition is here}}

0 comments on commit e870dc2

Please sign in to comment.