@@ -5289,6 +5289,100 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
5289
5289
return false;
5290
5290
}
5291
5291
5292
+ static CXXDestructorDecl *LookupDestructorIfRelevant(Sema &S,
5293
+ CXXRecordDecl *Class) {
5294
+ if (Class->isInvalidDecl())
5295
+ return nullptr;
5296
+ if (Class->hasIrrelevantDestructor())
5297
+ return nullptr;
5298
+
5299
+ // Dtor might still be missing, e.g because it's invalid.
5300
+ return S.LookupDestructor(Class);
5301
+ }
5302
+
5303
+ static void MarkFieldDestructorReferenced(Sema &S, SourceLocation Location,
5304
+ FieldDecl *Field) {
5305
+ if (Field->isInvalidDecl())
5306
+ return;
5307
+
5308
+ // Don't destroy incomplete or zero-length arrays.
5309
+ if (isIncompleteOrZeroLengthArrayType(S.Context, Field->getType()))
5310
+ return;
5311
+
5312
+ QualType FieldType = S.Context.getBaseElementType(Field->getType());
5313
+
5314
+ auto *FieldClassDecl = FieldType->getAsCXXRecordDecl();
5315
+ if (!FieldClassDecl)
5316
+ return;
5317
+
5318
+ // The destructor for an implicit anonymous union member is never invoked.
5319
+ if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
5320
+ return;
5321
+
5322
+ auto *Dtor = LookupDestructorIfRelevant(S, FieldClassDecl);
5323
+ if (!Dtor)
5324
+ return;
5325
+
5326
+ S.CheckDestructorAccess(Field->getLocation(), Dtor,
5327
+ S.PDiag(diag::err_access_dtor_field)
5328
+ << Field->getDeclName() << FieldType);
5329
+
5330
+ S.MarkFunctionReferenced(Location, Dtor);
5331
+ S.DiagnoseUseOfDecl(Dtor, Location);
5332
+ }
5333
+
5334
+ static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location,
5335
+ CXXRecordDecl *ClassDecl) {
5336
+ if (ClassDecl->isDependentContext())
5337
+ return;
5338
+
5339
+ // We only potentially invoke the destructors of potentially constructed
5340
+ // subobjects.
5341
+ bool VisitVirtualBases = !ClassDecl->isAbstract();
5342
+
5343
+ // If the destructor exists and has already been marked used in the MS ABI,
5344
+ // then virtual base destructors have already been checked and marked used.
5345
+ // Skip checking them again to avoid duplicate diagnostics.
5346
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
5347
+ CXXDestructorDecl *Dtor = ClassDecl->getDestructor();
5348
+ if (Dtor && Dtor->isUsed())
5349
+ VisitVirtualBases = false;
5350
+ }
5351
+
5352
+ llvm::SmallPtrSet<const CXXRecordDecl *, 8> DirectVirtualBases;
5353
+
5354
+ // Bases.
5355
+ for (const auto &Base : ClassDecl->bases()) {
5356
+ auto *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();
5357
+ if (!BaseClassDecl)
5358
+ continue;
5359
+
5360
+ // Remember direct virtual bases.
5361
+ if (Base.isVirtual()) {
5362
+ if (!VisitVirtualBases)
5363
+ continue;
5364
+ DirectVirtualBases.insert(BaseClassDecl);
5365
+ }
5366
+
5367
+ auto *Dtor = LookupDestructorIfRelevant(S, BaseClassDecl);
5368
+ if (!Dtor)
5369
+ continue;
5370
+
5371
+ // FIXME: caret should be on the start of the class name
5372
+ S.CheckDestructorAccess(Base.getBeginLoc(), Dtor,
5373
+ S.PDiag(diag::err_access_dtor_base)
5374
+ << Base.getType() << Base.getSourceRange(),
5375
+ S.Context.getTypeDeclType(ClassDecl));
5376
+
5377
+ S.MarkFunctionReferenced(Location, Dtor);
5378
+ S.DiagnoseUseOfDecl(Dtor, Location);
5379
+ }
5380
+
5381
+ if (VisitVirtualBases)
5382
+ S.MarkVirtualBaseDestructorsReferenced(Location, ClassDecl,
5383
+ &DirectVirtualBases);
5384
+ }
5385
+
5292
5386
bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
5293
5387
ArrayRef<CXXCtorInitializer *> Initializers) {
5294
5388
if (Constructor->isDependentContext()) {
@@ -5456,10 +5550,24 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
5456
5550
NumInitializers * sizeof(CXXCtorInitializer*));
5457
5551
Constructor->setCtorInitializers(baseOrMemberInitializers);
5458
5552
5553
+ SourceLocation Location = Constructor->getLocation();
5554
+
5459
5555
// Constructors implicitly reference the base and member
5460
5556
// destructors.
5461
- MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
5462
- Constructor->getParent());
5557
+
5558
+ for (CXXCtorInitializer *Initializer : Info.AllToInit) {
5559
+ FieldDecl *Field = Initializer->getAnyMember();
5560
+ if (!Field)
5561
+ continue;
5562
+
5563
+ // C++ [class.base.init]p12:
5564
+ // In a non-delegating constructor, the destructor for each
5565
+ // potentially constructed subobject of class type is potentially
5566
+ // invoked.
5567
+ MarkFieldDestructorReferenced(*this, Location, Field);
5568
+ }
5569
+
5570
+ MarkBaseDestructorsReferenced(*this, Location, Constructor->getParent());
5463
5571
}
5464
5572
5465
5573
return HadError;
@@ -5764,9 +5872,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
5764
5872
DiagnoseUninitializedFields(*this, Constructor);
5765
5873
}
5766
5874
5767
- void
5768
- Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
5769
- CXXRecordDecl *ClassDecl) {
5875
+ void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
5876
+ CXXRecordDecl *ClassDecl) {
5770
5877
// Ignore dependent contexts. Also ignore unions, since their members never
5771
5878
// have destructors implicitly called.
5772
5879
if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
@@ -5779,119 +5886,29 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
5779
5886
5780
5887
// Non-static data members.
5781
5888
for (auto *Field : ClassDecl->fields()) {
5782
- if (Field->isInvalidDecl())
5783
- continue;
5784
-
5785
- // Don't destroy incomplete or zero-length arrays.
5786
- if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
5787
- continue;
5788
-
5789
- QualType FieldType = Context.getBaseElementType(Field->getType());
5790
-
5791
- const RecordType* RT = FieldType->getAs<RecordType>();
5792
- if (!RT)
5793
- continue;
5794
-
5795
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5796
- if (FieldClassDecl->isInvalidDecl())
5797
- continue;
5798
- if (FieldClassDecl->hasIrrelevantDestructor())
5799
- continue;
5800
- // The destructor for an implicit anonymous union member is never invoked.
5801
- if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
5802
- continue;
5803
-
5804
- CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
5805
- // Dtor might still be missing, e.g because it's invalid.
5806
- if (!Dtor)
5807
- continue;
5808
- CheckDestructorAccess(Field->getLocation(), Dtor,
5809
- PDiag(diag::err_access_dtor_field)
5810
- << Field->getDeclName()
5811
- << FieldType);
5812
-
5813
- MarkFunctionReferenced(Location, Dtor);
5814
- DiagnoseUseOfDecl(Dtor, Location);
5815
- }
5816
-
5817
- // We only potentially invoke the destructors of potentially constructed
5818
- // subobjects.
5819
- bool VisitVirtualBases = !ClassDecl->isAbstract();
5820
-
5821
- // If the destructor exists and has already been marked used in the MS ABI,
5822
- // then virtual base destructors have already been checked and marked used.
5823
- // Skip checking them again to avoid duplicate diagnostics.
5824
- if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
5825
- CXXDestructorDecl *Dtor = ClassDecl->getDestructor();
5826
- if (Dtor && Dtor->isUsed())
5827
- VisitVirtualBases = false;
5889
+ MarkFieldDestructorReferenced(*this, Location, Field);
5828
5890
}
5829
5891
5830
- llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
5831
-
5832
- // Bases.
5833
- for (const auto &Base : ClassDecl->bases()) {
5834
- const RecordType *RT = Base.getType()->getAs<RecordType>();
5835
- if (!RT)
5836
- continue;
5837
-
5838
- // Remember direct virtual bases.
5839
- if (Base.isVirtual()) {
5840
- if (!VisitVirtualBases)
5841
- continue;
5842
- DirectVirtualBases.insert(RT);
5843
- }
5844
-
5845
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5846
- // If our base class is invalid, we probably can't get its dtor anyway.
5847
- if (BaseClassDecl->isInvalidDecl())
5848
- continue;
5849
- if (BaseClassDecl->hasIrrelevantDestructor())
5850
- continue;
5851
-
5852
- CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
5853
- // Dtor might still be missing, e.g because it's invalid.
5854
- if (!Dtor)
5855
- continue;
5856
-
5857
- // FIXME: caret should be on the start of the class name
5858
- CheckDestructorAccess(Base.getBeginLoc(), Dtor,
5859
- PDiag(diag::err_access_dtor_base)
5860
- << Base.getType() << Base.getSourceRange(),
5861
- Context.getTypeDeclType(ClassDecl));
5862
-
5863
- MarkFunctionReferenced(Location, Dtor);
5864
- DiagnoseUseOfDecl(Dtor, Location);
5865
- }
5866
-
5867
- if (VisitVirtualBases)
5868
- MarkVirtualBaseDestructorsReferenced(Location, ClassDecl,
5869
- &DirectVirtualBases);
5892
+ MarkBaseDestructorsReferenced(*this, Location, ClassDecl);
5870
5893
}
5871
5894
5872
5895
void Sema::MarkVirtualBaseDestructorsReferenced(
5873
5896
SourceLocation Location, CXXRecordDecl *ClassDecl,
5874
- llvm::SmallPtrSetImpl<const RecordType *> *DirectVirtualBases) {
5897
+ llvm::SmallPtrSetImpl<const CXXRecordDecl *> *DirectVirtualBases) {
5875
5898
// Virtual bases.
5876
5899
for (const auto &VBase : ClassDecl->vbases()) {
5877
- // Bases are always records in a well-formed non-dependent class.
5878
- const RecordType *RT = VBase.getType()->castAs<RecordType>();
5879
-
5880
- // Ignore already visited direct virtual bases.
5881
- if (DirectVirtualBases && DirectVirtualBases->count(RT))
5900
+ auto *BaseClassDecl = VBase.getType()->getAsCXXRecordDecl();
5901
+ if (!BaseClassDecl)
5882
5902
continue;
5883
5903
5884
- CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5885
- // If our base class is invalid, we probably can't get its dtor anyway.
5886
- if (BaseClassDecl->isInvalidDecl())
5887
- continue;
5888
- if (BaseClassDecl->hasIrrelevantDestructor())
5904
+ // Ignore already visited direct virtual bases.
5905
+ if (DirectVirtualBases && DirectVirtualBases->count(BaseClassDecl))
5889
5906
continue;
5890
5907
5891
- CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
5892
- // Dtor might still be missing, e.g because it's invalid.
5908
+ auto *Dtor = LookupDestructorIfRelevant(*this, BaseClassDecl);
5893
5909
if (!Dtor)
5894
5910
continue;
5911
+
5895
5912
if (CheckDestructorAccess(
5896
5913
ClassDecl->getLocation(), Dtor,
5897
5914
PDiag(diag::err_access_dtor_vbase)
0 commit comments