================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits