@@ -3293,6 +3293,9 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
3293
3293
continue ;
3294
3294
if (FieldClassDecl->hasIrrelevantDestructor ())
3295
3295
continue ;
3296
+ // The destructor for an implicit anonymous union member is never invoked.
3297
+ if (FieldClassDecl->isUnion () && FieldClassDecl->isAnonymousStructOrUnion ())
3298
+ continue ;
3296
3299
3297
3300
CXXDestructorDecl *Dtor = LookupDestructor (FieldClassDecl);
3298
3301
assert (Dtor && " No dtor found for FieldClassDecl!" );
@@ -4372,31 +4375,33 @@ struct SpecialMemberDeletionInfo {
4372
4375
TQ & Qualifiers::Volatile);
4373
4376
}
4374
4377
4378
+ bool shouldDeleteForClassSubobject (CXXRecordDecl *Class, FieldDecl *Field);
4379
+
4375
4380
bool shouldDeleteForBase (CXXRecordDecl *BaseDecl, bool IsVirtualBase);
4376
4381
bool shouldDeleteForField (FieldDecl *FD);
4377
4382
bool shouldDeleteForAllConstMembers ();
4378
4383
};
4379
4384
}
4380
4385
4381
- // / Check whether we should delete a special member function due to the class
4382
- // / having a particular direct or virtual base class.
4383
- bool SpecialMemberDeletionInfo::shouldDeleteForBase (CXXRecordDecl *BaseDecl,
4384
- bool IsVirtualBase) {
4385
- // C++11 [class.copy]p23:
4386
- // -- for the move assignment operator, any direct or indirect virtual
4387
- // base class.
4388
- if (CSM == Sema::CXXMoveAssignment && IsVirtualBase)
4389
- return true ;
4390
-
4386
+ // / Check whether we should delete a special member function due to having a
4387
+ // / direct or virtual base class or static data member of class type M.
4388
+ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject (
4389
+ CXXRecordDecl *Class, FieldDecl *Field) {
4391
4390
// C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5:
4392
4391
// -- any direct or virtual base class [...] has a type with a destructor
4393
4392
// that is deleted or inaccessible
4394
4393
if (!IsAssignment) {
4395
- CXXDestructorDecl *BaseDtor = S.LookupDestructor (BaseDecl );
4396
- if (BaseDtor ->isDeleted ())
4394
+ CXXDestructorDecl *Dtor = S.LookupDestructor (Class );
4395
+ if (Dtor ->isDeleted ())
4397
4396
return true ;
4398
- if (S.CheckDestructorAccess (Loc, BaseDtor, S.PDiag ())
4399
- != Sema::AR_accessible)
4397
+ if (S.CheckDestructorAccess (Loc, Dtor, S.PDiag ()) != Sema::AR_accessible)
4398
+ return true ;
4399
+
4400
+ // C++11 [class.dtor]p5:
4401
+ // -- X is a union-like class that has a variant member with a non-trivial
4402
+ // destructor
4403
+ if (CSM == Sema::CXXDestructor && Field && Field->getParent ()->isUnion () &&
4404
+ !Dtor->isTrivial ())
4400
4405
return true ;
4401
4406
}
4402
4407
@@ -4410,50 +4415,58 @@ bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXRecordDecl *BaseDecl,
4410
4415
// overload resolution, as applied to B's corresponding special member,
4411
4416
// results in an ambiguity or a function that is deleted or inaccessible
4412
4417
// from the defaulted special member
4418
+ // FIXME: in-class initializers should be handled here
4413
4419
if (CSM != Sema::CXXDestructor) {
4414
- Sema::SpecialMemberOverloadResult *SMOR = lookupIn (BaseDecl );
4420
+ Sema::SpecialMemberOverloadResult *SMOR = lookupIn (Class );
4415
4421
if (!SMOR->hasSuccess ())
4416
4422
return true ;
4417
4423
4418
- CXXMethodDecl *BaseMember = SMOR->getMethod ();
4424
+ CXXMethodDecl *Member = SMOR->getMethod ();
4425
+ // A member of a union must have a trivial corresponding special member.
4426
+ if (Field && Field->getParent ()->isUnion () && !Member->isTrivial ())
4427
+ return true ;
4428
+
4419
4429
if (IsConstructor) {
4420
- CXXConstructorDecl *BaseCtor = cast<CXXConstructorDecl>(BaseMember );
4421
- if (S.CheckConstructorAccess (Loc, BaseCtor, BaseCtor ->getAccess (),
4422
- S. PDiag ()) != Sema::AR_accessible)
4430
+ CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(Member );
4431
+ if (S.CheckConstructorAccess (Loc, Ctor, Ctor ->getAccess (), S. PDiag ())
4432
+ != Sema::AR_accessible)
4423
4433
return true ;
4424
4434
4425
4435
// -- for the move constructor, a [...] direct or virtual base class with
4426
4436
// a type that does not have a move constructor and is not trivially
4427
4437
// copyable.
4428
- if (IsMove && !BaseCtor->isMoveConstructor () &&
4429
- !BaseDecl->isTriviallyCopyable ())
4438
+ if (IsMove && !Ctor->isMoveConstructor () && !Class->isTriviallyCopyable ())
4430
4439
return true ;
4431
4440
} else {
4432
4441
assert (IsAssignment && " unexpected kind of special member" );
4433
- if (S.CheckDirectMemberAccess (Loc, BaseMember , S.PDiag ())
4442
+ if (S.CheckDirectMemberAccess (Loc, Member , S.PDiag ())
4434
4443
!= Sema::AR_accessible)
4435
4444
return true ;
4436
4445
4437
4446
// -- for the move assignment operator, a direct base class with a type
4438
4447
// that does not have a move assignment operator and is not trivially
4439
4448
// copyable.
4440
- if (IsMove && !BaseMember ->isMoveAssignmentOperator () &&
4441
- !BaseDecl ->isTriviallyCopyable ())
4449
+ if (IsMove && !Member ->isMoveAssignmentOperator () &&
4450
+ !Class ->isTriviallyCopyable ())
4442
4451
return true ;
4443
4452
}
4444
4453
}
4445
4454
4446
- // C++11 [class.dtor]p5:
4447
- // -- for a virtual destructor, lookup of the non-array deallocation function
4448
- // results in an ambiguity or in a function that is deleted or inaccessible
4449
- if (CSM == Sema::CXXDestructor && MD->isVirtual ()) {
4450
- FunctionDecl *OperatorDelete = 0 ;
4451
- DeclarationName Name =
4452
- S.Context .DeclarationNames .getCXXOperatorName (OO_Delete);
4453
- if (S.FindDeallocationFunction (Loc, MD->getParent (), Name,
4454
- OperatorDelete, false ))
4455
- return true ;
4456
- }
4455
+ return false ;
4456
+ }
4457
+
4458
+ // / Check whether we should delete a special member function due to the class
4459
+ // / having a particular direct or virtual base class.
4460
+ bool SpecialMemberDeletionInfo::shouldDeleteForBase (CXXRecordDecl *BaseDecl,
4461
+ bool IsVirtualBase) {
4462
+ // C++11 [class.copy]p23:
4463
+ // -- for the move assignment operator, any direct or indirect virtual
4464
+ // base class.
4465
+ if (CSM == Sema::CXXMoveAssignment && IsVirtualBase)
4466
+ return true ;
4467
+
4468
+ if (shouldDeleteForClassSubobject (BaseDecl, 0 ))
4469
+ return true ;
4457
4470
4458
4471
return false ;
4459
4472
}
@@ -4500,58 +4513,14 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
4500
4513
UE = FieldRecord->field_end ();
4501
4514
UI != UE; ++UI) {
4502
4515
QualType UnionFieldType = S.Context .getBaseElementType (UI->getType ());
4503
- CXXRecordDecl *UnionFieldRecord =
4504
- UnionFieldType->getAsCXXRecordDecl ();
4505
4516
4506
4517
if (!UnionFieldType.isConstQualified ())
4507
4518
AllVariantFieldsAreConst = false ;
4508
4519
4509
- if (UnionFieldRecord) {
4510
- // FIXME: Checking for accessibility and validity of this
4511
- // destructor is technically going beyond the
4512
- // standard, but this is believed to be a defect.
4513
- if (!IsAssignment) {
4514
- CXXDestructorDecl *FieldDtor = S.LookupDestructor (UnionFieldRecord);
4515
- if (FieldDtor->isDeleted ())
4516
- return true ;
4517
- if (S.CheckDestructorAccess (Loc, FieldDtor, S.PDiag ()) !=
4518
- Sema::AR_accessible)
4519
- return true ;
4520
- if (!FieldDtor->isTrivial ())
4521
- return true ;
4522
- }
4523
-
4524
- // FIXME: in-class initializers should be handled here
4525
- if (CSM != Sema::CXXDestructor) {
4526
- Sema::SpecialMemberOverloadResult *SMOR =
4527
- lookupIn (UnionFieldRecord);
4528
- // FIXME: Checking for accessibility and validity of this
4529
- // corresponding member is technically going beyond the
4530
- // standard, but this is believed to be a defect.
4531
- if (!SMOR->hasSuccess ())
4532
- return true ;
4533
-
4534
- CXXMethodDecl *FieldMember = SMOR->getMethod ();
4535
- // A member of a union must have a trivial corresponding
4536
- // special member.
4537
- if (!FieldMember->isTrivial ())
4538
- return true ;
4539
-
4540
- if (IsConstructor) {
4541
- CXXConstructorDecl *FieldCtor =
4542
- cast<CXXConstructorDecl>(FieldMember);
4543
- if (S.CheckConstructorAccess (Loc, FieldCtor,
4544
- FieldCtor->getAccess (),
4545
- S.PDiag ()) != Sema::AR_accessible)
4546
- return true ;
4547
- } else {
4548
- assert (IsAssignment && " unexpected kind of special member" );
4549
- if (S.CheckDirectMemberAccess (Loc, FieldMember, S.PDiag ())
4550
- != Sema::AR_accessible)
4551
- return true ;
4552
- }
4553
- }
4554
- }
4520
+ CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl ();
4521
+ if (UnionFieldRecord &&
4522
+ shouldDeleteForClassSubobject (UnionFieldRecord, *UI))
4523
+ return true ;
4555
4524
}
4556
4525
4557
4526
// At least one member in each anonymous union must be non-const
@@ -4564,9 +4533,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
4564
4533
return false ;
4565
4534
}
4566
4535
4567
- // Unless we're doing assignment , the field's destructor must be
4568
- // accessible and not deleted.
4569
- if (!IsAssignment ) {
4536
+ // When checking a constructor , the field's destructor must be accessible
4537
+ // and not deleted.
4538
+ if (IsConstructor ) {
4570
4539
CXXDestructorDecl *FieldDtor = S.LookupDestructor (FieldRecord);
4571
4540
if (FieldDtor->isDeleted ())
4572
4541
return true ;
@@ -4578,13 +4547,18 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
4578
4547
// Check that the corresponding member of the field is accessible,
4579
4548
// unique, and non-deleted. We don't do this if it has an explicit
4580
4549
// initialization when default-constructing.
4581
- if (CSM != Sema::CXXDestructor &&
4582
- !(CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer ())) {
4550
+ if (!(CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer ())) {
4583
4551
Sema::SpecialMemberOverloadResult *SMOR = lookupIn (FieldRecord);
4584
4552
if (!SMOR->hasSuccess ())
4585
4553
return true ;
4586
4554
4587
4555
CXXMethodDecl *FieldMember = SMOR->getMethod ();
4556
+
4557
+ // We need the corresponding member of a union to be trivial so that
4558
+ // we can safely process all members simultaneously.
4559
+ if (inUnion () && !FieldMember->isTrivial ())
4560
+ return true ;
4561
+
4588
4562
if (IsConstructor) {
4589
4563
CXXConstructorDecl *FieldCtor = cast<CXXConstructorDecl>(FieldMember);
4590
4564
if (S.CheckConstructorAccess (Loc, FieldCtor, FieldCtor->getAccess (),
@@ -4597,6 +4571,13 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
4597
4571
if (IsMove && !FieldCtor->isMoveConstructor () &&
4598
4572
!FieldRecord->isTriviallyCopyable ())
4599
4573
return true ;
4574
+ } else if (CSM == Sema::CXXDestructor) {
4575
+ CXXDestructorDecl *FieldDtor = S.LookupDestructor (FieldRecord);
4576
+ if (FieldDtor->isDeleted ())
4577
+ return true ;
4578
+ if (S.CheckDestructorAccess (Loc, FieldDtor, S.PDiag ()) !=
4579
+ Sema::AR_accessible)
4580
+ return true ;
4600
4581
} else {
4601
4582
assert (IsAssignment && " unexpected kind of special member" );
4602
4583
if (S.CheckDirectMemberAccess (Loc, FieldMember, S.PDiag ())
@@ -4610,14 +4591,6 @@ bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
4610
4591
!FieldRecord->isTriviallyCopyable ())
4611
4592
return true ;
4612
4593
}
4613
-
4614
- // We need the corresponding member of a union to be trivial so that
4615
- // we can safely copy them all simultaneously.
4616
- // FIXME: Note that performing the check here (where we rely on the lack
4617
- // of an in-class initializer) is technically ill-formed. However, this
4618
- // seems most obviously to be a bug in the standard.
4619
- if (inUnion () && !FieldMember->isTrivial ())
4620
- return true ;
4621
4594
}
4622
4595
} else if (CSM == Sema::CXXDefaultConstructor && !inUnion () &&
4623
4596
FieldType.isConstQualified () && !FD->hasInClassInitializer ()) {
@@ -4652,6 +4625,8 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) {
4652
4625
if (!LangOpts.CPlusPlus0x || RD->isInvalidDecl ())
4653
4626
return false ;
4654
4627
4628
+ // FIXME: Provide the ability to diagnose why a special member was deleted.
4629
+
4655
4630
// C++11 [expr.lambda.prim]p19:
4656
4631
// The closure type associated with a lambda-expression has a
4657
4632
// deleted (8.4.3) default constructor and a deleted copy
@@ -4660,6 +4635,18 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) {
4660
4635
(CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment))
4661
4636
return true ;
4662
4637
4638
+ // C++11 [class.dtor]p5:
4639
+ // -- for a virtual destructor, lookup of the non-array deallocation function
4640
+ // results in an ambiguity or in a function that is deleted or inaccessible
4641
+ if (CSM == Sema::CXXDestructor && MD->isVirtual ()) {
4642
+ FunctionDecl *OperatorDelete = 0 ;
4643
+ DeclarationName Name =
4644
+ Context.DeclarationNames .getCXXOperatorName (OO_Delete);
4645
+ if (FindDeallocationFunction (MD->getLocation (), MD->getParent (), Name,
4646
+ OperatorDelete, false ))
4647
+ return true ;
4648
+ }
4649
+
4663
4650
// For an anonymous struct or union, the copy and assignment special members
4664
4651
// will never be used, so skip the check. For an anonymous union declared at
4665
4652
// namespace scope, the constructor and destructor are used.
@@ -4672,8 +4659,6 @@ bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM) {
4672
4659
4673
4660
SpecialMemberDeletionInfo SMI (*this , MD, CSM);
4674
4661
4675
- // FIXME: We should put some diagnostic logic right into this function.
4676
-
4677
4662
for (CXXRecordDecl::base_class_iterator BI = RD->bases_begin (),
4678
4663
BE = RD->bases_end (); BI != BE; ++BI)
4679
4664
if (!BI->isVirtual () &&
@@ -7216,11 +7201,11 @@ CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
7216
7201
// This could be uniqued if it ever proves significant.
7217
7202
Destructor->setTypeSourceInfo (Context.getTrivialTypeSourceInfo (Ty));
7218
7203
7204
+ AddOverriddenMethods (ClassDecl, Destructor);
7205
+
7219
7206
if (ShouldDeleteSpecialMember (Destructor, CXXDestructor))
7220
7207
Destructor->setDeletedAsWritten ();
7221
-
7222
- AddOverriddenMethods (ClassDecl, Destructor);
7223
-
7208
+
7224
7209
return Destructor;
7225
7210
}
7226
7211
0 commit comments