1a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify=expected,both %s 2a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter -verify=expected,both %s 3a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++14 -verify=ref,both %s 4a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++23 -verify=ref,both %s 5a07aba5dSTimm Baeder 6a07aba5dSTimm Baeder namespace MemberPointers { 7a07aba5dSTimm Baeder struct A { 8a07aba5dSTimm Baeder constexpr A(int n) : n(n) {} 9a07aba5dSTimm Baeder int n; 10a07aba5dSTimm Baeder constexpr int f() const { return n + 3; } 11a07aba5dSTimm Baeder }; 12a07aba5dSTimm Baeder 13a07aba5dSTimm Baeder constexpr A a(7); 14a07aba5dSTimm Baeder static_assert(A(5).*&A::n == 5, ""); 15a07aba5dSTimm Baeder static_assert((&a)->*&A::n == 7, ""); 16a07aba5dSTimm Baeder static_assert((A(8).*&A::f)() == 11, ""); 17a07aba5dSTimm Baeder static_assert(((&a)->*&A::f)() == 10, ""); 18a07aba5dSTimm Baeder 19a07aba5dSTimm Baeder struct B : A { 20a07aba5dSTimm Baeder constexpr B(int n, int m) : A(n), m(m) {} 21a07aba5dSTimm Baeder int m; 22a07aba5dSTimm Baeder constexpr int g() const { return n + m + 1; } 23a07aba5dSTimm Baeder }; 24a07aba5dSTimm Baeder constexpr B b(9, 13); 25a07aba5dSTimm Baeder static_assert(B(4, 11).*&A::n == 4, ""); 26a07aba5dSTimm Baeder static_assert(B(4, 11).*&B::m == 11, ""); 27a07aba5dSTimm Baeder static_assert(B(4, 11).m == 11, ""); 28a07aba5dSTimm Baeder static_assert(B(4, 11).*(int(A::*))&B::m == 11, ""); 29a07aba5dSTimm Baeder static_assert(B(4, 11).*&B::m == 11, ""); 30a07aba5dSTimm Baeder static_assert((&b)->*&A::n == 9, ""); 31a07aba5dSTimm Baeder static_assert((&b)->*&B::m == 13, ""); 32a07aba5dSTimm Baeder static_assert((&b)->*(int(A::*))&B::m == 13, ""); 33a07aba5dSTimm Baeder static_assert((B(4, 11).*&A::f)() == 7, ""); 34a07aba5dSTimm Baeder static_assert((B(4, 11).*&B::g)() == 16, ""); 35a07aba5dSTimm Baeder 36a07aba5dSTimm Baeder static_assert((B(4, 11).*(int(A::*)() const)&B::g)() == 16, ""); 37a07aba5dSTimm Baeder 38a07aba5dSTimm Baeder static_assert(((&b)->*&A::f)() == 12, ""); 39a07aba5dSTimm Baeder static_assert(((&b)->*&B::g)() == 23, ""); 40a07aba5dSTimm Baeder static_assert(((&b)->*(int(A::*)()const)&B::g)() == 23, ""); 41a07aba5dSTimm Baeder 42a07aba5dSTimm Baeder 43a07aba5dSTimm Baeder struct S { 44a07aba5dSTimm Baeder constexpr S(int m, int n, int (S::*pf)() const, int S::*pn) : 45a07aba5dSTimm Baeder m(m), n(n), pf(pf), pn(pn) {} 46a07aba5dSTimm Baeder constexpr S() : m(), n(), pf(&S::f), pn(&S::n) {} 47a07aba5dSTimm Baeder 48a07aba5dSTimm Baeder constexpr int f() const { return this->*pn; } 49a07aba5dSTimm Baeder virtual int g() const; 50a07aba5dSTimm Baeder 51a07aba5dSTimm Baeder int m, n; 52a07aba5dSTimm Baeder int (S::*pf)() const; 53a07aba5dSTimm Baeder int S::*pn; 54a07aba5dSTimm Baeder }; 55a07aba5dSTimm Baeder 56a07aba5dSTimm Baeder constexpr int S::*pm = &S::m; 57a07aba5dSTimm Baeder constexpr int S::*pn = &S::n; 58a07aba5dSTimm Baeder 59a07aba5dSTimm Baeder constexpr int (S::*pf)() const = &S::f; 60a07aba5dSTimm Baeder constexpr int (S::*pg)() const = &S::g; 61a07aba5dSTimm Baeder 62a07aba5dSTimm Baeder constexpr S s(2, 5, &S::f, &S::m); 63a07aba5dSTimm Baeder 64a07aba5dSTimm Baeder static_assert((s.*&S::f)() == 2, ""); 65a07aba5dSTimm Baeder static_assert((s.*s.pf)() == 2, ""); 66a07aba5dSTimm Baeder 67a07aba5dSTimm Baeder static_assert(pf == &S::f, ""); 68a07aba5dSTimm Baeder 69a07aba5dSTimm Baeder static_assert(pf == s.*&S::pf, ""); 70a07aba5dSTimm Baeder 71a07aba5dSTimm Baeder static_assert(pm == &S::m, ""); 72a07aba5dSTimm Baeder static_assert(pm != pn, ""); 73a07aba5dSTimm Baeder static_assert(s.pn != pn, ""); 74a07aba5dSTimm Baeder static_assert(s.pn == pm, ""); 75a07aba5dSTimm Baeder static_assert(pg != nullptr, ""); 76a07aba5dSTimm Baeder static_assert(pf != nullptr, ""); 77a07aba5dSTimm Baeder static_assert((int S::*)nullptr == nullptr, ""); 78a07aba5dSTimm Baeder static_assert(pg == pg, ""); // both-error {{constant expression}} \ 79a07aba5dSTimm Baeder // both-note {{comparison of pointer to virtual member function 'g' has unspecified value}} 80a07aba5dSTimm Baeder static_assert(pf != pg, ""); // both-error {{constant expression}} \ 81a07aba5dSTimm Baeder // both-note {{comparison of pointer to virtual member function 'g' has unspecified value}} 82a07aba5dSTimm Baeder 83a07aba5dSTimm Baeder template<int n> struct T : T<n-1> { const int X = n;}; 84a07aba5dSTimm Baeder template<> struct T<0> { int n; char k;}; 85a07aba5dSTimm Baeder template<> struct T<30> : T<29> { int m; }; 86a07aba5dSTimm Baeder 87a07aba5dSTimm Baeder T<17> t17; 88a07aba5dSTimm Baeder T<30> t30; 89a07aba5dSTimm Baeder 90a07aba5dSTimm Baeder constexpr int (T<15>::*deepm) = (int(T<10>::*))&T<30>::m; 91a07aba5dSTimm Baeder constexpr int (T<10>::*deepn) = &T<0>::n; 92a07aba5dSTimm Baeder constexpr char (T<10>::*deepk) = &T<0>::k; 93a07aba5dSTimm Baeder 94a07aba5dSTimm Baeder static_assert(&(t17.*deepn) == &t17.n, ""); 95a07aba5dSTimm Baeder static_assert(&(t17.*deepk) == &t17.k, ""); 96a07aba5dSTimm Baeder static_assert(deepn == &T<2>::n, ""); 97a07aba5dSTimm Baeder 98a07aba5dSTimm Baeder constexpr int *pgood = &(t30.*deepm); 99a07aba5dSTimm Baeder constexpr int *pbad = &(t17.*deepm); // both-error {{constant expression}} 100a07aba5dSTimm Baeder static_assert(&(t30.*deepm) == &t30.m, ""); 101a07aba5dSTimm Baeder 102a07aba5dSTimm Baeder static_assert(deepm == &T<50>::m, ""); 103a07aba5dSTimm Baeder static_assert(deepm != deepn, ""); 104a07aba5dSTimm Baeder 105a07aba5dSTimm Baeder constexpr T<5> *p17_5 = &t17; 106a07aba5dSTimm Baeder constexpr T<13> *p17_13 = (T<13>*)p17_5; 107a07aba5dSTimm Baeder constexpr T<23> *p17_23 = (T<23>*)p17_13; // both-error {{constant expression}} \ 108a07aba5dSTimm Baeder // both-note {{cannot cast object of dynamic type 'T<17>' to type 'T<23>'}} 109a07aba5dSTimm Baeder constexpr T<18> *p17_18 = (T<18>*)p17_13; // both-error {{constant expression}} \ 110a07aba5dSTimm Baeder // both-note {{cannot cast object of dynamic type 'T<17>' to type 'T<18>'}} 111a07aba5dSTimm Baeder static_assert(&(p17_5->*(int(T<0>::*))deepn) == &t17.n, ""); 112a07aba5dSTimm Baeder static_assert(&(p17_5->*(int(T<0>::*))deepn), ""); 113a07aba5dSTimm Baeder 114a07aba5dSTimm Baeder 115a07aba5dSTimm Baeder static_assert(&(p17_13->*deepn) == &t17.n, ""); 116a07aba5dSTimm Baeder constexpr int *pbad2 = &(p17_13->*(int(T<9>::*))deepm); // both-error {{constant expression}} 117a07aba5dSTimm Baeder 118a07aba5dSTimm Baeder constexpr T<5> *p30_5 = &t30; 119a07aba5dSTimm Baeder constexpr T<23> *p30_23 = (T<23>*)p30_5; 120a07aba5dSTimm Baeder constexpr T<13> *p30_13 = p30_23; 121a07aba5dSTimm Baeder static_assert(&(p30_13->*deepn) == &t30.n, ""); 122a07aba5dSTimm Baeder static_assert(&(p30_23->*deepn) == &t30.n, ""); 123a07aba5dSTimm Baeder static_assert(&(p30_5->*(int(T<3>::*))deepn) == &t30.n, ""); 124a07aba5dSTimm Baeder 125a07aba5dSTimm Baeder static_assert(&(p30_5->*(int(T<2>::*))deepm) == &t30.m, ""); 126a07aba5dSTimm Baeder static_assert(&(((T<17>*)p30_13)->*deepm) == &t30.m, ""); 127a07aba5dSTimm Baeder static_assert(&(p30_23->*deepm) == &t30.m, ""); 128a07aba5dSTimm Baeder 129a07aba5dSTimm Baeder 130a07aba5dSTimm Baeder /// Added tests not from constant-expression-cxx11.cpp 131a07aba5dSTimm Baeder static_assert(pm, ""); 132a07aba5dSTimm Baeder static_assert(!((int S::*)nullptr), ""); 133a07aba5dSTimm Baeder constexpr int S::*pk = nullptr; 134a07aba5dSTimm Baeder static_assert(!pk, ""); 135a07aba5dSTimm Baeder } 136a07aba5dSTimm Baeder 137a07aba5dSTimm Baeder namespace test3 { 138a07aba5dSTimm Baeder struct nsCSSRect { 139a07aba5dSTimm Baeder }; 140a07aba5dSTimm Baeder static int nsCSSRect::* sides; 141a07aba5dSTimm Baeder nsCSSRect dimenX; 142a07aba5dSTimm Baeder void ParseBoxCornerRadii(int y) { 143a07aba5dSTimm Baeder switch (y) { 144a07aba5dSTimm Baeder } 145a07aba5dSTimm Baeder int& x = dimenX.*sides; 146a07aba5dSTimm Baeder } 147a07aba5dSTimm Baeder } 148a07aba5dSTimm Baeder 149a07aba5dSTimm Baeder void foo() { 150a07aba5dSTimm Baeder class X; 151a07aba5dSTimm Baeder void (X::*d) (); 152a07aba5dSTimm Baeder d = nullptr; /// This calls in the constant interpreter. 153a07aba5dSTimm Baeder } 154a07aba5dSTimm Baeder 155a07aba5dSTimm Baeder namespace { 156a07aba5dSTimm Baeder struct A { int n; }; 157a07aba5dSTimm Baeder struct B { int n; }; 158a07aba5dSTimm Baeder struct C : A, B {}; 159a07aba5dSTimm Baeder struct D { double d; C c; }; 160a07aba5dSTimm Baeder const int &&u = static_cast<B&&>(0, ((D&&)D{}).*&D::c).n; // both-warning {{left operand of comma operator has no effect}} 161a07aba5dSTimm Baeder } 162a07aba5dSTimm Baeder 163a07aba5dSTimm Baeder /// From SemaTemplate/instantiate-member-pointers.cpp 164a07aba5dSTimm Baeder namespace { 165a07aba5dSTimm Baeder struct Y { 166a07aba5dSTimm Baeder int x; 167a07aba5dSTimm Baeder }; 168a07aba5dSTimm Baeder 169a07aba5dSTimm Baeder template<typename T, typename Class, T Class::*Ptr> 170a07aba5dSTimm Baeder struct X3 { 171a07aba5dSTimm Baeder X3<T, Class, Ptr> &operator=(const T& value) { 172a07aba5dSTimm Baeder return *this; 173a07aba5dSTimm Baeder } 174a07aba5dSTimm Baeder }; 175a07aba5dSTimm Baeder 176a07aba5dSTimm Baeder typedef int Y::*IntMember; 177a07aba5dSTimm Baeder template<IntMember Member> 178a07aba5dSTimm Baeder struct X4 { 179a07aba5dSTimm Baeder X3<int, Y, Member> member; 180a07aba5dSTimm Baeder int &getMember(Y& y) { return y.*Member; } 181a07aba5dSTimm Baeder }; 182a07aba5dSTimm Baeder 183a07aba5dSTimm Baeder int &get_X4(X4<&Y::x> x4, Y& y) { 184a07aba5dSTimm Baeder return x4.getMember(y); 185a07aba5dSTimm Baeder } 186a07aba5dSTimm Baeder } 187a07aba5dSTimm Baeder 188a07aba5dSTimm Baeder /// From test/CXX/basic/basic.def.odr/p2.cpp 189a07aba5dSTimm Baeder namespace { 190a07aba5dSTimm Baeder void use(int); 191a07aba5dSTimm Baeder struct S { int x; int f() const; }; 192a07aba5dSTimm Baeder constexpr S *ps = nullptr; 193a07aba5dSTimm Baeder S *const &psr = ps; 194a07aba5dSTimm Baeder 195a07aba5dSTimm Baeder void test() { 196a07aba5dSTimm Baeder use(ps->*&S::x); 197a07aba5dSTimm Baeder use(psr->*&S::x); 198a07aba5dSTimm Baeder } 199a07aba5dSTimm Baeder } 200a07aba5dSTimm Baeder 201a07aba5dSTimm Baeder namespace MemPtrTemporary { 202a07aba5dSTimm Baeder struct A { 203a07aba5dSTimm Baeder constexpr int f() const { return 5; } 204a07aba5dSTimm Baeder }; 205a07aba5dSTimm Baeder 206a07aba5dSTimm Baeder constexpr int apply(const A &a, int (A::*ff)() const) { 207a07aba5dSTimm Baeder return (a.*ff)(); 208a07aba5dSTimm Baeder } 209a07aba5dSTimm Baeder 210a07aba5dSTimm Baeder static_assert(apply(A(), &A::f) == 5, ""); 211a07aba5dSTimm Baeder } 212*c6605a08STimm Baeder 213*c6605a08STimm Baeder namespace IndirectFields { 214*c6605a08STimm Baeder struct I { union { struct { int a, b; }; }; }; 215*c6605a08STimm Baeder 216*c6605a08STimm Baeder template <typename T, int T::*F> 217*c6605a08STimm Baeder constexpr int ReadField(const T &o) { 218*c6605a08STimm Baeder return F ? o.*F : 0; 219*c6605a08STimm Baeder } 220*c6605a08STimm Baeder void ReadFields() { 221*c6605a08STimm Baeder I i; 222*c6605a08STimm Baeder ReadField<I, &I::a>(i); 223*c6605a08STimm Baeder ReadField<I, &I::b>(i); 224*c6605a08STimm Baeder } 225*c6605a08STimm Baeder 226*c6605a08STimm Baeder constexpr I i{12}; 227*c6605a08STimm Baeder static_assert(ReadField<I, &I::a>(i) == 12, ""); 228*c6605a08STimm Baeder } 229