[clang] 881547d - [clang][Interp] Implement add and sub compound assign operators

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 30 00:11:46 PDT 2022


Author: Timm Bäder
Date: 2022-10-30T08:11:04+01:00
New Revision: 881547db03a6ea243505a8ccba1547f2f18c05ca

URL: https://github.com/llvm/llvm-project/commit/881547db03a6ea243505a8ccba1547f2f18c05ca
DIFF: https://github.com/llvm/llvm-project/commit/881547db03a6ea243505a8ccba1547f2f18c05ca.diff

LOG: [clang][Interp] Implement add and sub compound assign operators

Differential Revision: https://reviews.llvm.org/D136528

Added: 
    

Modified: 
    clang/lib/AST/Interp/ByteCodeExprGen.cpp
    clang/lib/AST/Interp/ByteCodeExprGen.h
    clang/test/AST/Interp/literals.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 30ae7fbfc637a..2edd16bc7e6cc 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -414,6 +414,57 @@ bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
   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);

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 489e8bdb79ca4..4c7550aa497df 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -85,6 +85,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   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;

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index 1c6aa4e26979c..afb98e3c1ef99 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -415,5 +415,43 @@ namespace IncDec {
                                          // 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


        


More information about the cfe-commits mailing list