// RUN: %clang_cc1 -std=c++2c -verify %s // RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-intrinsics -fptrauth-calls -std=c++2c -verify %s class Trivial {}; static_assert(__builtin_is_cpp_trivially_relocatable(Trivial)); struct NonRelocatable { ~NonRelocatable(); }; static NonRelocatable NonRelocatable_g; class A trivially_relocatable_if_eligible {}; static_assert(__builtin_is_cpp_trivially_relocatable(A)); class B trivially_relocatable_if_eligible : Trivial{}; static_assert(__builtin_is_cpp_trivially_relocatable(B)); class C trivially_relocatable_if_eligible { int a; void* b; int c[3]; Trivial d[3]; NonRelocatable& e = NonRelocatable_g; }; static_assert(__builtin_is_cpp_trivially_relocatable(C)); class D trivially_relocatable_if_eligible : Trivial {}; static_assert(__builtin_is_cpp_trivially_relocatable(D)); class E trivially_relocatable_if_eligible : virtual Trivial {}; static_assert(!__builtin_is_cpp_trivially_relocatable(E)); class F trivially_relocatable_if_eligible : NonRelocatable {}; static_assert(!__builtin_is_cpp_trivially_relocatable(F)); class G trivially_relocatable_if_eligible { G(G&&); }; static_assert(__builtin_is_cpp_trivially_relocatable(G)); class H trivially_relocatable_if_eligible { ~H(); }; static_assert(__builtin_is_cpp_trivially_relocatable(H)); class I trivially_relocatable_if_eligible { NonRelocatable a; NonRelocatable b[1]; const NonRelocatable c; const NonRelocatable d[1]; }; static_assert(!__builtin_is_cpp_trivially_relocatable(I)); class J trivially_relocatable_if_eligible: virtual Trivial, NonRelocatable { NonRelocatable a; }; static_assert(!__builtin_is_cpp_trivially_relocatable(J)); 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(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])); static_assert(__builtin_is_cpp_trivially_relocatable(Trivial[])); struct WithConst { const int i; }; static_assert(!__builtin_is_cpp_trivially_relocatable(WithConst)); struct WithConstExplicit trivially_relocatable_if_eligible { const int i; }; static_assert(__builtin_is_cpp_trivially_relocatable(WithConstExplicit)); 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 UserMoveAssignDefault { UserMoveAssignDefault(UserMoveAssignDefault&&) = default; UserMoveAssignDefault& operator=(UserMoveAssignDefault&&) = 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(UserMoveAssignDefault)); static_assert(__builtin_is_cpp_trivially_relocatable(UserCopyDefault)); static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeletedMove)); template class TestDependentErrors trivially_relocatable_if_eligible : T {}; TestDependentErrors Ok; TestDependentErrors Err; struct DeletedMove { DeletedMove(DeletedMove&&) = delete; }; struct DeletedCopy { DeletedCopy(const DeletedCopy&) = delete; }; struct DeletedMoveAssign { DeletedMoveAssign& operator=(DeletedMoveAssign&&) = delete; }; struct DeletedDtr { ~DeletedDtr() = 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)); static_assert(!__builtin_is_cpp_trivially_relocatable(DeletedDtr)); union U { G g; }; static_assert(!__is_trivially_copyable(U)); static_assert(__builtin_is_cpp_trivially_relocatable(U)); template struct S { T t; }; static_assert(__builtin_is_cpp_trivially_relocatable(S)); static_assert(__builtin_is_cpp_trivially_relocatable(S)); static_assert(!__builtin_is_cpp_trivially_relocatable(S)); static_assert(!__builtin_is_cpp_trivially_relocatable(S)); static_assert(!__builtin_is_cpp_trivially_relocatable(S)); static_assert(__builtin_is_cpp_trivially_relocatable(S)); static_assert(!__builtin_is_cpp_trivially_relocatable(S)); static_assert(__builtin_is_cpp_trivially_relocatable(S)); template struct SExplicit trivially_relocatable_if_eligible{ T t; }; static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); static_assert(__builtin_is_cpp_trivially_relocatable(SExplicit)); 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(DeletedDtr)); static_assert(!__builtin_is_replaceable(UserProvidedMove)); static_assert(!__builtin_is_replaceable(UserProvidedCopy)); static_assert(!__builtin_is_replaceable(UserProvidedMoveAssign)); struct DeletedCopyTpl { template DeletedCopyTpl(const U&) = delete; }; static_assert(__builtin_is_replaceable(DeletedCopyTpl)); using NotReplaceable = DeletedMove; template struct WithBase : T{}; template struct WithVBase : virtual T{}; struct WithVirtual { virtual ~WithVirtual() = default; WithVirtual(WithVirtual&&) = default; WithVirtual& operator=(WithVirtual&&) = default; }; static_assert(__builtin_is_replaceable(S)); static_assert(!__builtin_is_replaceable(S)); static_assert(!__builtin_is_replaceable(S)); static_assert(!__builtin_is_replaceable(S)); static_assert(!__builtin_is_replaceable(S)); static_assert(__builtin_is_replaceable(S)); static_assert(!__builtin_is_replaceable(S)); static_assert(__builtin_is_replaceable(WithBase>)); static_assert(!__builtin_is_replaceable(WithBase>)); static_assert(!__builtin_is_replaceable(WithBase)); static_assert(__builtin_is_replaceable(WithVBase>)); static_assert(!__builtin_is_replaceable(WithVBase>)); static_assert(!__builtin_is_replaceable(WithVBase)); static_assert(__builtin_is_replaceable(WithVirtual)); int n = 4; // expected-note 2{{declared here}} static_assert(!__builtin_is_cpp_trivially_relocatable(int[n])); // expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} // expected-note@-2 {{read of non-const variable 'n' is not allowed in a constant expression}} static_assert(!__builtin_is_replaceable(int[n])); // expected-warning@-1 {{variable length arrays in C++ are a Clang extension}} // expected-note@-2 {{read of non-const variable 'n' is not allowed in a constant expression}} 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 struct WithVBaseExplicit replaceable_if_eligible : virtual T{}; static_assert(__builtin_is_replaceable(WithVBaseExplicit>)); struct S42 trivially_relocatable_if_eligible replaceable_if_eligible { S42(S42&&); S42& operator=(S42&&) = default; }; struct S43 trivially_relocatable_if_eligible replaceable_if_eligible { S43(S43&&) = default; S43& operator=(S43&&); }; struct Copyable1Explicit replaceable_if_eligible { Copyable1Explicit(Copyable1Explicit const &) = default; }; struct Copyable1 { Copyable1(Copyable1 const &) = default; }; struct CopyAssign1Explicit replaceable_if_eligible { CopyAssign1Explicit & operator=(const CopyAssign1Explicit&) = default; }; struct CopyAssign1 { CopyAssign1 & operator=(CopyAssign1 const &) = default; }; struct UserDeleted1 { UserDeleted1(const UserDeleted1&) = delete; }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted1)); static_assert(!__builtin_is_replaceable(UserDeleted1)); struct UserDeleted2 { UserDeleted2(UserDeleted2&&) = delete; }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted2)); static_assert(!__builtin_is_replaceable(UserDeleted2)); struct UserDeleted3 { UserDeleted3 operator=(UserDeleted3); }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted3)); static_assert(!__builtin_is_replaceable(UserDeleted3)); struct UserDeleted4 { UserDeleted4 operator=(UserDeleted4&&); }; static_assert(!__builtin_is_cpp_trivially_relocatable(UserDeleted4)); static_assert(!__builtin_is_replaceable(UserDeleted4)); } void test__builtin_trivially_relocate() { struct S{ ~S();}; struct R {}; __builtin_trivially_relocate(); //expected-error {{too few arguments to function call, expected 3, have 0}} __builtin_trivially_relocate(0, 0, 0, 0); //expected-error {{too many arguments to function call, expected 3, have 4}} __builtin_trivially_relocate(0, 0, 0); //expected-error {{argument to '__builtin_trivially_relocate' must be a pointer}} __builtin_trivially_relocate((const int*)0, 0, 0); //expected-error {{argument to '__builtin_trivially_relocate' must be non-const}} __builtin_trivially_relocate((S*)0, 0, 0); //expected-error {{argument to '__builtin_trivially_relocate' must be relocatable}} __builtin_trivially_relocate((int*)0, 0, 0); //expected-error {{first and second arguments to '__builtin_trivially_relocate' must be of the same type}} __builtin_trivially_relocate((int*)0, (int*)0, (int*)0); // expected-error-re {{cannot initialize a value of type '__size_t' (aka '{{.*}}') with an rvalue of type 'int *'}} __builtin_trivially_relocate((int*)0, (int*)0, 0); __builtin_trivially_relocate((R*)0, (R*)0, 0); } void test__builtin_trivially_relocate(auto&& src, auto&&dest, auto size) { __builtin_trivially_relocate(src, dest, size); // #reloc1 } void do_test__builtin_trivially_relocate() { struct S{ ~S();}; struct R {}; test__builtin_trivially_relocate((R*)0, (R*)0, 0); test__builtin_trivially_relocate((S*)0, (S*)0, 0); // expected-note@-1 {{'test__builtin_trivially_relocate' requested here}} // expected-error@#reloc1 {{first argument to '__builtin_trivially_relocate' must be relocatable}} } namespace GH143599 { struct A { ~A (); }; A::~A () = default; static_assert (!__builtin_is_cpp_trivially_relocatable(A)); static_assert (!__builtin_is_replaceable(A)); struct B { B(const B&); }; B::B (const B&) = default; static_assert (!__builtin_is_cpp_trivially_relocatable(B)); static_assert (!__builtin_is_replaceable(B)); struct C { C& operator=(const C&); }; C& C::operator=(const C&) = default; static_assert (!__builtin_is_cpp_trivially_relocatable(C)); static_assert (!__builtin_is_replaceable(C)); } namespace GH144232 { struct E trivially_relocatable_if_eligible replaceable_if_eligible { E (E &&); E &operator= (E &&) = default; }; struct F trivially_relocatable_if_eligible replaceable_if_eligible { F (F &&) = default; F &operator= (F &&); }; struct G trivially_relocatable_if_eligible replaceable_if_eligible { G (G const &) = default; }; struct I trivially_relocatable_if_eligible replaceable_if_eligible { I &operator= (const I &) = default; }; struct J trivially_relocatable_if_eligible replaceable_if_eligible { J (J const &); }; struct K trivially_relocatable_if_eligible replaceable_if_eligible { K (K const &); }; static_assert (__builtin_is_replaceable (E)); static_assert (__builtin_is_cpp_trivially_relocatable(E)); static_assert (__builtin_is_replaceable (F)); static_assert (__builtin_is_cpp_trivially_relocatable(F)); static_assert (__builtin_is_replaceable (G)); static_assert (__builtin_is_cpp_trivially_relocatable(G)); static_assert (__builtin_is_replaceable (I)); static_assert (__builtin_is_cpp_trivially_relocatable(I)); static_assert (__builtin_is_replaceable (J)); static_assert (__builtin_is_cpp_trivially_relocatable(J)); static_assert (__builtin_is_replaceable (K)); static_assert (__builtin_is_cpp_trivially_relocatable(K)); }