@@ -7601,89 +7601,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7601
7601
NTCUC_AutoVar, NTCUK_Destruct);
7602
7602
} else {
7603
7603
bool Invalid = false;
7604
-
7605
- if (DC->isRecord() && !CurContext->isRecord()) {
7606
- // This is an out-of-line definition of a static data member.
7607
- switch (SC) {
7608
- case SC_None:
7609
- break;
7610
- case SC_Static:
7611
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7612
- diag::err_static_out_of_line)
7613
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7614
- break;
7615
- case SC_Auto:
7616
- case SC_Register:
7617
- case SC_Extern:
7618
- // [dcl.stc] p2: The auto or register specifiers shall be applied only
7619
- // to names of variables declared in a block or to function parameters.
7620
- // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7621
- // of class members
7622
-
7623
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7624
- diag::err_storage_class_for_static_member)
7625
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7626
- break;
7627
- case SC_PrivateExtern:
7628
- llvm_unreachable("C storage class in c++!");
7629
- }
7630
- }
7631
-
7632
- if (SC == SC_Static && CurContext->isRecord()) {
7633
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7634
- // Walk up the enclosing DeclContexts to check for any that are
7635
- // incompatible with static data members.
7636
- const DeclContext *FunctionOrMethod = nullptr;
7637
- const CXXRecordDecl *AnonStruct = nullptr;
7638
- for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7639
- if (Ctxt->isFunctionOrMethod()) {
7640
- FunctionOrMethod = Ctxt;
7641
- break;
7642
- }
7643
- const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7644
- if (ParentDecl && !ParentDecl->getDeclName()) {
7645
- AnonStruct = ParentDecl;
7646
- break;
7647
- }
7648
- }
7649
- if (FunctionOrMethod) {
7650
- // C++ [class.static.data]p5: A local class shall not have static data
7651
- // members.
7652
- Diag(D.getIdentifierLoc(),
7653
- diag::err_static_data_member_not_allowed_in_local_class)
7654
- << Name << RD->getDeclName()
7655
- << llvm::to_underlying(RD->getTagKind());
7656
- } else if (AnonStruct) {
7657
- // C++ [class.static.data]p4: Unnamed classes and classes contained
7658
- // directly or indirectly within unnamed classes shall not contain
7659
- // static data members.
7660
- Diag(D.getIdentifierLoc(),
7661
- diag::err_static_data_member_not_allowed_in_anon_struct)
7662
- << Name << llvm::to_underlying(AnonStruct->getTagKind());
7663
- Invalid = true;
7664
- } else if (RD->isUnion()) {
7665
- // C++98 [class.union]p1: If a union contains a static data member,
7666
- // the program is ill-formed. C++11 drops this restriction.
7667
- Diag(D.getIdentifierLoc(),
7668
- getLangOpts().CPlusPlus11
7669
- ? diag::warn_cxx98_compat_static_data_member_in_union
7670
- : diag::ext_static_data_member_in_union) << Name;
7671
- }
7672
- }
7673
- }
7674
-
7675
7604
// Match up the template parameter lists with the scope specifier, then
7676
7605
// determine whether we have a template or a template specialization.
7677
- bool InvalidScope = false;
7678
7606
TemplateParams = MatchTemplateParametersToScopeSpecifier(
7679
7607
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
7680
7608
D.getCXXScopeSpec(),
7681
7609
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
7682
7610
? D.getName().TemplateId
7683
7611
: nullptr,
7684
7612
TemplateParamLists,
7685
- /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
7686
- Invalid |= InvalidScope;
7613
+ /*never a friend*/ false, IsMemberSpecialization, Invalid);
7687
7614
7688
7615
if (TemplateParams) {
7689
7616
if (!TemplateParams->size() &&
@@ -7726,6 +7653,102 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7726
7653
"should have a 'template<>' for this decl");
7727
7654
}
7728
7655
7656
+ bool IsExplicitSpecialization =
7657
+ IsVariableTemplateSpecialization && !IsPartialSpecialization;
7658
+
7659
+ // C++ [temp.expl.spec]p2:
7660
+ // The declaration in an explicit-specialization shall not be an
7661
+ // export-declaration. An explicit specialization shall not use a
7662
+ // storage-class-specifier other than thread_local.
7663
+ //
7664
+ // We use the storage-class-specifier from DeclSpec because we may have
7665
+ // added implicit 'extern' for declarations with __declspec(dllimport)!
7666
+ if (SCSpec != DeclSpec::SCS_unspecified &&
7667
+ (IsExplicitSpecialization || IsMemberSpecialization)) {
7668
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7669
+ diag::ext_explicit_specialization_storage_class)
7670
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7671
+ }
7672
+
7673
+ if (CurContext->isRecord()) {
7674
+ if (SC == SC_Static) {
7675
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7676
+ // Walk up the enclosing DeclContexts to check for any that are
7677
+ // incompatible with static data members.
7678
+ const DeclContext *FunctionOrMethod = nullptr;
7679
+ const CXXRecordDecl *AnonStruct = nullptr;
7680
+ for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7681
+ if (Ctxt->isFunctionOrMethod()) {
7682
+ FunctionOrMethod = Ctxt;
7683
+ break;
7684
+ }
7685
+ const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7686
+ if (ParentDecl && !ParentDecl->getDeclName()) {
7687
+ AnonStruct = ParentDecl;
7688
+ break;
7689
+ }
7690
+ }
7691
+ if (FunctionOrMethod) {
7692
+ // C++ [class.static.data]p5: A local class shall not have static
7693
+ // data members.
7694
+ Diag(D.getIdentifierLoc(),
7695
+ diag::err_static_data_member_not_allowed_in_local_class)
7696
+ << Name << RD->getDeclName()
7697
+ << llvm::to_underlying(RD->getTagKind());
7698
+ } else if (AnonStruct) {
7699
+ // C++ [class.static.data]p4: Unnamed classes and classes contained
7700
+ // directly or indirectly within unnamed classes shall not contain
7701
+ // static data members.
7702
+ Diag(D.getIdentifierLoc(),
7703
+ diag::err_static_data_member_not_allowed_in_anon_struct)
7704
+ << Name << llvm::to_underlying(AnonStruct->getTagKind());
7705
+ Invalid = true;
7706
+ } else if (RD->isUnion()) {
7707
+ // C++98 [class.union]p1: If a union contains a static data member,
7708
+ // the program is ill-formed. C++11 drops this restriction.
7709
+ Diag(D.getIdentifierLoc(),
7710
+ getLangOpts().CPlusPlus11
7711
+ ? diag::warn_cxx98_compat_static_data_member_in_union
7712
+ : diag::ext_static_data_member_in_union)
7713
+ << Name;
7714
+ }
7715
+ }
7716
+ } else if (IsVariableTemplate || IsPartialSpecialization) {
7717
+ // There is no such thing as a member field template.
7718
+ Diag(D.getIdentifierLoc(), diag::err_template_member)
7719
+ << II << TemplateParams->getSourceRange();
7720
+ // Recover by pretending this is a static data member template.
7721
+ SC = SC_Static;
7722
+ }
7723
+ } else if (DC->isRecord()) {
7724
+ // This is an out-of-line definition of a static data member.
7725
+ switch (SC) {
7726
+ case SC_None:
7727
+ break;
7728
+ case SC_Static:
7729
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7730
+ diag::err_static_out_of_line)
7731
+ << FixItHint::CreateRemoval(
7732
+ D.getDeclSpec().getStorageClassSpecLoc());
7733
+ break;
7734
+ case SC_Auto:
7735
+ case SC_Register:
7736
+ case SC_Extern:
7737
+ // [dcl.stc] p2: The auto or register specifiers shall be applied only
7738
+ // to names of variables declared in a block or to function parameters.
7739
+ // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7740
+ // of class members
7741
+
7742
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7743
+ diag::err_storage_class_for_static_member)
7744
+ << FixItHint::CreateRemoval(
7745
+ D.getDeclSpec().getStorageClassSpecLoc());
7746
+ break;
7747
+ case SC_PrivateExtern:
7748
+ llvm_unreachable("C storage class in c++!");
7749
+ }
7750
+ }
7751
+
7729
7752
if (IsVariableTemplateSpecialization) {
7730
7753
SourceLocation TemplateKWLoc =
7731
7754
TemplateParamLists.size() > 0
@@ -7771,8 +7794,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7771
7794
// the variable (matching the scope specifier), store them.
7772
7795
// An explicit variable template specialization does not own any template
7773
7796
// parameter lists.
7774
- bool IsExplicitSpecialization =
7775
- IsVariableTemplateSpecialization && !IsPartialSpecialization;
7776
7797
unsigned VDTemplateParamLists =
7777
7798
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
7778
7799
if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10202,25 +10223,45 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10202
10223
NewFD->setImplicitlyInline(ImplicitInlineCXX20);
10203
10224
}
10204
10225
10205
- if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
10206
- !CurContext->isRecord()) {
10207
- // C++ [class.static]p1:
10208
- // A data or function member of a class may be declared static
10209
- // in a class definition, in which case it is a static member of
10210
- // the class.
10226
+ if (!isFriend && SC != SC_None) {
10227
+ // C++ [temp.expl.spec]p2:
10228
+ // The declaration in an explicit-specialization shall not be an
10229
+ // export-declaration. An explicit specialization shall not use a
10230
+ // storage-class-specifier other than thread_local.
10231
+ //
10232
+ // We diagnose friend declarations with storage-class-specifiers
10233
+ // elsewhere.
10234
+ if (isFunctionTemplateSpecialization || isMemberSpecialization) {
10235
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10236
+ diag::ext_explicit_specialization_storage_class)
10237
+ << FixItHint::CreateRemoval(
10238
+ D.getDeclSpec().getStorageClassSpecLoc());
10239
+ }
10211
10240
10212
- // Complain about the 'static' specifier if it's on an out-of-line
10213
- // member function definition.
10241
+ if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
10242
+ assert(isa<CXXMethodDecl>(NewFD) &&
10243
+ "Out-of-line member function should be a CXXMethodDecl");
10244
+ // C++ [class.static]p1:
10245
+ // A data or function member of a class may be declared static
10246
+ // in a class definition, in which case it is a static member of
10247
+ // the class.
10214
10248
10215
- // MSVC permits the use of a 'static' storage specifier on an out-of-line
10216
- // member function template declaration and class member template
10217
- // declaration (MSVC versions before 2015), warn about this.
10218
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10219
- ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10220
- cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10221
- (getLangOpts().MSVCCompat && NewFD->getDescribedFunctionTemplate()))
10222
- ? diag::ext_static_out_of_line : diag::err_static_out_of_line)
10223
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
10249
+ // Complain about the 'static' specifier if it's on an out-of-line
10250
+ // member function definition.
10251
+
10252
+ // MSVC permits the use of a 'static' storage specifier on an
10253
+ // out-of-line member function template declaration and class member
10254
+ // template declaration (MSVC versions before 2015), warn about this.
10255
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10256
+ ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10257
+ cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10258
+ (getLangOpts().MSVCCompat &&
10259
+ NewFD->getDescribedFunctionTemplate()))
10260
+ ? diag::ext_static_out_of_line
10261
+ : diag::err_static_out_of_line)
10262
+ << FixItHint::CreateRemoval(
10263
+ D.getDeclSpec().getStorageClassSpecLoc());
10264
+ }
10224
10265
}
10225
10266
10226
10267
// C++11 [except.spec]p15:
@@ -10588,27 +10629,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10588
10629
Previous))
10589
10630
NewFD->setInvalidDecl();
10590
10631
}
10591
-
10592
- // C++ [dcl.stc]p1:
10593
- // A storage-class-specifier shall not be specified in an explicit
10594
- // specialization (14.7.3)
10595
- // FIXME: We should be checking this for dependent specializations.
10596
- FunctionTemplateSpecializationInfo *Info =
10597
- NewFD->getTemplateSpecializationInfo();
10598
- if (Info && SC != SC_None) {
10599
- if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
10600
- Diag(NewFD->getLocation(),
10601
- diag::err_explicit_specialization_inconsistent_storage_class)
10602
- << SC
10603
- << FixItHint::CreateRemoval(
10604
- D.getDeclSpec().getStorageClassSpecLoc());
10605
-
10606
- else
10607
- Diag(NewFD->getLocation(),
10608
- diag::ext_explicit_specialization_storage_class)
10609
- << FixItHint::CreateRemoval(
10610
- D.getDeclSpec().getStorageClassSpecLoc());
10611
- }
10612
10632
} else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
10613
10633
if (CheckMemberSpecialization(NewFD, Previous))
10614
10634
NewFD->setInvalidDecl();
0 commit comments