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