Skip to content

Commit e870dc2

Browse files
committed
[FOLD]
1 parent 107f8f7 commit e870dc2

File tree

4 files changed

+58
-56
lines changed

4 files changed

+58
-56
lines changed

clang/lib/Sema/SemaDecl.cpp

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7654,9 +7654,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76547654
"should have a 'template<>' for this decl");
76557655
}
76567656

7657-
if (SCSpec != DeclSpec::SCS_unspecified && ((IsVariableTemplateSpecialization && !IsPartialSpecialization) || IsMemberSpecialization)) {
7657+
bool IsExplicitSpecialization =
7658+
IsVariableTemplateSpecialization && !IsPartialSpecialization;
7659+
7660+
// C++ [temp.expl.spec]p2:
7661+
// The declaration in an explicit-specialization shall not be an
7662+
// export-declaration. An explicit specialization shall not use a
7663+
// storage-class-specifier other than thread_local.
7664+
//
7665+
// We use the storage-class-specifier from DeclSpec because we may have
7666+
// added implicit 'extern' for declarations with __declspec(dllimport)!
7667+
if (SCSpec != DeclSpec::SCS_unspecified &&
7668+
(IsExplicitSpecialization || IsMemberSpecialization)) {
76587669
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7659-
diag::ext_explicit_specialization_storage_class)
7670+
diag::ext_explicit_specialization_storage_class)
76607671
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
76617672
}
76627673

@@ -7679,8 +7690,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76797690
}
76807691
}
76817692
if (FunctionOrMethod) {
7682-
// C++ [class.static.data]p5: A local class shall not have static data
7683-
// members.
7693+
// C++ [class.static.data]p5: A local class shall not have static
7694+
// data members.
76847695
Diag(D.getIdentifierLoc(),
76857696
diag::err_static_data_member_not_allowed_in_local_class)
76867697
<< Name << RD->getDeclName()
@@ -7698,8 +7709,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76987709
// the program is ill-formed. C++11 drops this restriction.
76997710
Diag(D.getIdentifierLoc(),
77007711
getLangOpts().CPlusPlus11
7701-
? diag::warn_cxx98_compat_static_data_member_in_union
7702-
: diag::ext_static_data_member_in_union) << Name;
7712+
? diag::warn_cxx98_compat_static_data_member_in_union
7713+
: diag::ext_static_data_member_in_union)
7714+
<< Name;
77037715
}
77047716
}
77057717
} else if (IsVariableTemplate || IsPartialSpecialization) {
@@ -7717,7 +7729,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77177729
case SC_Static:
77187730
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
77197731
diag::err_static_out_of_line)
7720-
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7732+
<< FixItHint::CreateRemoval(
7733+
D.getDeclSpec().getStorageClassSpecLoc());
77217734
break;
77227735
case SC_Auto:
77237736
case SC_Register:
@@ -7729,7 +7742,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77297742

77307743
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
77317744
diag::err_storage_class_for_static_member)
7732-
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7745+
<< FixItHint::CreateRemoval(
7746+
D.getDeclSpec().getStorageClassSpecLoc());
77337747
break;
77347748
case SC_PrivateExtern:
77357749
llvm_unreachable("C storage class in c++!");
@@ -7781,8 +7795,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77817795
// the variable (matching the scope specifier), store them.
77827796
// An explicit variable template specialization does not own any template
77837797
// parameter lists.
7784-
bool IsExplicitSpecialization =
7785-
IsVariableTemplateSpecialization && !IsPartialSpecialization;
77867798
unsigned VDTemplateParamLists =
77877799
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
77887800
if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10213,12 +10225,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1021310225
}
1021410226

1021510227
if (!isFriend && SC != SC_None) {
10228+
// C++ [temp.expl.spec]p2:
10229+
// The declaration in an explicit-specialization shall not be an
10230+
// export-declaration. An explicit specialization shall not use a
10231+
// storage-class-specifier other than thread_local.
10232+
//
10233+
// We diagnose friend declarations with storage-class-specifiers
10234+
// elsewhere.
1021610235
if (isFunctionTemplateSpecialization || isMemberSpecialization) {
1021710236
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10218-
diag::ext_explicit_specialization_storage_class)
10219-
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
10220-
} else if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
10221-
assert(isa<CXXMethodDecl>(NewFD) && "Out-of-line member function should be a CXXMethodDecl");
10237+
diag::ext_explicit_specialization_storage_class)
10238+
<< FixItHint::CreateRemoval(
10239+
D.getDeclSpec().getStorageClassSpecLoc());
10240+
}
10241+
10242+
if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
10243+
assert(isa<CXXMethodDecl>(NewFD) &&
10244+
"Out-of-line member function should be a CXXMethodDecl");
1022210245
// C++ [class.static]p1:
1022310246
// A data or function member of a class may be declared static
1022410247
// in a class definition, in which case it is a static member of
@@ -10227,22 +10250,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1022710250
// Complain about the 'static' specifier if it's on an out-of-line
1022810251
// member function definition.
1022910252

