@@ -7609,89 +7609,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76097609 NTCUC_AutoVar, NTCUK_Destruct);
76107610 } else {
76117611 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-
76837612 // Match up the template parameter lists with the scope specifier, then
76847613 // determine whether we have a template or a template specialization.
7685- bool InvalidScope = false;
76867614 TemplateParams = MatchTemplateParametersToScopeSpecifier(
76877615 D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
76887616 D.getCXXScopeSpec(),
76897617 D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
76907618 ? D.getName().TemplateId
76917619 : nullptr,
76927620 TemplateParamLists,
7693- /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
7694- Invalid |= InvalidScope;
7621+ /*never a friend*/ false, IsMemberSpecialization, Invalid);
76957622
76967623 if (TemplateParams) {
76977624 if (!TemplateParams->size() &&
@@ -7734,6 +7661,102 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77347661 "should have a 'template<>' for this decl");
77357662 }
77367663
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+
77377760 if (IsVariableTemplateSpecialization) {
77387761 SourceLocation TemplateKWLoc =
77397762 TemplateParamLists.size() > 0
@@ -7779,8 +7802,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77797802 // the variable (matching the scope specifier), store them.
77807803 // An explicit variable template specialization does not own any template
77817804 // parameter lists.
7782- bool IsExplicitSpecialization =
7783- IsVariableTemplateSpecialization && !IsPartialSpecialization;
77847805 unsigned VDTemplateParamLists =
77857806 (TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
77867807 if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10210,25 +10231,45 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1021010231 NewFD->setImplicitlyInline(ImplicitInlineCXX20);
1021110232 }
1021210233
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+ }
1021910248
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.
1022210256
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+ }
1023210273 }
1023310274
1023410275 // C++11 [except.spec]p15:
@@ -10596,27 +10637,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1059610637 Previous))
1059710638 NewFD->setInvalidDecl();
1059810639 }
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- }
1062010640 } else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
1062110641 if (CheckMemberSpecialization(NewFD, Previous))
1062210642 NewFD->setInvalidDecl();
0 commit comments