[clang] 4a2c4ac - [clang][Interp] Support pointers in compound assignment operators

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Fri Feb 3 07:43:11 PST 2023


Author: Timm Bäder
Date: 2023-02-03T16:42:46+01:00
New Revision: 4a2c4acb98694bb90c04e05052898708a03a7ebc

URL: https://github.com/llvm/llvm-project/commit/4a2c4acb98694bb90c04e05052898708a03a7ebc
DIFF: https://github.com/llvm/llvm-project/commit/4a2c4acb98694bb90c04e05052898708a03a7ebc.diff

LOG: [clang][Interp] Support pointers in compound assignment operators

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

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 f8ee3a80326b..2b4e324f7b0f 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -685,6 +685,41 @@ bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
   return this->emitStore(*LT, E);
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
+    const CompoundAssignOperator *E) {
+  BinaryOperatorKind Op = E->getOpcode();
+  const Expr *LHS = E->getLHS();
+  const Expr *RHS = E->getRHS();
+  std::optional<PrimType> LT = classify(LHS->getType());
+  std::optional<PrimType> RT = classify(RHS->getType());
+
+  if (Op != BO_AddAssign && Op != BO_SubAssign)
+    return false;
+
+  if (!LT || !RT)
+    return false;
+  assert(*LT == PT_Ptr);
+
+  if (!visit(LHS))
+    return false;
+
+  if (!this->emitLoadPtr(LHS))
+    return false;
+
+  if (!visit(RHS))
+    return false;
+
+  if (Op == BO_AddAssign)
+    this->emitAddOffset(*RT, E);
+  else
+    this->emitSubOffset(*RT, E);
+
+  if (DiscardResult)
+    return this->emitStorePopPtr(E);
+  return this->emitStorePtr(E);
+}
+
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
     const CompoundAssignOperator *E) {
@@ -694,6 +729,9 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
   if (E->getType()->isFloatingType())
     return VisitFloatCompoundAssignOperator(E);
 
+  if (E->getType()->isPointerType())
+    return VisitPointerCompoundAssignOperator(E);
+
   const Expr *LHS = E->getLHS();
   const Expr *RHS = E->getRHS();
   std::optional<PrimType> LHSComputationT =
@@ -705,9 +743,7 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
   if (!LT || !RT || !ResultT || !LHSComputationT)
     return false;
 
-  assert(!E->getType()->isPointerType() &&
-         "Support pointer arithmethic in compound assignment operators");
-
+  assert(!E->getType()->isPointerType() && "Handled above");
   assert(!E->getType()->isFloatingType() && "Handled above");
 
   // Get LHS pointer, load its value and get RHS value.

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 6b16b62a2e58..74cd5984daf5 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -87,6 +87,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   bool VisitCharacterLiteral(const CharacterLiteral *E);
   bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
   bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E);
+  bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E);
   bool VisitExprWithCleanups(const ExprWithCleanups *E);
   bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
 

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index c57485aecbf9..7121a24052f9 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -669,5 +669,42 @@ namespace IncDec {
                                               // expected-note {{in call to 'IntMul}} \
                                               // ref-error {{not an integral constant expression}} \
                                               // ref-note {{in call to 'IntMul}}
+  constexpr int arr[] = {1,2,3};
+  constexpr int ptrInc1() {
+    const int *p = arr;
+    p += 2;
+    return *p;
+  }
+  static_assert(ptrInc1() == 3, "");
+
+  constexpr int ptrInc2() {
+    const int *p = arr;
+    return *(p += 1);
+  }
+  static_assert(ptrInc2() == 2, "");
+
+  constexpr int ptrInc3() { // expected-error {{never produces a constant expression}} \
+                            // ref-error {{never produces a constant expression}}
+    const int *p = arr;
+    p += 12; // expected-note {{cannot refer to element 12 of array of 3 elements}} \
+             // ref-note {{cannot refer to element 12 of array of 3 elements}}
+    return *p;
+  }
+
+  constexpr int ptrIncDec1() {
+    const int *p = arr;
+    p += 2;
+    p -= 1;
+    return *p;
+  }
+  static_assert(ptrIncDec1() == 2, "");
+
+  constexpr int ptrDec1() { // expected-error {{never produces a constant expression}} \
+                        // ref-error {{never produces a constant expression}}
+    const int *p = arr;
+    p -= 1;  // expected-note {{cannot refer to element -1 of array of 3 elements}} \
+             // ref-note {{cannot refer to element -1 of array of 3 elements}}
+    return *p;
+  }
 };
 #endif


        


More information about the cfe-commits mailing list