10230-
// MSVC permits the use of a 'static' storage specifier on an out-of-line
10231-
// member function template declaration and class member template
10232-
// declaration (MSVC versions before 2015), warn about this.
10253+
// MSVC permits the use of a 'static' storage specifier on an
10254+
// out-of-line member function template declaration and class member
10255+
// template declaration (MSVC versions before 2015), warn about this.
1023310256
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
1023410257
((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
1023510258
cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10236-
(getLangOpts().MSVCCompat && NewFD->getDescribedFunctionTemplate()))
10237-
? diag::ext_static_out_of_line : diag::err_static_out_of_line)
10238-
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
10259+
(getLangOpts().MSVCCompat &&
10260+
NewFD->getDescribedFunctionTemplate()))
10261+
? diag::ext_static_out_of_line
10262+
: diag::err_static_out_of_line)
10263+
<< FixItHint::CreateRemoval(
10264+
D.getDeclSpec().getStorageClassSpecLoc());
1023910265
}
1024010266
}
10241-
#if 0
10242-
if (SC != SC_None && !isFriend && ) {
10243-
} else if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) {
10244-
}
10245-
#endif
1024610267

1024710268
// C++11 [except.spec]p15:
1024810269
// A deallocation function with no exception-specification is treated
@@ -10609,29 +10630,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1060910630
Previous))
1061010631
NewFD->setInvalidDecl();
1061110632
}
10612-
10613-
#if 0
10614-
// C++ [dcl.stc]p1:
10615-
// A storage-class-specifier shall not be specified in an explicit
10616-
// specialization (14.7.3)
10617-
// FIXME: We should be checking this for dependent specializations.
10618-
FunctionTemplateSpecializationInfo *Info =
10619-
NewFD->getTemplateSpecializationInfo();
10620-
if (Info && SC != SC_None) {
10621-
if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
10622-
Diag(NewFD->getLocation(),
10623-
diag::err_explicit_specialization_inconsistent_storage_class)
10624-
<< SC
10625-
<< FixItHint::CreateRemoval(
10626-
D.getDeclSpec().getStorageClassSpecLoc());
10627-
10628-
else
10629-
Diag(NewFD->getLocation(),
10630-
diag::ext_explicit_specialization_storage_class)
10631-
<< FixItHint::CreateRemoval(
10632-
D.getDeclSpec().getStorageClassSpecLoc());
10633-
}
10634-
#endif
1063510633
} else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
1063610634
if (CheckMemberSpecialization(NewFD, Previous))
1063710635
NewFD->setInvalidDecl();

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3490,8 +3490,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
34903490
}
34913491

34923492
bool isInstField = (DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
3493-
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
3494-
!isFunc && TemplateParameterLists.empty();
3493+
DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
3494+
!isFunc && TemplateParameterLists.empty();
34953495

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

35423542
IdentifierInfo *II = Name.getAsIdentifierInfo();
35433543

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

35673567
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
35683568
Diag(D.getIdentifierLoc(), diag::err_member_with_template_arguments)

clang/test/CXX/temp/temp.spec/temp.expl.spec/p2-20.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void B::f<unsigned>();
122122

123123
template<>
124124
static void B::g<unsigned>(); // expected-warning {{explicit specialization cannot have a storage class}}
125-
125+
// expected-error@-1 {{'static' can only be specified inside the class definition}}
126126

127127
template<typename T>
128128
struct C {
@@ -159,7 +159,7 @@ void C<int>::f();
159159

160160
template<>
161161
static void C<int>::g(); // expected-warning {{explicit specialization cannot have a storage class}}
162-
162+
// expected-error@-1 {{'static' can only be specified inside the class definition}}
163163
template<typename T>
164164
struct D {
165165
template<typename U>
@@ -263,11 +263,12 @@ void D<int>::f();
263263
template<>
264264
template<typename U>
265265
static void D<int>::g(); // expected-warning {{explicit specialization cannot have a storage class}}
266-
266+
// expected-error@-1 {{'static' can only be specified inside the class definition}}
267267
template<>
268268
template<>
269269
void D<int>::f<unsigned>();
270270

271271
template<>
272272
template<>
273273
static void D<int>::g<unsigned>(); // expected-warning {{explicit specialization cannot have a storage class}}
274+
// expected-error@-1 {{'static' can only be specified inside the class definition}}

clang/test/Modules/redecl-templates.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ int &x = w<1>;
2828
// instantiation of this specialization.
2929
template<> struct A<1> {};
3030
template<> constexpr void f<1>() {}
31-
template<> int v<1>; // expected-error{{redefinition of 'v<1>'}}
31+
// Variable template explicit specializations are always definitions unless they
32+
// are static data members declared without an initializer.
33+
template<> int v<1>; // expected-error {{redefinition of 'v<1>'}}
34+
// expected-note@Inputs/redecl-templates/a.h:8 {{previous definition is here}}

0 commit comments

Comments
 (0)