@@ -7494,89 +7494,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7494
7494
NTCUC_AutoVar, NTCUK_Destruct);
7495
7495
} else {
7496
7496
bool Invalid = false;
7497
-
7498
- if (DC->isRecord() && !CurContext->isRecord()) {
7499
- // This is an out-of-line definition of a static data member.
7500
- switch (SC) {
7501
- case SC_None:
7502
- break;
7503
- case SC_Static:
7504
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7505
- diag::err_static_out_of_line)
7506
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7507
- break;
7508
- case SC_Auto:
7509
- case SC_Register:
7510
- case SC_Extern:
7511
- // [dcl.stc] p2: The auto or register specifiers shall be applied only
7512
- // to names of variables declared in a block or to function parameters.
7513
- // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7514
- // of class members
7515
-
7516
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7517
- diag::err_storage_class_for_static_member)
7518
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7519
- break;
7520
- case SC_PrivateExtern:
7521
- llvm_unreachable("C storage class in c++!");
7522
- }
7523
- }
7524
-
7525
- if (SC == SC_Static && CurContext->isRecord()) {
7526
- if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7527
- // Walk up the enclosing DeclContexts to check for any that are
7528
- // incompatible with static data members.
7529
- const DeclContext *FunctionOrMethod = nullptr;
7530
- const CXXRecordDecl *AnonStruct = nullptr;
7531
- for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7532
- if (Ctxt->isFunctionOrMethod()) {
7533
- FunctionOrMethod = Ctxt;
7534
- break;
7535
- }
7536
- const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7537
- if (ParentDecl && !ParentDecl->getDeclName()) {
7538
- AnonStruct = ParentDecl;
7539
- break;
7540
- }
7541
- }
7542
- if (FunctionOrMethod) {
7543
- // C++ [class.static.data]p5: A local class shall not have static data
7544
- // members.
7545
- Diag(D.getIdentifierLoc(),
7546
- diag::err_static_data_member_not_allowed_in_local_class)
7547
- << Name << RD->getDeclName()
7548
- << llvm::to_underlying(RD->getTagKind());
7549
- } else if (AnonStruct) {
7550
- // C++ [class.static.data]p4: Unnamed classes and classes contained
7551
- // directly or indirectly within unnamed classes shall not contain
7552
- // static data members.
7553
- Diag(D.getIdentifierLoc(),
7554
- diag::err_static_data_member_not_allowed_in_anon_struct)
7555
- << Name << llvm::to_underlying(AnonStruct->getTagKind());
7556
- Invalid = true;
7557
- } else if (RD->isUnion()) {
7558
- // C++98 [class.union]p1: If a union contains a static data member,
7559
- // the program is ill-formed. C++11 drops this restriction.
7560
- Diag(D.getIdentifierLoc(),
7561
- getLangOpts().CPlusPlus11
7562
- ? diag::warn_cxx98_compat_static_data_member_in_union
7563
- : diag::ext_static_data_member_in_union) << Name;
7564
- }
7565
- }
7566
- }
7567
-
7568
7497
// Match up the template parameter lists with the scope specifier, then
7569
7498
// determine whether we have a template or a template specialization.
7570
- bool InvalidScope = false;
7571
7499
TemplateParams = MatchTemplateParametersToScopeSpecifier(
7572
7500
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
7573
7501
D.getCXXScopeSpec(),
7574
7502
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
7575
7503
? D.getName().TemplateId
7576
7504
: nullptr,
7577
7505
TemplateParamLists,
7578
- /*never a friend*/ false, IsMemberSpecialization, InvalidScope);
7579
- Invalid |= InvalidScope;
7506
+ /*never a friend*/ false, IsMemberSpecialization, Invalid);
7580
7507
7581
7508
if (TemplateParams) {
7582
7509
if (DC->isDependentContext()) {
@@ -7625,6 +7552,102 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7625
7552
"should have a 'template<>' for this decl");
7626
7553
}
7627
7554
7555
+ bool IsExplicitSpecialization =
7556
+ IsVariableTemplateSpecialization && !IsPartialSpecialization;
7557
+
7558
+ // C++ [temp.expl.spec]p2:
7559
+ // The declaration in an explicit-specialization shall not be an
7560
+ // export-declaration. An explicit specialization shall not use a
7561
+ // storage-class-specifier other than thread_local.
7562
+ //
7563
+ // We use the storage-class-specifier from DeclSpec because we may have
7564
+ // added implicit 'extern' for declarations with __declspec(dllimport)!
7565
+ if (SCSpec != DeclSpec::SCS_unspecified &&
7566
+ (IsExplicitSpecialization || IsMemberSpecialization)) {
7567
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7568
+ diag::ext_explicit_specialization_storage_class)
7569
+ << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
7570
+ }
7571
+
7572
+ if (CurContext->isRecord()) {
7573
+ if (SC == SC_Static) {
7574
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
7575
+ // Walk up the enclosing DeclContexts to check for any that are
7576
+ // incompatible with static data members.
7577
+ const DeclContext *FunctionOrMethod = nullptr;
7578
+ const CXXRecordDecl *AnonStruct = nullptr;
7579
+ for (DeclContext *Ctxt = DC; Ctxt; Ctxt = Ctxt->getParent()) {
7580
+ if (Ctxt->isFunctionOrMethod()) {
7581
+ FunctionOrMethod = Ctxt;
7582
+ break;
7583
+ }
7584
+ const CXXRecordDecl *ParentDecl = dyn_cast<CXXRecordDecl>(Ctxt);
7585
+ if (ParentDecl && !ParentDecl->getDeclName()) {
7586
+ AnonStruct = ParentDecl;
7587
+ break;
7588
+ }
7589
+ }
7590
+ if (FunctionOrMethod) {
7591
+ // C++ [class.static.data]p5: A local class shall not have static
7592
+ // data members.
7593
+ Diag(D.getIdentifierLoc(),
7594
+ diag::err_static_data_member_not_allowed_in_local_class)
7595
+ << Name << RD->getDeclName()
7596
+ << llvm::to_underlying(RD->getTagKind());
7597
+ } else if (AnonStruct) {
7598
+ // C++ [class.static.data]p4: Unnamed classes and classes contained
7599
+ // directly or indirectly within unnamed classes shall not contain
7600
+ // static data members.
7601
+ Diag(D.getIdentifierLoc(),
7602
+ diag::err_static_data_member_not_allowed_in_anon_struct)
7603
+ << Name << llvm::to_underlying(AnonStruct->getTagKind());
7604
+ Invalid = true;
7605
+ } else if (RD->isUnion()) {
7606
+ // C++98 [class.union]p1: If a union contains a static data member,
7607
+ // the program is ill-formed. C++11 drops this restriction.
7608
+ Diag(D.getIdentifierLoc(),
7609
+ getLangOpts().CPlusPlus11
7610
+ ? diag::warn_cxx98_compat_static_data_member_in_union
7611
+ : diag::ext_static_data_member_in_union)
7612
+ << Name;
7613
+ }
7614
+ }
7615
+ } else if (IsVariableTemplate || IsPartialSpecialization) {
7616
+ // There is no such thing as a member field template.
7617
+ Diag(D.getIdentifierLoc(), diag::err_template_member)
7618
+ << II << TemplateParams->getSourceRange();
7619
+ // Recover by pretending this is a static data member template.
7620
+ SC = SC_Static;
7621
+ }
7622
+ } else if (DC->isRecord()) {
7623
+ // This is an out-of-line definition of a static data member.
7624
+ switch (SC) {
7625
+ case SC_None:
7626
+ break;
7627
+ case SC_Static:
7628
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7629
+ diag::err_static_out_of_line)
7630
+ << FixItHint::CreateRemoval(
7631
+ D.getDeclSpec().getStorageClassSpecLoc());
7632
+ break;
7633
+ case SC_Auto:
7634
+ case SC_Register:
7635
+ case SC_Extern:
7636
+ // [dcl.stc] p2: The auto or register specifiers shall be applied only
7637
+ // to names of variables declared in a block or to function parameters.
7638
+ // [dcl.stc] p6: The extern specifier cannot be used in the declaration
7639
+ // of class members
7640
+
7641
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
7642
+ diag::err_storage_class_for_static_member)
7643
+ << FixItHint::CreateRemoval(
7644
+ D.getDeclSpec().getStorageClassSpecLoc());
7645
+ break;
7646
+ case SC_PrivateExtern:
7647
+ llvm_unreachable("C storage class in c++!");
7648
+ }
7649
+ }
7650
+
7628
7651
if (IsVariableTemplateSpecialization) {
7629
7652
SourceLocation TemplateKWLoc =
7630
7653
TemplateParamLists.size() > 0
@@ -7670,8 +7693,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
7670
7693
// the variable (matching the scope specifier), store them.
7671
7694
// An explicit variable template specialization does not own any template
7672
7695
// parameter lists.
7673
- bool IsExplicitSpecialization =
7674
- IsVariableTemplateSpecialization && !IsPartialSpecialization;
7675
7696
unsigned VDTemplateParamLists =
7676
7697
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
7677
7698
if (TemplateParamLists.size() > VDTemplateParamLists)
@@ -10073,25 +10094,45 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10073
10094
NewFD->setImplicitlyInline(ImplicitInlineCXX20);
10074
10095
}
10075
10096
10076
- if (SC == SC_Static && isa<CXXMethodDecl>(NewFD) &&
10077
- !CurContext->isRecord()) {
10078
- // C++ [class.static]p1:
10079
- // A data or function member of a class may be declared static
10080
- // in a class definition, in which case it is a static member of
10081
- // the class.
10097
+ if (!isFriend && SC != SC_None) {
10098
+ // C++ [temp.expl.spec]p2:
10099
+ // The declaration in an explicit-specialization shall not be an
10100
+ // export-declaration. An explicit specialization shall not use a
10101
+ // storage-class-specifier other than thread_local.
10102
+ //
10103
+ // We diagnose friend declarations with storage-class-specifiers
10104
+ // elsewhere.
10105
+ if (isFunctionTemplateSpecialization || isMemberSpecialization) {
10106
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10107
+ diag::ext_explicit_specialization_storage_class)
10108
+ << FixItHint::CreateRemoval(
10109
+ D.getDeclSpec().getStorageClassSpecLoc());
10110
+ }
10082
10111
10083
- // Complain about the 'static' specifier if it's on an out-of-line
10084
- // member function definition.
10112
+ if (SC == SC_Static && !CurContext->isRecord() && DC->isRecord()) {
10113
+ assert(isa<CXXMethodDecl>(NewFD) &&
10114
+ "Out-of-line member function should be a CXXMethodDecl");
10115
+ // C++ [class.static]p1:
10116
+ // A data or function member of a class may be declared static
10117
+ // in a class definition, in which case it is a static member of
10118
+ // the class.
10085
10119
10086
- // MSVC permits the use of a 'static' storage specifier on an out-of-line
10087
- // member function template declaration and class member template
10088
- // declaration (MSVC versions before 2015), warn about this.
10089
- Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10090
- ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10091
- cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10092
- (getLangOpts().MSVCCompat && NewFD->getDescribedFunctionTemplate()))
10093
- ? diag::ext_static_out_of_line : diag::err_static_out_of_line)
10094
- << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());
10120
+ // Complain about the 'static' specifier if it's on an out-of-line
10121
+ // member function definition.
10122
+
10123
+ // MSVC permits the use of a 'static' storage specifier on an
10124
+ // out-of-line member function template declaration and class member
10125
+ // template declaration (MSVC versions before 2015), warn about this.
10126
+ Diag(D.getDeclSpec().getStorageClassSpecLoc(),
10127
+ ((!getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
10128
+ cast<CXXRecordDecl>(DC)->getDescribedClassTemplate()) ||
10129
+ (getLangOpts().MSVCCompat &&
10130
+ NewFD->getDescribedFunctionTemplate()))
10131
+ ? diag::ext_static_out_of_line
10132
+ : diag::err_static_out_of_line)
10133
+ << FixItHint::CreateRemoval(
10134
+ D.getDeclSpec().getStorageClassSpecLoc());
10135
+ }
10095
10136
}
10096
10137
10097
10138
// C++11 [except.spec]p15:
@@ -10459,27 +10500,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
10459
10500
Previous))
10460
10501
NewFD->setInvalidDecl();
10461
10502
}
10462
-
10463
- // C++ [dcl.stc]p1:
10464
- // A storage-class-specifier shall not be specified in an explicit
10465
- // specialization (14.7.3)
10466
- // FIXME: We should be checking this for dependent specializations.
10467
- FunctionTemplateSpecializationInfo *Info =
10468
- NewFD->getTemplateSpecializationInfo();
10469
- if (Info && SC != SC_None) {
10470
- if (SC != Info->getTemplate()->getTemplatedDecl()->getStorageClass())
10471
- Diag(NewFD->getLocation(),
10472
- diag::err_explicit_specialization_inconsistent_storage_class)
10473
- << SC
10474
- << FixItHint::CreateRemoval(
10475
- D.getDeclSpec().getStorageClassSpecLoc());
10476
-
10477
- else
10478
- Diag(NewFD->getLocation(),
10479
- diag::ext_explicit_specialization_storage_class)
10480
- << FixItHint::CreateRemoval(
10481
- D.getDeclSpec().getStorageClassSpecLoc());
10482
- }
10483
10503
} else if (isMemberSpecialization && !FunctionTemplate) {
10484
10504
if (CheckMemberSpecialization(NewFD, Previous))
10485
10505
NewFD->setInvalidDecl();
0 commit comments