tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135858

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/arrays.cpp

Index: clang/test/AST/Interp/arrays.cpp
===================================================================
--- clang/test/AST/Interp/arrays.cpp
+++ clang/test/AST/Interp/arrays.cpp
@@ -37,6 +37,20 @@
 static_assert(getElement(1) == 4, "");
 static_assert(getElement(5) == 36, "");
 
+constexpr int data[] = {5, 4, 3, 2, 1};
+constexpr int getElement(const int *Arr, int index) {
+  return *(Arr + index);
+}
+
+static_assert(getElement(data, 1) == 4, "");
+static_assert(getElement(data, 4) == 1, "");
+
+constexpr int getElementFromEnd(const int *Arr, int size, int index) {
+  return *(Arr + size - index - 1);
+}
+static_assert(getElementFromEnd(data, 5, 0) == 1, "");
+static_assert(getElementFromEnd(data, 5, 4) == 5, "");
+
 
 template<typename T>
 constexpr T getElementOf(T* array, int i) {
@@ -52,7 +66,6 @@
 static_assert(getElementOfArray(foo[2], 3) == &m, "");
 
 
-constexpr int data[] = {5, 4, 3, 2, 1};
 static_assert(data[0] == 4, ""); // expected-error{{failed}} \
                                  // expected-note{{5 == 4}} \
                                  // ref-error{{failed}} \
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -226,61 +226,79 @@
   // Typecheck the args.
   Optional<PrimType> LT = classify(LHS->getType());
   Optional<PrimType> RT = classify(RHS->getType());
-  if (!LT || !RT) {
+  Optional<PrimType> T = classify(BO->getType());
+  if (!LT || !RT || !T) {
     return this->bail(BO);
   }
 
-  if (Optional<PrimType> T = classify(BO->getType())) {
-    if (!visit(LHS))
+  auto Discard = [this, T, BO](bool Result) {
+    if (!Result)
       return false;
-    if (!visit(RHS))
-      return false;
-
-    auto Discard = [this, T, BO](bool Result) {
-      if (!Result)
+    return DiscardResult ? this->emitPop(*T, BO) : true;
+  };
+
+  // Pointer arithmethic special case. This is supported for one of
+  // LHS and RHS being a pointer type and the other being an integer type.
+  if (BO->getType()->isPointerType()) {
+    PrimType OffsetType;
+    if (LHS->getType()->isIntegerType() && RHS->getType()->isPointerType()) {
+      if (!visit(RHS) || !visit(LHS))
         return false;
-      return DiscardResult ? this->emitPop(*T, BO) : true;
-    };
-
-    switch (BO->getOpcode()) {
-    case BO_EQ:
-      return Discard(this->emitEQ(*LT, BO));
-    case BO_NE:
-      return Discard(this->emitNE(*LT, BO));
-    case BO_LT:
-      return Discard(this->emitLT(*LT, BO));
-    case BO_LE:
-      return Discard(this->emitLE(*LT, BO));
-    case BO_GT:
-      return Discard(this->emitGT(*LT, BO));
-    case BO_GE:
-      return Discard(this->emitGE(*LT, BO));
-    case BO_Sub:
-      return Discard(this->emitSub(*T, BO));
-    case BO_Add:
-      return Discard(this->emitAdd(*T, BO));
-    case BO_Mul:
-      return Discard(this->emitMul(*T, BO));
-    case BO_Rem:
-      return Discard(this->emitRem(*T, BO));
-    case BO_Div:
-      return Discard(this->emitDiv(*T, BO));
-    case BO_Assign:
-      if (!this->emitStore(*T, BO))
+      OffsetType = *LT;
+    } else {
+      if (!visit(LHS) || !visit(RHS))
         return false;
-      return DiscardResult ? this->emitPopPtr(BO) : true;
-    case BO_And:
-      return Discard(this->emitBitAnd(*T, BO));
-    case BO_Or:
-      return Discard(this->emitBitOr(*T, BO));
-    case BO_LAnd:
-    case BO_LOr:
-    default:
-      return this->bail(BO);
+      OffsetType = *RT;
     }
+
+    if (BO->getOpcode() == BO_Add)
+      return Discard(this->emitAddOffset(OffsetType, BO));
+    else if (BO->getOpcode() == BO_Sub)
+      return Discard(this->emitSubOffset(OffsetType, BO));
+    return this->bail(BO);
+  }
+
+  if (!visit(LHS) || !visit(RHS))
+    return false;
+
+  switch (BO->getOpcode()) {
+  case BO_EQ:
+    return Discard(this->emitEQ(*LT, BO));
+  case BO_NE:
+    return Discard(this->emitNE(*LT, BO));
+  case BO_LT:
+    return Discard(this->emitLT(*LT, BO));
+  case BO_LE:
+    return Discard(this->emitLE(*LT, BO));
+  case BO_GT:
+    return Discard(this->emitGT(*LT, BO));
+  case BO_GE:
+    return Discard(this->emitGE(*LT, BO));
+  case BO_Sub:
+    return Discard(this->emitSub(*T, BO));
+  case BO_Add:
+    return Discard(this->emitAdd(*T, BO));
+  case BO_Mul:
+    return Discard(this->emitMul(*T, BO));
+  case BO_Rem:
+    return Discard(this->emitRem(*T, BO));
+  case BO_Div:
+    return Discard(this->emitDiv(*T, BO));
+  case BO_Assign:
+    if (!this->emitStore(*T, BO))
+      return false;
+    return DiscardResult ? this->emitPopPtr(BO) : true;
+  case BO_And:
+    return Discard(this->emitBitAnd(*T, BO));
+  case BO_Or:
+    return Discard(this->emitBitOr(*T, BO));
+  case BO_LAnd:
+  case BO_LOr:
+  default:
+    return this->bail(BO);
   }
 
-  return this->bail(BO);
+  llvm_unreachable("Unhandled binary op");
 }
 
 template <class Emitter>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to