[clang] [clang][Interp] Fix assignment eval order (PR #101833)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 3 08:25:15 PDT 2024


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/101833

RHS first.

>From dc4740dd572eb71af1a7cd33e2c4cf5400d7d5af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 3 Aug 2024 17:24:15 +0200
Subject: [PATCH] [clang][Interp] Fix assignment eval order

RHS first.
---
 clang/lib/AST/Interp/Compiler.cpp    | 16 ++++++++++++----
 clang/test/AST/Interp/eval-order.cpp |  5 ++---
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/clang/lib/AST/Interp/Compiler.cpp b/clang/lib/AST/Interp/Compiler.cpp
index ada22b569b2b0..d9db1c788314c 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -733,8 +733,8 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
   }
 
   // Typecheck the args.
-  std::optional<PrimType> LT = classify(LHS->getType());
-  std::optional<PrimType> RT = classify(RHS->getType());
+  std::optional<PrimType> LT = classify(LHS);
+  std::optional<PrimType> RT = classify(RHS);
   std::optional<PrimType> T = classify(BO->getType());
 
   // Special case for C++'s three-way/spaceship operator <=>, which
@@ -769,8 +769,16 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
       return this->VisitPointerArithBinOp(BO);
   }
 
-  if (!visit(LHS) || !visit(RHS))
-    return false;
+  // Assignmentes require us to evalute the RHS first.
+  if (BO->getOpcode() == BO_Assign) {
+    if (!visit(RHS) || !visit(LHS))
+      return false;
+    if (!this->emitFlip(*LT, *RT, BO))
+      return false;
+  } else {
+    if (!visit(LHS) || !visit(RHS))
+      return false;
+  }
 
   // For languages such as C, cast the result of one
   // of our comparision opcodes to T (which is usually int).
diff --git a/clang/test/AST/Interp/eval-order.cpp b/clang/test/AST/Interp/eval-order.cpp
index d9cfd0b4642fa..c78c5061a08f2 100644
--- a/clang/test/AST/Interp/eval-order.cpp
+++ b/clang/test/AST/Interp/eval-order.cpp
@@ -45,7 +45,7 @@ namespace EvalOrder {
     }
     template <typename T> constexpr T &&b(T &&v) {
       if (!done_a)
-        throw "wrong"; // expected-note 4{{not valid}}
+        throw "wrong"; // expected-note 3{{not valid}}
       done_b = true;
       return (T &&)v;
     }
@@ -78,8 +78,7 @@ namespace EvalOrder {
   SEQ(A(f)(B(1), B(2), B(3)));
 
   // Rule 5: b = a, b @= a
-  SEQ(B(lvalue<int>().get()) = A(0)); // expected-error {{not an integral constant expression}} FIXME \
-                                      // expected-note 2{{in call to}}
+  SEQ(B(lvalue<int>().get()) = A(0));
   SEQ(B(lvalue<UserDefined>().get()) = A(ud)); // expected-error {{not an integral constant expression}} FIXME \
                                                // expected-note 2{{in call to}}
   SEQ(B(lvalue<int>().get()) += A(0));



More information about the cfe-commits mailing list