================ @@ -7258,6 +7261,221 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { } } +static bool hasSuitableConstructorForReplaceability(CXXRecordDecl *D, + bool Implicit) { + assert(D->hasDefinition() && !D->isInvalidDecl()); + + bool HasDeletedMoveConstructor = false; + bool HasDeletedCopyConstructor = false; + bool HasMoveConstructor = D->needsImplicitMoveConstructor(); + bool HasDefaultedMoveConstructor = D->needsImplicitMoveConstructor(); + bool HasDefaultedCopyConstructor = D->needsImplicitMoveConstructor(); + + for (const Decl *D : D->decls()) { + auto *MD = dyn_cast<CXXConstructorDecl>(D); + if (!MD || MD->isIneligibleOrNotSelected()) + continue; + + if (MD->isMoveConstructor()) { + HasMoveConstructor = true; + if (MD->isDefaulted()) + HasDefaultedMoveConstructor = true; + if (MD->isDeleted()) + HasDeletedMoveConstructor = true; + } + if (MD->isCopyConstructor()) { + if (MD->isDefaulted()) + HasDefaultedCopyConstructor = true; + if (MD->isDeleted()) + HasDeletedCopyConstructor = true; + } + } + + if (HasMoveConstructor) + return !HasDeletedMoveConstructor && + (Implicit ? HasDefaultedMoveConstructor : true); + return !HasDeletedCopyConstructor && + (Implicit ? HasDefaultedCopyConstructor : true); + ; +} + +static bool hasSuitableMoveAssignmentOperatorForReplaceability(CXXRecordDecl *D, + bool Implicit) { + assert(D->hasDefinition() && !D->isInvalidDecl()); + + if (D->hasExplicitlyDeletedMoveAssignment()) + return false; + + bool HasDeletedMoveAssignment = false; + bool HasDeletedCopyAssignment = false; + bool HasMoveAssignment = D->needsImplicitMoveAssignment(); + bool HasDefaultedMoveAssignment = D->needsImplicitMoveAssignment(); + bool HasDefaultedCopyAssignment = D->needsImplicitCopyAssignment(); + + for (const Decl *D : D->decls()) { + auto *MD = dyn_cast<CXXMethodDecl>(D); + if (!MD || MD->isIneligibleOrNotSelected()) + continue; + + if (MD->isMoveAssignmentOperator()) { + HasMoveAssignment = true; + if (MD->isDefaulted()) + HasDefaultedMoveAssignment = true; + if (MD->isDeleted()) + HasDeletedMoveAssignment = true; + } + if (MD->isCopyAssignmentOperator()) { + if (MD->isDefaulted()) + HasDefaultedCopyAssignment = true; + if (MD->isDeleted()) + HasDeletedCopyAssignment = true; + } + } + + if (HasMoveAssignment) + return !HasDeletedMoveAssignment && + (Implicit ? HasDefaultedMoveAssignment : true); + return !HasDeletedCopyAssignment && + (Implicit ? HasDefaultedCopyAssignment : true); +} + +void Sema::CheckCXX2CTriviallyRelocatable(CXXRecordDecl *D) { ---------------- Sirraide wrote:
When it comes to this function, I’m having to think pretty hard to try and pair the code here w/ the wording on the standard; imo it would help if you could add some comments that briefly show which sections in this function correspond to what condition(s) in the standard. Also, I think factoring most of this out into either a lambda or a separate function so we can early-return whenever `IsTriviallyRelocatable` is set to `false` here would aid readability as well. https://github.com/llvm/llvm-project/pull/127636 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits