[clang] [Clang] Implement the core language parts of P2786 - Trivial relocation (PR #127636)

via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 21 06:34:44 PST 2025


================
@@ -0,0 +1,272 @@
+// RUN: %clang_cc1 -std=c++2c -verify %s
+
+class Trivial {};
+struct NonRelocatable {
+    ~NonRelocatable();
+};
+static NonRelocatable NonRelocatable_g;
+
+class A trivially_relocatable_if_eligible {};
+class B trivially_relocatable_if_eligible : Trivial{};
+class C trivially_relocatable_if_eligible {
+    int a;
+    void* b;
+    int c[3];
+    Trivial d[3];
+    NonRelocatable& e = NonRelocatable_g;
+};
+class D trivially_relocatable_if_eligible : Trivial {};
+class E trivially_relocatable_if_eligible : virtual Trivial {};
+
+class F trivially_relocatable_if_eligible : NonRelocatable {};
+
+class I trivially_relocatable_if_eligible {
+    NonRelocatable a;
+    NonRelocatable b[1];
+    const NonRelocatable c;
+    const NonRelocatable d[1];
+};
+
+class J trivially_relocatable_if_eligible:  virtual Trivial, NonRelocatable {
+    NonRelocatable a;
+};
+
+class G trivially_relocatable_if_eligible {
+    G(G&&);
+};
+
+class H trivially_relocatable_if_eligible {
+    ~H();
+};
+
+struct Incomplete; // expected-note {{forward declaration of 'Incomplete'}}
+static_assert(__builtin_is_cpp_trivially_relocatable(Incomplete));  // expected-error {{incomplete type 'Incomplete' used in type trait expression}}
+static_assert(__builtin_is_cpp_trivially_relocatable(Trivial));
+static_assert(__builtin_is_cpp_trivially_relocatable(G));
+static_assert(__builtin_is_cpp_trivially_relocatable(H));
+static_assert(__builtin_is_cpp_trivially_relocatable(int));
+static_assert(__builtin_is_cpp_trivially_relocatable(void*));
+static_assert(!__builtin_is_cpp_trivially_relocatable(int&));
+static_assert(!__builtin_is_cpp_trivially_relocatable(Trivial&));
+static_assert(__builtin_is_cpp_trivially_relocatable(const Trivial));
+static_assert(__builtin_is_cpp_trivially_relocatable(Trivial[1]));
+
+struct UserDtr {
+    ~UserDtr();
+};
+
+struct DefaultedDtr {
+    ~DefaultedDtr() = default;
+};
+struct UserMoveWithDefaultCopy {
+    UserMoveWithDefaultCopy(UserMoveWithDefaultCopy&&);
+    UserMoveWithDefaultCopy(const UserMoveWithDefaultCopy&) = default;
+};
+
+struct UserMove{
+    UserMove(UserMove&&);
+};
+
+struct UserMoveDefault{
+    UserMoveDefault(UserMoveDefault&&) = default;
+};
+
+struct UserCopy{
+    UserCopy(const UserCopy&);
+};
+
+struct UserCopyDefault{
+    UserCopyDefault(const UserCopyDefault&) = default;
+};
+
+
+struct UserDeletedMove{
+    UserDeletedMove(UserDeletedMove&) = delete;
+    UserDeletedMove(const UserDeletedMove&) = default;
+};
+
+static_assert(!__builtin_is_cpp_trivially_relocatable(UserDtr));
+static_assert(__builtin_is_cpp_trivially_relocatable(DefaultedDtr));
+static_assert(!__builtin_is_cpp_trivially_relocatable(UserMoveWithDefaultCopy));
+static_assert(!__builtin_is_cpp_trivially_relocatable(UserMove));
+static_assert(!__builtin_is_cpp_trivially_relocatable(UserCopy));
+static_assert(__builtin_is_cpp_trivially_relocatable(UserMoveDefault));
+static_assert(__builtin_is_cpp_trivially_relocatable(UserCopyDefault));
+static_assert(__builtin_is_cpp_trivially_relocatable(UserDeletedMove));
+
+template <typename T>
+class TestDependentErrors trivially_relocatable_if_eligible : T {};
+TestDependentErrors<Trivial> Ok;
+TestDependentErrors<NonRelocatable> Err;
+
+struct DeletedMove {
+    DeletedMove(DeletedMove&&) = delete;
+};
+struct DeletedCopy {
+    DeletedCopy(const DeletedCopy&) = delete;
+};
+struct DeletedMoveAssign {
+    DeletedMoveAssign& operator=(DeletedMoveAssign&&) = delete;
+};
+
+static_assert(!__builtin_is_cpp_trivially_relocatable(DeletedMove));
+static_assert(!__builtin_is_cpp_trivially_relocatable(DeletedCopy));
+static_assert(!__builtin_is_cpp_trivially_relocatable(DeletedMoveAssign));
+
+union U {
+    G g;
+};
+static_assert(!__is_trivially_copyable(U));
+static_assert(__builtin_is_cpp_trivially_relocatable(U));
+
+
+namespace replaceable {
+
+struct DeletedMove {
+    DeletedMove(DeletedMove&&) = delete;
+};
+struct DeletedCopy {
+    DeletedCopy(const DeletedCopy&) = delete;
+};
+struct DeletedMoveAssign {
+    DeletedMoveAssign& operator=(DeletedMoveAssign&&) = delete;
+};
+
+struct DefaultedMove {
+    DefaultedMove(DefaultedMove&&) = default;
+    DefaultedMove& operator=(DefaultedMove&&) = default;
+};
+struct DefaultedCopy {
+    DefaultedCopy(const DefaultedCopy&) = default;
+    DefaultedCopy(DefaultedCopy&&) = default;
+    DefaultedCopy& operator=(DefaultedCopy&&) = default;
+};
+struct DefaultedMoveAssign {
+    DefaultedMoveAssign(DefaultedMoveAssign&&) = default;
+    DefaultedMoveAssign& operator=(DefaultedMoveAssign&&) = default;
+};
+
+struct UserProvidedMove {
+    UserProvidedMove(UserProvidedMove&&){};
+};
+struct UserProvidedCopy {
+    UserProvidedCopy(const UserProvidedCopy&) {};
+};
+struct UserProvidedMoveAssign {
+    UserProvidedMoveAssign& operator=(const UserProvidedMoveAssign&){return *this;};
+};
+
+struct Empty{};
+static_assert(__builtin_is_replaceable(Empty));
+struct S1 replaceable_if_eligible{};
+static_assert(__builtin_is_replaceable(S1));
+
+static_assert(__builtin_is_replaceable(DefaultedMove));
+static_assert(__builtin_is_replaceable(DefaultedCopy));
+static_assert(__builtin_is_replaceable(DefaultedMoveAssign));
+
+static_assert(!__builtin_is_replaceable(DeletedMove));
+static_assert(!__builtin_is_replaceable(DeletedCopy));
+static_assert(!__builtin_is_replaceable(DeletedMoveAssign));
+
+static_assert(!__builtin_is_replaceable(UserProvidedMove));
+static_assert(!__builtin_is_replaceable(UserProvidedCopy));
+static_assert(!__builtin_is_replaceable(UserProvidedMoveAssign));
+
+using NotReplaceable = DeletedMove;
+
+template <typename T>
+struct S {
+    T t;
+};
+
+template <typename T>
+struct WithBase : T{};
+
+template <typename T>
+struct WithVBase : virtual T{};
+
+struct WithVirtual {
+    virtual ~WithVirtual() = default;
+    WithVirtual(WithVirtual&&) = default;
+    WithVirtual& operator=(WithVirtual&&) = default;
+};
+
+static_assert(__builtin_is_replaceable(S<int>));
+static_assert(__builtin_is_replaceable(S<volatile int>));
+static_assert(!__builtin_is_replaceable(S<const int>));
+static_assert(!__builtin_is_replaceable(S<const int&>));
+static_assert(!__builtin_is_replaceable(S<int&>));
+static_assert(__builtin_is_replaceable(S<int[2]>));
+static_assert(!__builtin_is_replaceable(S<const int[2]>));
+static_assert(__builtin_is_replaceable(WithBase<S<int>>));
+static_assert(!__builtin_is_replaceable(WithBase<S<const int>>));
+static_assert(!__builtin_is_replaceable(WithBase<UserProvidedMove>));
+static_assert(!__builtin_is_replaceable(WithVBase<S<int>>));
+static_assert(!__builtin_is_replaceable(WithVBase<S<const int>>));
+static_assert(!__builtin_is_replaceable(WithVBase<UserProvidedMove>));
+static_assert(__builtin_is_replaceable(WithVirtual));
+
+
+struct U1 replaceable_if_eligible {
+    ~U1() = delete;
+    U1(U1&&) = default;
+    U1& operator=(U1&&) = default;
+
+};
+static_assert(__builtin_is_replaceable(U1));
+
+struct U2 replaceable_if_eligible {
+    U2(const U2&) = delete;
+};
+static_assert(!__builtin_is_replaceable(U2));
+
+
+template <typename T>
+struct WithVBaseExplicit replaceable_if_eligible : virtual T{};
+static_assert(__builtin_is_replaceable(WithVBaseExplicit<S<int>>)); // expected-error {{failed}}
----------------
Sirraide wrote:

```suggestion
static_assert(!__builtin_is_replaceable(WithVBaseExplicit<S<int>>));
```
Any reason we’re not just doing this here?

https://github.com/llvm/llvm-project/pull/127636


More information about the cfe-commits mailing list