diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -72,6 +72,7 @@ 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/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -222,6 +222,10 @@ 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 @@ template bool ByteCodeExprGen::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 @@ 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 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 @@ return false; } +template +bool ByteCodeExprGen::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(Decl)) { + if (auto It = this->Params.find(PVD); It != this->Params.end()) + return this->emitGetPtrParam(It->second, E); + } + + return false; +} + template void ByteCodeExprGen::emitCleanup() { for (VariableScope *C = VarScope; C; C = C->getParent()) diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp new file mode 100644 --- /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 --- a/clang/test/AST/Interp/literals.cpp +++ b/clang/test/AST/Interp/literals.cpp @@ -31,3 +31,19 @@ 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