@@ -7654,9 +7654,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76547654 "should have a 'template<>' for this decl");
76557655 }
76567656
7657- if (SCSpec != DeclSpec::SCS_unspecified && ((IsVariableTemplateSpecialization && !IsPartialSpecialization) || IsMemberSpecialization)) {
7657+ bool IsExplicitSpecialization =
7658+ IsVariableTemplateSpecialization && !IsPartialSpecialization;
7659+
7660+ // C++ [temp.expl.spec]p2:
7661+ // The declaration in an explicit-specialization shall not be an
7662+ // export-declaration. An explicit specialization shall not use a
7663+ // storage-class-specifier other than thread_local.
7664+ //
7665+ // We use the storage-class-specifier from DeclSpec because we may have
7666+ // added implicit 'extern' for declarations with __declspec(dllimport)!
7667+ if (SCSpec != DeclSpec::SCS_unspecified &&
7668+ (IsExplicitSpecialization || IsMemberSpecialization)) {
76587669 Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7659- diag::ext_explicit_specialization_storage_class)
7670+ diag::ext_explicit_specialization_storage_class)
76607671 << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
76617672 }
76627673
@@ -7679,8 +7690,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76797690 }
76807691 }
76817692 if (FunctionOrMethod) {
7682- // C++ [class.static.data]p5: A local class shall not have static data
7683- // members.
7693+ // C++ [class.static.data]p5: A local class shall not have static
7694+ // data members.
76847695 Diag(D.getIdentifierLoc(),
76857696 diag::err_static_data_member_not_allowed_in_local_class)
76867697 << Name << RD->getDeclName()
@@ -7698,8 +7709,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
76987709 // the program is ill-formed. C++11 drops this restriction.
76997710 Diag(D.getIdentifierLoc(),
77007711 getLangOpts().CPlusPlus11
7701- ? diag::warn_cxx98_compat_static_data_member_in_union
7702- : diag::ext_static_data_member_in_union) << Name;
7712+ ? diag::warn_cxx98_compat_static_data_member_in_union
7713+ : diag::ext_static_data_member_in_union)
7714+ << Name;
77037715 }
77047716 }
77057717 } else if (IsVariableTemplate || IsPartialSpecialization) {
@@ -7717,7 +7729,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77177729 case SC_Static:
77187730 Diag(D.getDeclSpec().getStorageClassSpecLoc(),
77197731 diag::err_static_out_of_line)
7720- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7732+ << FixItHint::CreateRemoval(
7733+ D.getDeclSpec().getStorageClassSpecLoc());
77217734 break;
77227735 case SC_Auto:
77237736 case SC_Register:
@@ -7729,7 +7742,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77297742
77307743 Diag(D.getDeclSpec().getStorageClassSpecLoc(),
77317744 diag::err_storage_class_for_static_member)
7732- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7745+ << FixItHint::CreateRemoval(
7746+ D.getDeclSpec().getStorageClassSpecLoc());
77337747 break;
77347748 case SC_PrivateExtern:
77357749 llvm_unreachable("C storage class in c++!");
@@ -7781,8 +7795,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
77817795 // the variable (matching the scope specifier), store them.
77827796 // An explicit variable template specialization does not own any template
77837797 // parameter lists.
7784- bool IsExplicitSpecialization =
7785- IsVariableTemplateSpecialization && !IsPartialSpecialization;
77867798 unsigned VDTemplateParamLists =
77877799 (TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
77887800 if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10213,12 +10225,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1021310225 }
1021410226
1021510227 if (!isFriend && SC != SC_None) {
10228+ // C++ [temp.expl.spec]p2:
10229+ // The declaration in an explicit-specialization shall not be an
10230+ // export-declaration. An explicit specialization shall not use a
10231+ // storage-class-specifier other than thread_local.
10232+ //
10233+ // We diagnose friend declarations with storage-class-specifiers
10234+ // elsewhere.
1021610235 if (isFunctionTemplateSpecialization || isMemberSpecialization) {
1021710236 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");
10237+ diag::ext_explicit_specialization_storage_class)
10238+ << FixItHint::CreateRemoval(
10239+ D.getDeclSpec().getStorageClassSpecLoc());
10240+ }
10241+
10242+ if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
10243+ assert(isa<CXXMethodDecl>(NewFD) &&
10244+ "Out-of-line member function should be a CXXMethodDecl");
1022210245 // C++ [class.static]p1:
1022310246 // A data or function member of a class may be declared static
1022410247 // in a class definition, in which case it is a static member of
@@ -10227,22 +10250,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1022710250 // Complain about the 'static' specifier if it's on an out-of-line
1022810251 // member function definition.
1022910252
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.
10253+ // MSVC permits the use of a 'static' storage specifier on an
10254+ // out-of-line member function template declaration and class member
10255+ // template declaration (MSVC versions before 2015), warn about this.
1023310256 Diag(D.getDeclSpec().getStorageClassSpecLoc(),
1023410257 ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
1023510258 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());
10259+ (getLangOpts().MSVCCompat &&
10260+ NewFD->getDescribedFunctionTemplate()))
10261+ ? diag::ext_static_out_of_line
10262+ : diag::err_static_out_of_line)
10263+ << FixItHint::CreateRemoval(
10264+ D.getDeclSpec().getStorageClassSpecLoc());
1023910265 }
1024010266 }
10241- #if 0
10242- if (SC != SC_None && !isFriend && ) {
10243- } else if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) {
10244- }
10245- #endif
1024610267
1024710268 // C++11 [except.spec]p15:
1024810269 // A deallocation function with no exception-specification is treated
@@ -10609,29 +10630,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1060910630 Previous))
1061010631 NewFD->setInvalidDecl();
1061110632 }
10612-
10613- #if 0
10614- // C++ [dcl.stc]p1:
10615- // A storage-class-specifier shall not be specified in an explicit
10616- // specialization (14.7.3)
10617- // FIXME: We should be checking this for dependent specializations.
10618- FunctionTemplateSpecializationInfo *Info =
10619- NewFD->getTemplateSpecializationInfo();
10620- if (Info && SC != SC_None) {
10621- if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
10622- Diag(NewFD->getLocation(),
10623- diag::err_explicit_specialization_inconsistent_storage_class)
10624- << SC
10625- << FixItHint::CreateRemoval(
10626- D.getDeclSpec().getStorageClassSpecLoc());
10627-
10628- else
10629- Diag(NewFD->getLocation(),
10630- diag::ext_explicit_specialization_storage_class)
10631- << FixItHint::CreateRemoval(
10632- D.getDeclSpec().getStorageClassSpecLoc());
10633- }
10634- #endif
1063510633 } else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
1063610634 if (CheckMemberSpecialization(NewFD, Previous))
1063710635 NewFD->setInvalidDecl();
0 commit comments