[clang] fdfc0df - [clang][Interp] Implement pointer (de)ref operators

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 25 05:22:56 PDT 2022


Author: Timm Bäder
Date: 2022-08-25T14:20:32+02:00
New Revision: fdfc0dfa8ee3dc3d39741ac03a975917f28dcb46

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

LOG: [clang][Interp] Implement pointer (de)ref operators

Implement pointer references, dereferences and assignments.

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

Added: 
    clang/test/AST/Interp/cxx20.cpp

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 be2c48456b5b1..03f877197d160 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -222,6 +222,10 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
       return Discard(this->emitAdd(*T, BO));
     case BO_Mul:
       return Discard(this->emitMul(*T, BO));
+    case BO_Assign:
+      if (!this->emitStore(*T, BO))
+        return false;
+      return DiscardResult ? this->emitPopPtr(BO) : true;
     default:
       return this->bail(BO);
     }
@@ -609,8 +613,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
 
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
-  if (!this->Visit(E->getSubExpr()))
-    return false;
+  const Expr *SubExpr = E->getSubExpr();
 
   switch (E->getOpcode()) {
   case UO_PostInc: // x++
@@ -620,16 +623,32 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
     return false;
 
   case UO_LNot: // !x
+    if (!this->Visit(SubExpr))
+      return false;
     return this->emitInvBool(E);
   case UO_Minus: // -x
+    if (!this->Visit(SubExpr))
+      return false;
     if (Optional<PrimType> T = classify(E->getType()))
       return this->emitNeg(*T, E);
     return false;
   case UO_Plus:  // +x
-    return true; // noop
+    return this->Visit(SubExpr); // noop
 
   case UO_AddrOf: // &x
+    // We should already have a pointer when we get here.
+    return this->Visit(SubExpr);
+
   case UO_Deref:  // *x
+    return dereference(
+        SubExpr, DerefKind::Read,
+        [](PrimType) {
+          llvm_unreachable("Dereferencing requires a pointer");
+          return false;
+        },
+        [this, E](PrimType T) {
+          return DiscardResult ? this->emitPop(T, E) : true;
+        });
   case UO_Not:    // ~x
   case UO_Real:   // __real x
   case UO_Imag:   // __imag x
@@ -641,6 +660,23 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
   return false;
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
+  const auto *Decl = E->getDecl();
+
+  if (auto It = Locals.find(Decl); It != Locals.end()) {
+    const unsigned Offset = It->second.Offset;
+    return this->emitGetPtrLocal(Offset, E);
+  } else if (auto GlobalIndex = P.getGlobal(Decl)) {
+    return this->emitGetPtrGlobal(*GlobalIndex, E);
+  } else if (const auto *PVD = dyn_cast<ParmVarDecl>(Decl)) {
+    if (auto It = this->Params.find(PVD); It != this->Params.end())
+      return this->emitGetPtrParam(It->second, E);
+  }
+
+  return false;
+}
+
 template <class Emitter>
 void ByteCodeExprGen<Emitter>::emitCleanup() {
   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())

diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index ae023aee9390d..f0459b55c8ef0 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -72,6 +72,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
   bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E);
   bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E);
   bool VisitUnaryOperator(const UnaryOperator *E);
+  bool VisitDeclRefExpr(const DeclRefExpr *E);
 
 protected:
   bool visitExpr(const Expr *E) override;

diff  --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
new file mode 100644
index 0000000000000..30de029658338
--- /dev/null
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref %s
+
+
+// expected-no-diagnostics
+// ref-no-diagnostics
+constexpr int getMinus5() {
+  int a = 10;
+  a = -5;
+  int *p = &a;
+  return *p;
+}
+//static_assert(getMinus5() == -5, "") TODO
+
+constexpr int assign() {
+  int m = 10;
+  int k = 12;
+
+  m = (k = 20);
+
+  return m;
+}
+//static_assert(assign() == 20, "");  TODO
+
+
+constexpr int pointerAssign() {
+  int m = 10;
+  int *p = &m;
+
+  *p = 12; // modifies m
+
+  return m;
+}
+//static_assert(pointerAssign() == 12, "");  TODO
+
+constexpr int pointerDeref() {
+  int m = 12;
+  int *p = &m;
+
+  return *p;
+}
+//static_assert(pointerDeref() == 12, ""); TODO
+
+constexpr int pointerAssign2() {
+  int m = 10;
+  int *p = &m;
+  int **pp = &p;
+
+  **pp = 12;
+
+  int v = **pp;
+
+  return v;
+}
+//static_assert(pointerAssign2() == 12, ""); TODO

diff  --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index ed84027f7e1eb..f32f813a49868 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -31,3 +31,19 @@ static_assert(!5 == false, "");
 static_assert(!0, "");
 static_assert(-true, "");
 static_assert(-false, ""); //expected-error{{failed}} ref-error{{failed}}
+
+constexpr int m = 10;
+constexpr const int *p = &m;
+static_assert(p != nullptr, "");
+static_assert(*p == 10, "");
+
+constexpr const int* getIntPointer() {
+  return &m;
+}
+//static_assert(getIntPointer() == &m, ""); TODO
+//static_assert(*getIntPointer() == 10, ""); TODO
+
+constexpr int gimme(int k) {
+  return k;
+}
+// static_assert(gimme(5) == 5, ""); TODO


        


More information about the cfe-commits mailing list