@@ -7602,89 +7602,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7602
7602
NTCUC_AutoVar, NTCUK_Destruct);
7603
7603
} else {
7604
7604
bool Invalid = false;
7605
-
7606
- if (DC->isRecord() && !CurContext->isRecord()) {
7607
- // This is an out-of-line definition of a static data member.
7608
- switch (SC) {
7609
- case SC_None:
7610
- break;
7611
- case SC_Static:
7612
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7613
- diag::err_static_out_of_line)
7614
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7615
- break;
7616
- case SC_Auto:
7617
- case SC_Register:
7618
- case SC_Extern:
7619
- // [dcl.stc] p2: The auto or register specifiers shall be applied only
7620
- // to names of variables declared in a block or to function parameters.
7621
- // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7622
- // of class members
7623
-
7624
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7625
- diag::err_storage_class_for_static_member)
7626
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7627
- break;
7628
- case SC_PrivateExtern:
7629
- llvm_unreachable("C storage class in c++!");
7630
- }
7631
- }
7632
-
7633
- if (SC == SC_Static && CurContext->isRecord()) {
7634
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7635
- // Walk up the enclosing DeclContexts to check for any that are
7636
- // incompatible with static data members.
7637
- const DeclContext *FunctionOrMethod = nullptr;
7638
- const CXXRecordDecl *AnonStruct = nullptr;
7639
- for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7640
- if (Ctxt->isFunctionOrMethod()) {
7641
- FunctionOrMethod = Ctxt;
7642
- break;
7643
- }
7644
- const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7645
- if (ParentDecl && !ParentDecl->getDeclName()) {
7646
- AnonStruct = ParentDecl;
7647
- break;
7648
- }
7649
- }
7650
- if (FunctionOrMethod) {
7651
- // C++ [class.static.data]p5: A local class shall not have static data
7652
- // members.
7653
- Diag(D.getIdentifierLoc(),
7654
- diag::err_static_data_member_not_allowed_in_local_class)
7655
- << Name << RD->getDeclName()
7656
- << llvm::to_underlying(RD->getTagKind());
7657
- } else if (AnonStruct) {
7658
- // C++ [class.static.data]p4: Unnamed classes and classes contained
7659
- // directly or indirectly within unnamed classes shall not contain
7660
- // static data members.
7661
- Diag(D.getIdentifierLoc(),
7662
- diag::err_static_data_member_not_allowed_in_anon_struct)
7663
- << Name << llvm::to_underlying(AnonStruct->getTagKind());
7664
- Invalid = true;
7665
- } else if (RD->isUnion()) {
7666
- // C++98 [class.union]p1: If a union contains a static data member,
7667
- // the program is ill-formed. C++11 drops this restriction.
7668
- Diag(D.getIdentifierLoc(),
7669
- getLangOpts().CPlusPlus11
7670
- ? diag::warn_cxx98_compat_static_data_member_in_union
7671
- : diag::ext_static_data_member_in_union) << Name;
7672
- }
7673
- }
7674
- }
7675
-
7676
7605
// Match up the template parameter lists with the scope specifier, then
7677
7606
// determine whether we have a template or a template specialization.
7678
- bool InvalidScope = false;
7679
7607
TemplateParams = MatchTemplateParametersToScopeSpecifier(
7680
7608
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
7681
7609
D.getCXXScopeSpec(),
7682
7610
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
7683
7611
? D.getName().TemplateId
7684
7612
: nullptr,
7685
7613
TemplateParamLists,
7686
- /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
7687
- Invalid |= InvalidScope;
7614
+ /*never a friend*/ false, IsMemberSpecialization, Invalid);
7688
7615
7689
7616
if (TemplateParams) {
7690
7617
if (!TemplateParams->size() &&
@@ -7716,14 +7643,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7716
7643
? diag::warn_cxx11_compat_variable_template
7717
7644
: diag::ext_variable_template);
7718
7645
}
7719
-
7720
- if (CurContext->isRecord() && SC != SC_Static && (IsVariableTemplate || IsPartialSpecialization)) {
7721
- // There is no such thing as a member field template.
7722
- Diag(D.getIdentifierLoc(), diag::err_template_member)
7723
- << II << TemplateParams->getSourceRange();
7724
- // Recover by pretending this is a static data member template.
7725
- SC = SC_Static;
7726
- }
7727
7646
}
7728
7647
} else {
7729
7648
// Check that we can declare a member specialization here.
@@ -7735,6 +7654,88 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7735
7654
"should have a 'template<>' for this decl");
7736
7655
}
7737
7656
7657
+ if (SC != SC_None && ((IsVariableTemplateSpecialization && !IsPartialSpecialization) || IsMemberSpecialization)) {
7658
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7659
+ diag::ext_explicit_specialization_storage_class)
7660
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7661
+ }
7662
+
7663
+ if (CurContext->isRecord()) {
7664
+ if (SC == SC_Static) {
7665
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7666
+ // Walk up the enclosing DeclContexts to check for any that are
7667
+ // incompatible with static data members.
7668
+ const DeclContext *FunctionOrMethod = nullptr;
7669
+ const CXXRecordDecl *AnonStruct = nullptr;
7670
+ for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7671
+ if (Ctxt->isFunctionOrMethod()) {
7672
+ FunctionOrMethod = Ctxt;
7673
+ break;
7674
+ }
7675
+ const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7676
+ if (ParentDecl && !ParentDecl->getDeclName()) {
7677
+ AnonStruct = ParentDecl;
7678
+ break;
7679
+ }
7680
+ }
7681
+ if (FunctionOrMethod) {
7682
+ // C++ [class.static.data]p5: A local class shall not have static data
7683
+ // members.
7684
+ Diag(D.getIdentifierLoc(),
7685
+ diag::err_static_data_member_not_allowed_in_local_class)
7686
+ << Name << RD->getDeclName()
7687
+ << llvm::to_underlying(RD->getTagKind());
7688
+ } else if (AnonStruct) {
7689
+ // C++ [class.static.data]p4: Unnamed classes and classes contained
7690
+ // directly or indirectly within unnamed classes shall not contain
7691
+ // static data members.
7692
+ Diag(D.getIdentifierLoc(),
7693
+ diag::err_static_data_member_not_allowed_in_anon_struct)
7694
+ << Name << llvm::to_underlying(AnonStruct->getTagKind());
7695
+ Invalid = true;
7696
+ } else if (RD->isUnion()) {
7697
+ // C++98 [class.union]p1: If a union contains a static data member,
7698
+ // the program is ill-formed. C++11 drops this restriction.
7699
+ Diag(D.getIdentifierLoc(),
7700
+ getLangOpts().CPlusPlus11
7701
+ ? diag::warn_cxx98_compat_static_data_member_in_union
7702
+ : diag::ext_static_data_member_in_union) << Name;
7703
+ }
7704
+ }
7705
+ } else if (IsVariableTemplate || IsPartialSpecialization) {
7706
+ // There is no such thing as a member field template.
7707
+ Diag(D.getIdentifierLoc(), diag::err_template_member)
7708
+ << II << TemplateParams->getSourceRange();
7709
+ // Recover by pretending this is a static data member template.
7710
+ SC = SC_Static;
7711
+ }
7712
+ } else if (DC->isRecord()) {
7713
+ // This is an out-of-line definition of a static data member.
7714
+ switch (SC) {
7715
+ case SC_None:
7716
+ break;
7717
+ case SC_Static:
7718
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7719
+ diag::err_static_out_of_line)
7720
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7721
+ break;
7722
+ case SC_Auto:
7723
+ case SC_Register:
7724
+ case SC_Extern:
7725
+ // [dcl.stc] p2: The auto or register specifiers shall be applied only
7726
+ // to names of variables declared in a block or to function parameters.
7727
+ // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7728
+ // of class members
7729
+
7730
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7731
+ diag::err_storage_class_for_static_member)
7732
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7733
+ break;
7734
+ case SC_PrivateExtern:
7735
+ llvm_unreachable("C storage class in c++!");
7736
+ }
7737
+ }
7738
+
7738
7739
if (IsVariableTemplateSpecialization) {
7739
7740
SourceLocation TemplateKWLoc =
7740
7741
TemplateParamLists.size() > 0
@@ -10211,26 +10212,37 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10211
10212
NewFD->setImplicitlyInline(ImplicitInlineCXX20);
10212
10213
}
10213
10214
10214
- if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
10215
- !CurContext->isRecord()) {
10216
- // C++ [class.static]p1:
10217
- // A data or function member of a class may be declared static
10218
- // in a class definition, in which case it is a static member of
10219
- // the class.
10220
-
10221
- // Complain about the 'static' specifier if it's on an out-of-line
10222
- // member function definition.
10223
-
10224
- // MSVC permits the use of a 'static' storage specifier on an out-of-line
10225
- // member function template declaration and class member template
10226
- // declaration (MSVC versions before 2015), warn about this.
10227
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10228
- ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10229
- cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10230
- (getLangOpts().MSVCCompat && NewFD->getDescribedFunctionTemplate()))
10231
- ? diag::ext_static_out_of_line : diag::err_static_out_of_line)
10232
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
10215
+ if (!isFriend && SC != SC_None) {
10216
+ if (isFunctionTemplateSpecialization || isMemberSpecialization) {
10217
+ 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");
10222
+ // C++ [class.static]p1:
10223
+ // A data or function member of a class may be declared static
10224
+ // in a class definition, in which case it is a static member of
10225
+ // the class.
10226
+
10227
+ // Complain about the 'static' specifier if it's on an out-of-line
10228
+ // member function definition.
10229
+
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.
10233
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10234
+ ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10235
+ 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());
10239
+ }
10240
+ }
10241
+ #if 0
10242
+ if (SC != SC_None && !isFriend && ) {
10243
+ } else if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) {
10233
10244
}
10245
+ #endif
10234
10246
10235
10247
// C++11 [except.spec]p15:
10236
10248
// A deallocation function with no exception-specification is treated
@@ -10598,6 +10610,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10598
10610
NewFD->setInvalidDecl();
10599
10611
}
10600
10612
10613
+ #if 0
10601
10614
// C++ [dcl.stc]p1:
10602
10615
// A storage-class-specifier shall not be specified in an explicit
10603
10616
// specialization (14.7.3)
@@ -10618,6 +10631,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10618
10631
<< FixItHint::CreateRemoval(
10619
10632
D.getDeclSpec().getStorageClassSpecLoc());
10620
10633
}
10634
+ #endif
10621
10635
} else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
10622
10636
if (CheckMemberSpecialization(NewFD, Previous))
10623
10637
NewFD->setInvalidDecl();
0 commit comments