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