@@ -7602,89 +7602,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76027602 NTCUC_AutoVar, NTCUK_Destruct);
76037603 } else {
76047604 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-
76767605 // Match up the template parameter lists with the scope specifier, then
76777606 // determine whether we have a template or a template specialization.
7678- bool InvalidScope = false;
76797607 TemplateParams = MatchTemplateParametersToScopeSpecifier(
76807608 D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
76817609 D.getCXXScopeSpec(),
76827610 D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
76837611 ? D.getName().TemplateId
76847612 : nullptr,
76857613 TemplateParamLists,
7686- /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
7687- Invalid |= InvalidScope;
7614+ /*never a friend*/ false, IsMemberSpecialization, Invalid);
76887615
76897616 if (TemplateParams) {
76907617 if (!TemplateParams->size() &&
@@ -7716,14 +7643,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77167643 ? diag::warn_cxx11_compat_variable_template
77177644 : diag::ext_variable_template);
77187645 }
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- }
77277646 }
77287647 } else {
77297648 // Check that we can declare a member specialization here.
@@ -7735,6 +7654,88 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77357654 "should have a 'template<>' for this decl");
77367655 }
77377656
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+
77387739 if (IsVariableTemplateSpecialization) {
77397740 SourceLocation TemplateKWLoc =
77407741 TemplateParamLists.size() > 0
@@ -10211,26 +10212,37 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1021110212 NewFD->setImplicitlyInline(ImplicitInlineCXX20);
1021210213 }
1021310214
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()) {
1023310244 }
10245+ #endif
1023410246
1023510247 // C++11 [except.spec]p15:
1023610248 // A deallocation function with no exception-specification is treated
@@ -10598,6 +10610,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1059810610 NewFD->setInvalidDecl();
1059910611 }
1060010612
10613+ #if 0
1060110614 // C++ [dcl.stc]p1:
1060210615 // A storage-class-specifier shall not be specified in an explicit
1060310616 // specialization (14.7.3)
@@ -10618,6 +10631,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1061810631 << FixItHint::CreateRemoval(
1061910632 D.getDeclSpec().getStorageClassSpecLoc());
1062010633 }
10634+ #endif
1062110635 } else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
1062210636 if (CheckMemberSpecialization(NewFD, Previous))
1062310637 NewFD->setInvalidDecl();
0 commit comments