Author: Timm Bäder Date: 2024-05-07T07:58:42+02:00 New Revision: 05f4448d40f00b9fb2447e1c32cd18a7a9b8b011
URL: https://github.com/llvm/llvm-project/commit/05f4448d40f00b9fb2447e1c32cd18a7a9b8b011 DIFF: https://github.com/llvm/llvm-project/commit/05f4448d40f00b9fb2447e1c32cd18a7a9b8b011.diff LOG: [clang][Interp][NFC] Add eval-order test Demonstrate that this isn't yet working right. Added: clang/test/AST/Interp/eval-order.cpp Modified: Removed: ################################################################################ diff --git a/clang/test/AST/Interp/eval-order.cpp b/clang/test/AST/Interp/eval-order.cpp new file mode 100644 index 0000000000000..695a43c9d235b --- /dev/null +++ b/clang/test/AST/Interp/eval-order.cpp @@ -0,0 +1,117 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu +// RUN: %clang_cc1 -std=c++1z -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu -fexperimental-new-constant-interpreter + +// ref-no-diagnostics +// expected-no-diagnostics + +/// Check that assignment operators evaluate their operands right-to-left. +/// Copied from test/SemaCXX/constant-expression-cxx1z.cpp +/// +/// As you can see from the FIXME comments, some of these are not yet working correctly +/// in the new interpreter. +namespace EvalOrder { + template<typename T> struct lvalue { + T t; + constexpr T &get() { return t; } + }; + + struct UserDefined { + int n = 0; + constexpr UserDefined &operator=(const UserDefined&) { return *this; } + constexpr UserDefined &operator+=(const UserDefined&) { return *this; } + constexpr void operator<<(const UserDefined&) const {} + constexpr void operator>>(const UserDefined&) const {} + constexpr void operator+(const UserDefined&) const {} + constexpr void operator[](int) const {} + }; + constexpr UserDefined ud; + + struct NonMember {}; + constexpr void operator+=(NonMember, NonMember) {} + constexpr void operator<<(NonMember, NonMember) {} + constexpr void operator>>(NonMember, NonMember) {} + constexpr void operator+(NonMember, NonMember) {} + constexpr NonMember nm; + + constexpr void f(...) {} + + // Helper to ensure that 'a' is evaluated before 'b'. + struct seq_checker { + bool done_a = false; + bool done_b = false; + + template <typename T> constexpr T &&a(T &&v) { + done_a = true; + return (T &&)v; + } + template <typename T> constexpr T &&b(T &&v) { + if (!done_a) + throw "wrong"; + done_b = true; + return (T &&)v; + } + + constexpr bool ok() { return done_a && done_b; } + }; + + // SEQ(expr), where part of the expression is tagged A(...) and part is + // tagged B(...), checks that A is evaluated before B. + #define A sc.a + #define B sc.b + #define SEQ(...) static_assert([](seq_checker sc) { void(__VA_ARGS__); return sc.ok(); }({})) + + // Longstanding sequencing rules. + SEQ((A(1), B(2))); + SEQ((A(true) ? B(2) : throw "huh?")); + SEQ((A(false) ? throw "huh?" : B(2))); + SEQ(A(true) && B(true)); + SEQ(A(false) || B(true)); + + // From P0145R3: + + // Rules 1 and 2 have no effect ('b' is not an expression). + + // Rule 3: a->*b + // SEQ(A(ud).*B(&UserDefined::n)); FIXME + // SEQ(A(&ud)->*B(&UserDefined::n)); FIXME + + // Rule 4: a(b1, b2, b3) + // SEQ(A(f)(B(1), B(2), B(3))); FIXME + + // Rule 5: b = a, b @= a + // SEQ(B(lvalue<int>().get()) = A(0)); FIXME + // SEQ(B(lvalue<UserDefined>().get()) = A(ud)); FIXME + SEQ(B(lvalue<int>().get()) += A(0)); + // SEQ(B(lvalue<UserDefined>().get()) += A(ud)); FIXME + // SEQ(B(lvalue<NonMember>().get()) += A(nm)); FIXME + + // Rule 6: a[b] + constexpr int arr[3] = {}; + SEQ(A(arr)[B(0)]); + SEQ(A(+arr)[B(0)]); + // SEQ(A(0)[B(arr)]); FIXME + // SEQ(A(0)[B(+arr)]); FIXME + SEQ(A(ud)[B(0)]); + + // Rule 7: a << b + SEQ(A(1) << B(2)); + SEQ(A(ud) << B(ud)); + SEQ(A(nm) << B(nm)); + + // Rule 8: a >> b + SEQ(A(1) >> B(2)); + SEQ(A(ud) >> B(ud)); + SEQ(A(nm) >> B(nm)); + + // No particular order of evaluation is specified in other cases, but we in + // practice evaluate left-to-right. + // FIXME: Technically we're expected to check for undefined behavior due to + // unsequenced read and modification and treat it as non-constant due to UB. + SEQ(A(1) + B(2)); + SEQ(A(ud) + B(ud)); + SEQ(A(nm) + B(nm)); + SEQ(f(A(1), B(2))); + #undef SEQ + #undef A + #undef B +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits