| // P0466R5 |
| // { dg-do run { target c++20 } } |
| |
| namespace std |
| { |
| template <class S, class M> |
| constexpr bool |
| is_pointer_interconvertible_with_class (M S::*m) noexcept |
| { |
| return __builtin_is_pointer_interconvertible_with_class (m); |
| } |
| } |
| |
| struct A; |
| struct B { int b; double b2; }; |
| struct C : virtual B { int c; }; |
| struct D {}; |
| struct E {}; |
| struct F : public B, D, E {}; |
| struct G : public D, E { int g; }; |
| struct H {}; |
| struct I : public G, H {}; |
| struct J { int j1; private: int j2; public: int j3; }; |
| struct K : public J {}; |
| struct L : public B, D, E {}; |
| struct M { D d [[no_unique_address]]; E e [[no_unique_address]]; int f; }; |
| union U { int a; double b; long long c; }; |
| struct V { union { int a; long b; }; int c; }; |
| union X { int a; union { short b; long c; }; long long d; }; |
| struct Y { void foo () {} }; |
| union Z { int a; private: int b; protected: int c; public: int d; }; |
| |
| int |
| main () |
| { |
| auto t1 = &B::b; |
| if (!std::is_pointer_interconvertible_with_class (t1)) |
| __builtin_abort (); |
| auto t2 = &B::b2; |
| if (std::is_pointer_interconvertible_with_class (t2)) |
| __builtin_abort (); |
| auto t3 = &C::b; |
| if (!std::is_pointer_interconvertible_with_class (t3)) |
| __builtin_abort (); |
| auto t4 = &F::b; |
| if (!std::is_pointer_interconvertible_with_class (t4)) |
| __builtin_abort (); |
| int F::*t5 = &F::b; |
| if (!std::is_pointer_interconvertible_with_class (t5)) |
| __builtin_abort (); |
| auto t6 = &G::g; |
| if (!std::is_pointer_interconvertible_with_class (t6)) |
| __builtin_abort (); |
| int G::*t7 = &G::g; |
| if (!std::is_pointer_interconvertible_with_class (t7)) |
| __builtin_abort (); |
| auto t8 = &I::g; |
| if (!std::is_pointer_interconvertible_with_class (t8)) |
| __builtin_abort (); |
| int I::*t9 = &I::g; |
| if (!std::is_pointer_interconvertible_with_class (t9)) |
| __builtin_abort (); |
| auto t10 = &J::j1; |
| if (std::is_pointer_interconvertible_with_class (t10)) |
| __builtin_abort (); |
| auto t11 = &J::j3; |
| if (std::is_pointer_interconvertible_with_class (t11)) |
| __builtin_abort (); |
| auto t12 = &K::j1; |
| if (std::is_pointer_interconvertible_with_class (t12)) |
| __builtin_abort (); |
| auto t13 = &K::j3; |
| if (std::is_pointer_interconvertible_with_class (t13)) |
| __builtin_abort (); |
| auto t14 = &L::b; |
| if (!std::is_pointer_interconvertible_with_class (t14)) |
| __builtin_abort (); |
| int L::*t15 = &L::b; |
| if (!std::is_pointer_interconvertible_with_class (t15)) |
| __builtin_abort (); |
| auto t16 = &L::b; |
| if (!std::is_pointer_interconvertible_with_class (t16)) |
| __builtin_abort (); |
| auto t17 = &M::d; |
| if (!std::is_pointer_interconvertible_with_class (t17)) |
| __builtin_abort (); |
| auto t18 = &M::e; |
| if (std::is_pointer_interconvertible_with_class (t18)) |
| __builtin_abort (); |
| auto t19 = &M::f; |
| if (std::is_pointer_interconvertible_with_class (t19)) |
| __builtin_abort (); |
| auto t20 = &U::a; |
| if (!std::is_pointer_interconvertible_with_class (t20)) |
| __builtin_abort (); |
| auto t21 = &U::b; |
| if (!std::is_pointer_interconvertible_with_class (t21)) |
| __builtin_abort (); |
| auto t22 = &U::c; |
| if (!std::is_pointer_interconvertible_with_class (t22)) |
| __builtin_abort (); |
| auto t23 = &V::a; |
| if (!std::is_pointer_interconvertible_with_class (t23)) |
| __builtin_abort (); |
| auto t24 = &V::b; |
| if (!std::is_pointer_interconvertible_with_class (t24)) |
| __builtin_abort (); |
| auto t25 = &V::c; |
| if (std::is_pointer_interconvertible_with_class (t25)) |
| __builtin_abort (); |
| auto t26 = &X::a; |
| if (!std::is_pointer_interconvertible_with_class (t26)) |
| __builtin_abort (); |
| auto t27 = &X::b; |
| if (!std::is_pointer_interconvertible_with_class (t27)) |
| __builtin_abort (); |
| auto t28 = &X::c; |
| if (!std::is_pointer_interconvertible_with_class (t28)) |
| __builtin_abort (); |
| auto t29 = &X::d; |
| if (!std::is_pointer_interconvertible_with_class (t29)) |
| __builtin_abort (); |
| auto t30 = (int B::*) nullptr; |
| if (std::is_pointer_interconvertible_with_class (t30)) |
| __builtin_abort (); |
| auto t31 = &Y::foo; |
| if (std::is_pointer_interconvertible_with_class (t31)) |
| __builtin_abort (); |
| auto t32 = &Z::a; |
| if (!std::is_pointer_interconvertible_with_class (t32)) |
| __builtin_abort (); |
| auto t33 = &Z::d; |
| if (!std::is_pointer_interconvertible_with_class (t33)) |
| __builtin_abort (); |
| } |