Skip to content

Commit 75263de

Browse files
committed
Add comments
1 parent c88d7a2 commit 75263de

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7339,12 +7339,21 @@ hasSuitableMoveAssignmentOperatorForRelocation(CXXRecordDecl *D,
73397339
(AllowUserDefined ? true : HasDefaultedCopyAssignment);
73407340
}
73417341

7342+
// [C++26][class.prop]
7343+
// A class C is default-movable if
7344+
// - overload resolution for direct-initializing an object of type C
7345+
// from an xvalue of type C selects a constructor that is a direct member of C
7346+
// and is neither user-provided nor deleted,
7347+
// - overload resolution for assigning to an lvalue of type C from an xvalue of
7348+
// type C selects an assignment operator function that is a direct member of C
7349+
// and is neither user-provided nor deleted, and C has a destructor that is
7350+
// neither user-provided nor deleted.
73427351
static bool isDefaultMovable(CXXRecordDecl *D) {
7343-
if (!hasSuitableConstructorForRelocation(D, /*AllowUserDefined*/ false))
7352+
if (!hasSuitableConstructorForRelocation(D, /*AllowUserDefined=*/false))
73447353
return false;
73457354

73467355
if (!hasSuitableMoveAssignmentOperatorForRelocation(
7347-
D, /*AllowUserDefined*/ false))
7356+
D, /*AllowUserDefined=*/false))
73487357
return false;
73497358

73507359
const auto *Dtr = D->getDestructor();
@@ -7364,12 +7373,16 @@ static bool hasDeletedDestructor(CXXRecordDecl *D) {
73647373
return false;
73657374
}
73667375

7376+
// [C++26][class.prop]
7377+
// A class is eligible for trivial relocation unless it...
73677378
static bool isEligibleForTrivialRelocation(Sema &SemaRef, CXXRecordDecl *D) {
73687379

73697380
for (const CXXBaseSpecifier &B : D->bases()) {
73707381
const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
73717382
if (!BaseDecl)
73727383
continue;
7384+
// ... has any virtual base classes
7385+
// ... has a base class that is not a trivially relocatable class
73737386
if (B.isVirtual() ||
73747387
(!BaseDecl->isDependentType() && !BaseDecl->isTriviallyRelocatable()))
73757388
return false;
@@ -7380,6 +7393,8 @@ static bool isEligibleForTrivialRelocation(Sema &SemaRef, CXXRecordDecl *D) {
73807393
continue;
73817394
if (Field->getType()->isReferenceType())
73827395
continue;
7396+
// ... has a non-static data member of an object type that is not
7397+
// of a trivially relocatable type
73837398
QualType T = SemaRef.getASTContext().getBaseElementType(
73847399
Field->getType().getUnqualifiedType());
73857400
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
@@ -7388,9 +7403,12 @@ static bool isEligibleForTrivialRelocation(Sema &SemaRef, CXXRecordDecl *D) {
73887403
}
73897404
}
73907405

7406+
// ...has a deleted destructor
73917407
return !hasDeletedDestructor(D);
73927408
}
73937409

7410+
// [C++26][class.prop]
7411+
// A class C is a trivially relocatable class if
73947412
void Sema::CheckCXX2CTriviallyRelocatable(CXXRecordDecl *D) {
73957413
if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
73967414
return;
@@ -7401,30 +7419,38 @@ void Sema::CheckCXX2CTriviallyRelocatable(CXXRecordDecl *D) {
74017419
D->getTriviallyRelocatableSpecifier().isSet();
74027420

74037421
bool IsTriviallyRelocatable = [&] {
7422+
// if it is eligible for trivial relocation
7423+
74047424
if (!isEligibleForTrivialRelocation(*this, D))
74057425
return false;
74067426

7427+
// has the trivially_relocatable_if_eligible class-property-specifier,
74077428
if (D->isDependentType() || MarkedTriviallyRelocatable)
74087429
return true;
74097430

7431+
// is a union with no user-declared special member functions, or
74107432
if (D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
74117433
!D->hasUserDeclaredCopyAssignment() &&
74127434
!D->hasUserDeclaredMoveOperation() && !D->hasUserDeclaredDestructor()) {
74137435
return true;
74147436
}
74157437

7438+
// is default-movable.
74167439
return isDefaultMovable(D);
74177440
}();
74187441

74197442
D->setIsTriviallyRelocatable(IsTriviallyRelocatable);
74207443
}
74217444

7445+
// [C++26][class.prop]
7446+
// A class C is eligible for replacement unless
74227447
static bool isEligibleForReplacement(Sema &SemaRef, CXXRecordDecl *D) {
74237448

74247449
for (const CXXBaseSpecifier &B : D->bases()) {
74257450
const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
74267451
if (!BaseDecl)
74277452
continue;
7453+
// it has a base class that is not a replaceable class
74287454
if ((!BaseDecl->isDependentType() && !BaseDecl->isReplaceable()))
74297455
return false;
74307456
}
@@ -7433,23 +7459,16 @@ static bool isEligibleForReplacement(Sema &SemaRef, CXXRecordDecl *D) {
74337459
if (Field->getType()->isDependentType())
74347460
continue;
74357461

7436-
if (Field->getType()->isReferenceType())
7462+
// it has a non-static data member that is not of a replaceable type,
7463+
if (Field->getType().isReplaceableType(SemaRef.getASTContext()))
74377464
return false;
7438-
7439-
if (Field->getType().isConstQualified())
7440-
return false;
7441-
7442-
QualType T = SemaRef.getASTContext().getBaseElementType(
7443-
Field->getType().getUnqualifiedType());
7444-
if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) {
7445-
if (!RD->isReplaceable())
7446-
return false;
7447-
}
74487465
}
74497466

7467+
// it has a deleted destructor.
74507468
return !hasDeletedDestructor(D);
74517469
}
74527470

7471+
// [C++26][class.prop] A class C is a replaceable class if...
74537472
void Sema::CheckCXX2CReplaceable(CXXRecordDecl *D) {
74547473
if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
74557474
return;
@@ -7458,25 +7477,31 @@ void Sema::CheckCXX2CReplaceable(CXXRecordDecl *D) {
74587477

74597478
bool MarkedCXX2CReplaceable = D->getReplaceableSpecifier().isSet();
74607479

7480+
// This is part of "eligible for replacement", however we defer it
7481+
// to avoid extraneous computations.
74617482
auto HasSuitableSMP = [&] {
74627483
return hasSuitableConstructorForRelocation(D, /*AllowUserDefined=*/true) &&
74637484
hasSuitableMoveAssignmentOperatorForRelocation(
74647485
D, /*AllowUserDefined=*/true);
74657486
};
74667487

74677488
bool IsReplaceable = [&] {
7489+
// A class C is a replaceable class if it is eligible for replacement
74687490
if (!isEligibleForReplacement(*this, D))
74697491
return false;
74707492

7493+
// has the replaceable_if_eligible class-property-specifier
74717494
if (D->isDependentType() || MarkedCXX2CReplaceable)
74727495
return HasSuitableSMP();
74737496

7497+
// is a union with no user-declared special member functions, or
74747498
if (D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
74757499
!D->hasUserDeclaredCopyAssignment() &&
74767500
!D->hasUserDeclaredMoveOperation() && !D->hasUserDeclaredDestructor()) {
74777501
return HasSuitableSMP();
74787502
}
74797503

7504+
// is default-movable.
74807505
return isDefaultMovable(D);
74817506
}();
74827507

0 commit comments

Comments
 (0)