brintos

brintos / llvm-project-archived public Read only

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