[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