@@ -7654,9 +7654,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7654
7654
"should have a 'template<>' for this decl");
7655
7655
}
7656
7656
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)) {
7658
7669
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7659
- diag::ext_explicit_specialization_storage_class)
7670
+ diag::ext_explicit_specialization_storage_class)
7660
7671
<< FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7661
7672
}
7662
7673
@@ -7679,8 +7690,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7679
7690
}
7680
7691
}
7681
7692
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.
7684
7695
Diag(D.getIdentifierLoc(),
7685
7696
diag::err_static_data_member_not_allowed_in_local_class)
7686
7697
<< Name << RD->getDeclName()
@@ -7698,8 +7709,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7698
7709
// the program is ill-formed. C++11 drops this restriction.
7699
7710
Diag(D.getIdentifierLoc(),
7700
7711
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;
7703
7715
}
7704
7716
}
7705
7717
} else if (IsVariableTemplate || IsPartialSpecialization) {
@@ -7717,7 +7729,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7717
7729
case SC_Static:
7718
7730
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7719
7731
diag::err_static_out_of_line)
7720
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7732
+ << FixItHint::CreateRemoval(
7733
+ D.getDeclSpec().getStorageClassSpecLoc());
7721
7734
break;
7722
7735
case SC_Auto:
7723
7736
case SC_Register:
@@ -7729,7 +7742,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7729
7742
7730
7743
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7731
7744
diag::err_storage_class_for_static_member)
7732
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7745
+ << FixItHint::CreateRemoval(
7746
+ D.getDeclSpec().getStorageClassSpecLoc());
7733
7747
break;
7734
7748
case SC_PrivateExtern:
7735
7749
llvm_unreachable("C storage class in c++!");
@@ -7781,8 +7795,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7781
7795
// the variable (matching the scope specifier), store them.
7782
7796
// An explicit variable template specialization does not own any template
7783
7797
// parameter lists.
7784
- bool IsExplicitSpecialization =
7785
- IsVariableTemplateSpecialization && !IsPartialSpecialization;
7786
7798
unsigned VDTemplateParamLists =
7787
7799
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
7788
7800
if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10213,12 +10225,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10213
10225
}
10214
10226
10215
10227
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.
10216
10235
if (isFunctionTemplateSpecialization || isMemberSpecialization) {
10217
10236
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");
10222
10245
// C++ [class.static]p1:
10223
10246
// A data or function member of a class may be declared static
10224
10247
// 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,
10227
10250
// Complain about the 'static' specifier if it's on an out-of-line
10228
10251
// member function definition.
10229
10252
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.
10233
10256
Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10234
10257
((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10235
10258
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());
10239
10265
}
10240
10266
}
10241
- #if 0
10242
- if (SC != SC_None && !isFriend && ) {
10243
- } else if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) && !CurContext->isRecord()) {
10244
- }
10245
- #endif
10246
10267
10247
10268
// C++11 [except.spec]p15:
10248
10269
// A deallocation function with no exception-specification is treated
@@ -10609,29 +10630,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10609
10630
Previous))
10610
10631
NewFD->setInvalidDecl();
10611
10632
}
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
10635
10633
} else if (isMemberSpecialization && isa<CXXMethodDecl>(NewFD)) {
10636
10634
if (CheckMemberSpecialization(NewFD, Previous))
10637
10635
NewFD->setInvalidDecl();
0 commit comments