tbaeder updated this revision to Diff 519428.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D149550/new/
https://reviews.llvm.org/D149550
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/test/AST/Interp/floats.cpp
clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -773,6 +773,17 @@
}
static_assert(bug1Dec() == 3);
+ constexpr int f() {
+ int a[] = {1,2};
+ int i = 0;
+
+ // RHS should be evaluated before LHS, so this should
+ // write to a[1];
+ a[i++] += ++i;
+
+ return a[1];
+ }
+ static_assert(f() == 3, "");
};
#endif
Index: clang/test/AST/Interp/floats.cpp
===================================================================
--- clang/test/AST/Interp/floats.cpp
+++ clang/test/AST/Interp/floats.cpp
@@ -86,6 +86,18 @@
return f;
}
static_assert(f2() == __FLT_MAX__, "");
+
+ constexpr float ff() {
+ float a[] = {1,2};
+ int i = 0;
+
+ // RHS should be evaluated before LHS, so this should
+ // write to a[1];
+ a[i++] += ++i;
+
+ return a[1];
+ }
+ static_assert(ff() == 3, "");
}
namespace unary {
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -682,10 +682,19 @@
if (!LT || !RT)
return false;
+ // C++17 onwards require that we evaluate the RHS first.
+ // Compute RHS and save it in a temporary variable so we can
+ // load it again later.
+ if (!visit(RHS))
+ return false;
+
+ unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
+ if (!this->emitSetLocal(*RT, TempOffset, E))
+ return false;
+
// First, visit LHS.
if (!visit(LHS))
return false;
-
if (!this->emitLoad(*LT, E))
return false;
@@ -698,7 +707,7 @@
}
// Now load RHS.
- if (!visit(RHS))
+ if (!this->emitGetLocal(*RT, TempOffset, E))
return false;
switch (E->getOpcode()) {
@@ -796,18 +805,32 @@
assert(!E->getType()->isPointerType() && "Handled above");
assert(!E->getType()->isFloatingType() && "Handled above");
- // Get LHS pointer, load its value and get RHS value.
+ // C++17 onwards require that we evaluate the RHS first.
+ // Compute RHS and save it in a temporary variable so we can
+ // load it again later.
+ // FIXME: Compound assignments are unsequenced in C, so we might
+ // have to figure out how to reject them.
+ if (!visit(RHS))
+ return false;
+
+ unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
+
+ if (!this->emitSetLocal(*RT, TempOffset, E))
+ return false;
+
+ // Get LHS pointer, load its value and cast it to the
+ // computation type if necessary.
if (!visit(LHS))
return false;
if (!this->emitLoad(*LT, E))
return false;
- // If necessary, cast LHS to its computation type.
if (*LT != *LHSComputationT) {
if (!this->emitCast(*LT, *LHSComputationT, E))
return false;
}
- if (!visit(RHS))
+ // Get the RHS value on the stack.
+ if (!this->emitGetLocal(*RT, TempOffset, E))
return false;
// Perform operation.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits