This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG881547db03a6: [clang][Interp] Implement add and sub compound 
assign operators (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D136528?vs=470138&id=471817#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136528/new/

https://reviews.llvm.org/D136528

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  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
@@ -415,5 +415,43 @@
                                          // expected-note {{in call to 'UnderFlow()'}} \
                                          // ref-error {{not an integral constant expression}} \
                                          // ref-note {{in call to 'UnderFlow()'}}
+
+  constexpr int getTwo() {
+    int i = 1;
+    return (i += 1);
+  }
+  static_assert(getTwo() == 2, "");
+
+  constexpr int sub(int a) {
+    return (a -= 2);
+  }
+  static_assert(sub(7) == 5, "");
+
+  constexpr int add(int a, int b) {
+    a += b; // expected-note {{is outside the range of representable values}} \
+            // ref-note {{is outside the range of representable values}} 
+    return a;
+  }
+  static_assert(add(1, 2) == 3, "");
+  static_assert(add(INT_MAX, 1) == 0, ""); // expected-error {{not an integral constant expression}} \
+                                           // expected-note {{in call to 'add}} \
+                                           // ref-error {{not an integral constant expression}} \
+                                           // ref-note {{in call to 'add}}
+
+  constexpr int sub(int a, int b) {
+    a -= b; // expected-note {{is outside the range of representable values}} \
+            // ref-note {{is outside the range of representable values}} 
+    return a;
+  }
+  static_assert(sub(10, 20) == -10, "");
+  static_assert(sub(INT_MIN, 1) == 0, ""); // expected-error {{not an integral constant expression}} \
+                                           // expected-note {{in call to 'sub}} \
+                                           // ref-error {{not an integral constant expression}} \
+                                           // ref-note {{in call to 'sub}}
+
+  constexpr int subAll(int a) {
+    return (a -= a);
+  }
+  static_assert(subAll(213) == 0, "");
 };
 #endif
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -85,6 +85,7 @@
   bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
   bool VisitStringLiteral(const StringLiteral *E);
   bool VisitCharacterLiteral(const CharacterLiteral *E);
+  bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
 
 protected:
   bool visitExpr(const Expr *E) override;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -414,6 +414,57 @@
   return this->emitConst(E, E->getValue());
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
+    const CompoundAssignOperator *E) {
+  const Expr *LHS = E->getLHS();
+  const Expr *RHS = E->getRHS();
+  Optional<PrimType> LT = classify(E->getLHS()->getType());
+  Optional<PrimType> RT = classify(E->getRHS()->getType());
+
+  if (!LT || !RT)
+    return false;
+
+  assert(!E->getType()->isPointerType() &&
+         "Support pointer arithmethic in compound assignment operators");
+
+  // Get LHS pointer, load its value and get RHS value.
+  if (!visit(LHS))
+    return false;
+  if (!this->emitLoad(*LT, E))
+    return false;
+  if (!visit(RHS))
+    return false;
+
+  // Perform operation.
+  switch (E->getOpcode()) {
+  case BO_AddAssign:
+    if (!this->emitAdd(*LT, E))
+      return false;
+    break;
+  case BO_SubAssign:
+    if (!this->emitSub(*LT, E))
+      return false;
+    break;
+
+  case BO_MulAssign:
+  case BO_DivAssign:
+  case BO_RemAssign:
+  case BO_ShlAssign:
+  case BO_ShrAssign:
+  case BO_AndAssign:
+  case BO_XorAssign:
+  case BO_OrAssign:
+  default:
+    llvm_unreachable("Unimplemented compound assign operator");
+  }
+
+  // And store the result in LHS.
+  if (DiscardResult)
+    return this->emitStorePop(*LT, E);
+  return this->emitStore(*LT, E);
+}
+
 template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
   return this->Visit(E);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to