Skip to content

Commit a99e8c9

Browse files
authored
[clang][Interp] Fix assignment eval order (#101833)
RHS first.
1 parent f78d288 commit a99e8c9

File tree

2 files changed

+14
-7
lines changed

2 files changed

+14
-7
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,8 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
733733
}
734734

735735
// Typecheck the args.
736-
std::optional<PrimType> LT = classify(LHS->getType());
737-
std::optional<PrimType> RT = classify(RHS->getType());
736+
std::optional<PrimType> LT = classify(LHS);
737+
std::optional<PrimType> RT = classify(RHS);
738738
std::optional<PrimType> T = classify(BO->getType());
739739

740740
// Special case for C++'s three-way/spaceship operator <=>, which
@@ -769,8 +769,16 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
769769
return this->VisitPointerArithBinOp(BO);
770770
}
771771

772-
if (!visit(LHS) || !visit(RHS))
773-
return false;
772+
// Assignmentes require us to evalute the RHS first.
773+
if (BO->getOpcode() == BO_Assign) {
774+
if (!visit(RHS) || !visit(LHS))
775+
return false;
776+
if (!this->emitFlip(*LT, *RT, BO))
777+
return false;
778+
} else {
779+
if (!visit(LHS) || !visit(RHS))
780+
return false;
781+
}
774782

775783
// For languages such as C, cast the result of one
776784
// of our comparision opcodes to T (which is usually int).

clang/test/AST/Interp/eval-order.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ namespace EvalOrder {
4545
}
4646
template <typename T> constexpr T &&b(T &&v) {
4747
if (!done_a)
48-
throw "wrong"; // expected-note 4{{not valid}}
48+
throw "wrong"; // expected-note 3{{not valid}}
4949
done_b = true;
5050
return (T &&)v;
5151
}
@@ -78,8 +78,7 @@ namespace EvalOrder {
7878
SEQ(A(f)(B(1), B(2), B(3)));
7979

8080
// Rule 5: b = a, b @= a
81-
SEQ(B(lvalue<int>().get()) = A(0)); // expected-error {{not an integral constant expression}} FIXME \
82-
// expected-note 2{{in call to}}
81+
SEQ(B(lvalue<int>().get()) = A(0));
8382
SEQ(B(lvalue<UserDefined>().get()) = A(ud)); // expected-error {{not an integral constant expression}} FIXME \
8483
// expected-note 2{{in call to}}
8584
SEQ(B(lvalue<int>().get()) += A(0));

0 commit comments

Comments
 (0)