Author: Timm Baeder Date: 2024-08-03T17:57:23+02:00 New Revision: a99e8c9c1d624433b57e16d46ab4ecf9f944f6ae
URL: https://github.com/llvm/llvm-project/commit/a99e8c9c1d624433b57e16d46ab4ecf9f944f6ae DIFF: https://github.com/llvm/llvm-project/commit/a99e8c9c1d624433b57e16d46ab4ecf9f944f6ae.diff LOG: [clang][Interp] Fix assignment eval order (#101833) RHS first. Added: Modified: clang/lib/AST/Interp/Compiler.cpp clang/test/AST/Interp/eval-order.cpp Removed: ################################################################################ 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)); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits