[clang] 05f4448 - [clang][Interp][NFC] Add eval-order test
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon May 6 22:58:58 PDT 2024
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
+}
More information about the cfe-commits
mailing list