[clang] [Clang] Implement the core language parts of P2786 - Trivial relocation (PR #127636)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 24 05:41:58 PST 2025
================
@@ -7258,6 +7261,228 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
}
}
+static bool hasSuitableConstructorForRelocation(CXXRecordDecl *D,
+ bool AllowUserDefined) {
+ assert(D->hasDefinition() && !D->isInvalidDecl());
+
+ bool HasDeletedMoveConstructor = false;
+ bool HasDeletedCopyConstructor = false;
+ bool HasMoveConstructor = D->needsImplicitMoveConstructor();
+ bool HasCopyConstructor = D->needsImplicitCopyConstructor();
+ bool HasDefaultedMoveConstructor = D->needsImplicitMoveConstructor();
+ bool HasDefaultedCopyConstructor = D->needsImplicitCopyConstructor();
+
+ 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;
+ } else if (MD->isCopyConstructor()) {
+ HasCopyConstructor = true;
+ if (MD->isDefaulted())
+ HasDefaultedCopyConstructor = true;
+ if (MD->isDeleted())
+ HasDeletedCopyConstructor = true;
+ }
+ }
+
+ if (HasMoveConstructor)
+ return !HasDeletedMoveConstructor &&
+ (AllowUserDefined ? true : HasDefaultedMoveConstructor);
+ return HasCopyConstructor && !HasDeletedCopyConstructor &&
+ (AllowUserDefined ? true : HasDefaultedCopyConstructor);
+}
+
+static bool
+hasSuitableMoveAssignmentOperatorForRelocation(CXXRecordDecl *D,
+ bool AllowUserDefined) {
+ 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;
+ } else if (MD->isCopyAssignmentOperator()) {
+ if (MD->isDefaulted())
+ HasDefaultedCopyAssignment = true;
+ if (MD->isDeleted())
+ HasDeletedCopyAssignment = true;
+ }
+ }
+
+ if (HasMoveAssignment)
+ return !HasDeletedMoveAssignment &&
+ (AllowUserDefined ? true : HasDefaultedMoveAssignment);
+ return !HasDeletedCopyAssignment &&
+ (AllowUserDefined ? true : HasDefaultedCopyAssignment);
+}
+
+static bool isDefaultMovable(CXXRecordDecl *D) {
+ if (!hasSuitableConstructorForRelocation(D, /*AllowUserDefined*/ false))
+ return false;
+
+ if (!hasSuitableMoveAssignmentOperatorForRelocation(
+ D, /*AllowUserDefined*/ false))
+ return false;
+
+ const auto *Dtr = D->getDestructor();
+ if (!Dtr)
+ return true;
+
+ if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))
+ return false;
+
+ return !Dtr->isDeleted();
+}
+
+static bool hasDeletedDestructor(CXXRecordDecl *D) {
----------------
Fznamznon wrote:
Does it make sense to make `hasDeletedDestructor` a method of `CXXRecordDecl`? Maybe it will end up bein useful around codebase.
https://github.com/llvm/llvm-project/pull/127636
More information about the cfe-commits
mailing list