@@ -5283,6 +5283,102 @@ Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
5283
5283
return false;
5284
5284
}
5285
5285
5286
+ static void MarkFieldDestructorReferenced(Sema &S, SourceLocation Location,
5287
+ FieldDecl *Field) {
5288
+ if (Field->isInvalidDecl())
5289
+ return;
5290
+
5291
+ // Don't destroy incomplete or zero-length arrays.
5292
+ if (isIncompleteOrZeroLengthArrayType(S.Context, Field->getType()))
5293
+ return;
5294
+
5295
+ QualType FieldType = S.Context.getBaseElementType(Field->getType());
5296
+
5297
+ const RecordType *RT = FieldType->getAs<RecordType>();
5298
+ if (!RT)
5299
+ return;
5300
+
5301
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5302
+ if (FieldClassDecl->isInvalidDecl())
5303
+ return;
5304
+ if (FieldClassDecl->hasIrrelevantDestructor())
5305
+ return;
5306
+ // The destructor for an implicit anonymous union member is never invoked.
5307
+ if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
5308
+ return;
5309
+
5310
+ CXXDestructorDecl *Dtor = S.LookupDestructor(FieldClassDecl);
5311
+ // Dtor might still be missing, e.g because it's invalid.
5312
+ if (!Dtor)
5313
+ return;
5314
+ S.CheckDestructorAccess(Field->getLocation(), Dtor,
5315
+ S.PDiag(diag::err_access_dtor_field)
5316
+ << Field->getDeclName() << FieldType);
5317
+
5318
+ S.MarkFunctionReferenced(Location, Dtor);
5319
+ S.DiagnoseUseOfDecl(Dtor, Location);
5320
+ }
5321
+
5322
+ static void MarkBaseDestructorsReferenced(Sema &S, SourceLocation Location,
5323
+ CXXRecordDecl *ClassDecl) {
5324
+ if (ClassDecl->isDependentContext())
5325
+ return;
5326
+
5327
+ // We only potentially invoke the destructors of potentially constructed
5328
+ // subobjects.
5329
+ bool VisitVirtualBases = !ClassDecl->isAbstract();
5330
+
5331
+ // If the destructor exists and has already been marked used in the MS ABI,
5332
+ // then virtual base destructors have already been checked and marked used.
5333
+ // Skip checking them again to avoid duplicate diagnostics.
5334
+ if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) {
5335
+ CXXDestructorDecl *Dtor = ClassDecl->getDestructor();
5336
+ if (Dtor && Dtor->isUsed())
5337
+ VisitVirtualBases = false;
5338
+ }
5339
+
5340
+ llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
5341
+
5342
+ // Bases.
5343
+ for (const auto &Base : ClassDecl->bases()) {
5344
+ const RecordType *RT = Base.getType()->getAs<RecordType>();
5345
+ if (!RT)
5346
+ continue;
5347
+
5348
+ // Remember direct virtual bases.
5349
+ if (Base.isVirtual()) {
5350
+ if (!VisitVirtualBases)
5351
+ continue;
5352
+ DirectVirtualBases.insert(RT);
5353
+ }
5354
+
5355
+ CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5356
+ // If our base class is invalid, we probably can't get its dtor anyway.
5357
+ if (BaseClassDecl->isInvalidDecl())
5358
+ continue;
5359
+ if (BaseClassDecl->hasIrrelevantDestructor())
5360
+ continue;
5361
+
5362
+ CXXDestructorDecl *Dtor = S.LookupDestructor(BaseClassDecl);
5363
+ // Dtor might still be missing, e.g because it's invalid.
5364
+ if (!Dtor)
5365
+ continue;
5366
+
5367
+ // FIXME: caret should be on the start of the class name
5368
+ S.CheckDestructorAccess(Base.getBeginLoc(), Dtor,
5369
+ S.PDiag(diag::err_access_dtor_base)
5370
+ << Base.getType() << Base.getSourceRange(),
5371
+ S.Context.getTypeDeclType(ClassDecl));
5372
+
5373
+ S.MarkFunctionReferenced(Location, Dtor);
5374
+ S.DiagnoseUseOfDecl(Dtor, Location);
5375
+ }
5376
+
5377
+ if (VisitVirtualBases)
5378
+ S.MarkVirtualBaseDestructorsReferenced(Location, ClassDecl,
5379
+ &DirectVirtualBases);
5380
+ }
5381
+
5286
5382
bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
5287
5383
ArrayRef<CXXCtorInitializer *> Initializers) {
5288
5384
if (Constructor->isDependentContext()) {
@@ -5465,10 +5561,10 @@ bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
5465
5561
// potentially constructed subobject of class type is potentially
5466
5562
// invoked
5467
5563
// ([class.dtor]).
5468
- MarkFieldDestructorReferenced(Location, Field);
5564
+ MarkFieldDestructorReferenced(*this, Location, Field);
5469
5565
}
5470
5566
5471
- MarkBaseDestructorsReferenced(Location, Constructor->getParent());
5567
+ MarkBaseDestructorsReferenced(*this, Location, Constructor->getParent());
5472
5568
}
5473
5569
5474
5570
return HadError;
@@ -5773,102 +5869,6 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
5773
5869
DiagnoseUninitializedFields(*this, Constructor);
5774
5870
}
5775
5871
5776
- void Sema::MarkFieldDestructorReferenced(SourceLocation Location,
5777
- FieldDecl *Field) {
5778
- if (Field->isInvalidDecl())
5779
- return;
5780
-
5781
- // Don't destroy incomplete or zero-length arrays.
5782
- if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
5783
- return;
5784
-
5785
- QualType FieldType = Context.getBaseElementType(Field->getType());
5786
-
5787
- const RecordType *RT = FieldType->getAs<RecordType>();
5788
- if (!RT)
5789
- return;
5790
-
5791
- CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
5792
- if (FieldClassDecl->isInvalidDecl())
5793
- return;
5794
- if (FieldClassDecl->hasIrrelevantDestructor())
5795
- return;
5796
- // The destructor for an implicit anonymous union member is never invoked.
5797
- if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
5798
- return;
5799
-
5800
- CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
5801
- // Dtor might still be missing, e.g because it's invalid.
5802
- if (!Dtor)
5803
- return;
5804
- CheckDestructorAccess(Field->getLocation(), Dtor,
5805
- PDiag(diag::err_access_dtor_field)
5806
- << Field->getDeclName() << FieldType);
5807
-
5808
- MarkFunctionReferenced(Location, Dtor);
5809
- DiagnoseUseOfDecl(Dtor, Location);
5810
- }
5811
-
5812
- void Sema::MarkBaseDestructorsReferenced(SourceLocation Location,
5813
- CXXRecordDecl *ClassDecl) {
5814
- if (ClassDecl->isDependentContext())
5815
- return;
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;
5828
- }
5829
-
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);
5870
- }
5871
-
5872
5872
void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
5873
5873
CXXRecordDecl *ClassDecl) {
5874
5874
// Ignore dependent contexts. Also ignore unions, since their members never
@@ -5883,10 +5883,10 @@ void Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
5883
5883
5884
5884
// Non-static data members.
5885
5885
for (auto *Field : ClassDecl->fields()) {
5886
- MarkFieldDestructorReferenced(Location, Field);
5886
+ MarkFieldDestructorReferenced(*this, Location, Field);
5887
5887
}
5888
5888
5889
- MarkBaseDestructorsReferenced(Location, ClassDecl);
5889
+ MarkBaseDestructorsReferenced(*this, Location, ClassDecl);
5890
5890
}
5891
5891
5892
5892
void Sema::MarkVirtualBaseDestructorsReferenced(
0 commit comments