1*a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++1z -verify=ref,both %s -fcxx-exceptions -triple=x86_64-linux-gnu 2*a07aba5dSTimm Baeder // RUN: %clang_cc1 -std=c++1z -verify=expected,both %s -fcxx-exceptions -triple=x86_64-linux-gnu -fexperimental-new-constant-interpreter 3*a07aba5dSTimm Baeder 4*a07aba5dSTimm Baeder // both-no-diagnostics 5*a07aba5dSTimm Baeder namespace EvalOrder { 6*a07aba5dSTimm Baeder template<typename T> struct lvalue { 7*a07aba5dSTimm Baeder T t; 8*a07aba5dSTimm Baeder constexpr T &get() { return t; } 9*a07aba5dSTimm Baeder }; 10*a07aba5dSTimm Baeder 11*a07aba5dSTimm Baeder struct UserDefined { 12*a07aba5dSTimm Baeder int n = 0; 13*a07aba5dSTimm Baeder constexpr UserDefined &operator=(const UserDefined&) { return *this; } 14*a07aba5dSTimm Baeder constexpr UserDefined &operator+=(const UserDefined&) { return *this; } 15*a07aba5dSTimm Baeder constexpr void operator<<(const UserDefined&) const {} 16*a07aba5dSTimm Baeder constexpr void operator>>(const UserDefined&) const {} 17*a07aba5dSTimm Baeder constexpr void operator+(const UserDefined&) const {} 18*a07aba5dSTimm Baeder constexpr void operator[](int) const {} 19*a07aba5dSTimm Baeder }; 20*a07aba5dSTimm Baeder constexpr UserDefined ud; 21*a07aba5dSTimm Baeder 22*a07aba5dSTimm Baeder struct NonMember {}; 23*a07aba5dSTimm Baeder constexpr void operator+=(NonMember, NonMember) {} 24*a07aba5dSTimm Baeder constexpr void operator<<(NonMember, NonMember) {} 25*a07aba5dSTimm Baeder constexpr void operator>>(NonMember, NonMember) {} 26*a07aba5dSTimm Baeder constexpr void operator+(NonMember, NonMember) {} 27*a07aba5dSTimm Baeder constexpr NonMember nm; 28*a07aba5dSTimm Baeder 29*a07aba5dSTimm Baeder constexpr void f(...) {} 30*a07aba5dSTimm Baeder 31*a07aba5dSTimm Baeder // Helper to ensure that 'a' is evaluated before 'b'. 32*a07aba5dSTimm Baeder struct seq_checker { 33*a07aba5dSTimm Baeder bool done_a = false; 34*a07aba5dSTimm Baeder bool done_b = false; 35*a07aba5dSTimm Baeder 36*a07aba5dSTimm Baeder template <typename T> constexpr T &&a(T &&v) { 37*a07aba5dSTimm Baeder done_a = true; 38*a07aba5dSTimm Baeder return (T &&)v; 39*a07aba5dSTimm Baeder } 40*a07aba5dSTimm Baeder template <typename T> constexpr T &&b(T &&v) { 41*a07aba5dSTimm Baeder if (!done_a) 42*a07aba5dSTimm Baeder throw "wrong"; 43*a07aba5dSTimm Baeder done_b = true; 44*a07aba5dSTimm Baeder return (T &&)v; 45*a07aba5dSTimm Baeder } 46*a07aba5dSTimm Baeder 47*a07aba5dSTimm Baeder constexpr bool ok() { return done_a && done_b; } 48*a07aba5dSTimm Baeder }; 49*a07aba5dSTimm Baeder 50*a07aba5dSTimm Baeder // SEQ(expr), where part of the expression is tagged A(...) and part is 51*a07aba5dSTimm Baeder // tagged B(...), checks that A is evaluated before B. 52*a07aba5dSTimm Baeder #define A sc.a 53*a07aba5dSTimm Baeder #define B sc.b 54*a07aba5dSTimm Baeder #define SEQ(...) static_assert([](seq_checker sc) { void(__VA_ARGS__); return sc.ok(); }({})) 55*a07aba5dSTimm Baeder 56*a07aba5dSTimm Baeder // Longstanding sequencing rules. 57*a07aba5dSTimm Baeder SEQ((A(1), B(2))); 58*a07aba5dSTimm Baeder SEQ((A(true) ? B(2) : throw "huh?")); 59*a07aba5dSTimm Baeder SEQ((A(false) ? throw "huh?" : B(2))); 60*a07aba5dSTimm Baeder SEQ(A(true) && B(true)); 61*a07aba5dSTimm Baeder SEQ(A(false) || B(true)); 62*a07aba5dSTimm Baeder 63*a07aba5dSTimm Baeder // From P0145R3: 64*a07aba5dSTimm Baeder 65*a07aba5dSTimm Baeder // Rules 1 and 2 have no effect ('b' is not an expression). 66*a07aba5dSTimm Baeder 67*a07aba5dSTimm Baeder // Rule 3: a->*b 68*a07aba5dSTimm Baeder SEQ(A(ud).*B(&UserDefined::n)); 69*a07aba5dSTimm Baeder SEQ(A(&ud)->*B(&UserDefined::n)); 70*a07aba5dSTimm Baeder 71*a07aba5dSTimm Baeder // Rule 4: a(b1, b2, b3) 72*a07aba5dSTimm Baeder SEQ(A(f)(B(1), B(2), B(3))); 73*a07aba5dSTimm Baeder 74*a07aba5dSTimm Baeder // Rule 5: b = a, b @= a 75*a07aba5dSTimm Baeder SEQ(B(lvalue<int>().get()) = A(0)); 76*a07aba5dSTimm Baeder SEQ(B(lvalue<UserDefined>().get()) = A(ud)); 77*a07aba5dSTimm Baeder SEQ(B(lvalue<int>().get()) += A(0)); 78*a07aba5dSTimm Baeder SEQ(B(lvalue<UserDefined>().get()) += A(ud)); 79*a07aba5dSTimm Baeder SEQ(B(lvalue<NonMember>().get()) += A(nm)); 80*a07aba5dSTimm Baeder 81*a07aba5dSTimm Baeder // Rule 6: a[b] 82*a07aba5dSTimm Baeder constexpr int arr[3] = {}; 83*a07aba5dSTimm Baeder SEQ(A(arr)[B(0)]); 84*a07aba5dSTimm Baeder SEQ(A(+arr)[B(0)]); 85*a07aba5dSTimm Baeder SEQ(A(0)[B(arr)]); 86*a07aba5dSTimm Baeder SEQ(A(0)[B(+arr)]); 87*a07aba5dSTimm Baeder 88*a07aba5dSTimm Baeder SEQ(A(ud)[B(0)]); 89*a07aba5dSTimm Baeder 90*a07aba5dSTimm Baeder // Rule 7: a << b 91*a07aba5dSTimm Baeder SEQ(A(1) << B(2)); 92*a07aba5dSTimm Baeder SEQ(A(ud) << B(ud)); 93*a07aba5dSTimm Baeder SEQ(A(nm) << B(nm)); 94*a07aba5dSTimm Baeder 95*a07aba5dSTimm Baeder // Rule 8: a >> b 96*a07aba5dSTimm Baeder SEQ(A(1) >> B(2)); 97*a07aba5dSTimm Baeder SEQ(A(ud) >> B(ud)); 98*a07aba5dSTimm Baeder SEQ(A(nm) >> B(nm)); 99*a07aba5dSTimm Baeder 100*a07aba5dSTimm Baeder // No particular order of evaluation is specified in other cases, but we in 101*a07aba5dSTimm Baeder // practice evaluate left-to-right. 102*a07aba5dSTimm Baeder // FIXME: Technically we're expected to check for undefined behavior due to 103*a07aba5dSTimm Baeder // unsequenced read and modification and treat it as non-constant due to UB. 104*a07aba5dSTimm Baeder SEQ(A(1) + B(2)); 105*a07aba5dSTimm Baeder SEQ(A(ud) + B(ud)); 106*a07aba5dSTimm Baeder SEQ(A(nm) + B(nm)); 107*a07aba5dSTimm Baeder SEQ(f(A(1), B(2))); 108*a07aba5dSTimm Baeder #undef SEQ 109*a07aba5dSTimm Baeder #undef A 110*a07aba5dSTimm Baeder #undef B 111*a07aba5dSTimm Baeder } 112