Author: Timm Bäder Date: 2022-08-18T07:11:48+02:00 New Revision: a2a5470fc2499981ad8b4e2aa98ef7ea9893df6c
URL: https://github.com/llvm/llvm-project/commit/a2a5470fc2499981ad8b4e2aa98ef7ea9893df6c DIFF: https://github.com/llvm/llvm-project/commit/a2a5470fc2499981ad8b4e2aa98ef7ea9893df6c.diff LOG: [clang][Interp] Implement boolean and nullptr literals Handle CXX bool literals as well as nullptr literals and add a few tests for each. Differential Revision: https://reviews.llvm.org/D131942 Added: clang/test/AST/Interp/literals.cpp Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Function.cpp clang/lib/AST/Interp/Function.h clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Source.h Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 9b729e347a245..732d4d5c15a28 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -113,6 +113,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: + case CK_NullToPointer: return this->Visit(SubExpr); case CK_ToVoid: @@ -564,6 +565,24 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { return this->bail(VD); } +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr( + const CXXBoolLiteralExpr *E) { + if (DiscardResult) + return true; + + return this->emitConstBool(E->getValue(), E); +} + +template <class Emitter> +bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr( + const CXXNullPtrLiteralExpr *E) { + if (DiscardResult) + return true; + + return this->emitNullPtr(E); +} + 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 82aa413dabbc6..4ce1c8dbe11c1 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -69,6 +69,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, bool VisitIntegerLiteral(const IntegerLiteral *E); bool VisitParenExpr(const ParenExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); + bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E); + bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E); protected: bool visitExpr(const Expr *E) override; diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index 36adbe296b0cc..2edf6b908c4a2 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -23,13 +23,13 @@ using namespace clang::interp; template <typename T> inline std::enable_if_t<!std::is_pointer<T>::value, T> ReadArg(Program &P, - CodePtr OpPC) { + CodePtr &OpPC) { return OpPC.read<T>(); } template <typename T> inline std::enable_if_t<std::is_pointer<T>::value, T> ReadArg(Program &P, - CodePtr OpPC) { + CodePtr &OpPC) { uint32_t ID = OpPC.read<uint32_t>(); return reinterpret_cast<T>(P.getNativePointer(ID)); } diff --git a/clang/lib/AST/Interp/Function.cpp b/clang/lib/AST/Interp/Function.cpp index 6ba97df1cd30e..57d020e434ee8 100644 --- a/clang/lib/AST/Interp/Function.cpp +++ b/clang/lib/AST/Interp/Function.cpp @@ -21,10 +21,6 @@ Function::Function(Program &P, const FunctionDecl *F, unsigned ArgSize, : P(P), Loc(F->getBeginLoc()), F(F), ArgSize(ArgSize), ParamTypes(std::move(ParamTypes)), Params(std::move(Params)) {} -CodePtr Function::getCodeBegin() const { return Code.data(); } - -CodePtr Function::getCodeEnd() const { return Code.data() + Code.size(); } - Function::ParamDescriptor Function::getParamDescriptor(unsigned Offset) const { auto It = Params.find(Offset); assert(It != Params.end() && "Invalid parameter offset"); diff --git a/clang/lib/AST/Interp/Function.h b/clang/lib/AST/Interp/Function.h index ac1dffea11609..fa850f76c0267 100644 --- a/clang/lib/AST/Interp/Function.h +++ b/clang/lib/AST/Interp/Function.h @@ -66,13 +66,17 @@ class Function { unsigned getArgSize() const { return ArgSize; } /// Returns a pointer to the start of the code. - CodePtr getCodeBegin() const; + CodePtr getCodeBegin() const { return Code.data(); } /// Returns a pointer to the end of the code. - CodePtr getCodeEnd() const; + CodePtr getCodeEnd() const { return Code.data() + Code.size(); } /// Returns the original FunctionDecl. const FunctionDecl *getDecl() const { return F; } + /// Returns the name of the function decl this code + /// was generated for. + const std::string getName() const { return F->getNameInfo().getAsString(); } + /// Returns the location. SourceLocation getLoc() const { return Loc; } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index cec3f6d6160ec..7b64891ee68aa 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -399,8 +399,13 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) { return false; } bool Interpret(InterpState &S, APValue &Result) { + assert(!S.Current->isRoot()); CodePtr PC = S.Current->getPC(); + // Empty program. + if (!PC) + return true; + for (;;) { auto Op = PC.read<Opcode>(); CodePtr OpPC = PC; diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index a1d90f26ba464..475768677ed9b 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -956,13 +956,13 @@ inline bool ExpandPtr(InterpState &S, CodePtr OpPC) { template <typename T> inline std::enable_if_t<!std::is_pointer<T>::value, T> ReadArg(InterpState &S, - CodePtr OpPC) { + CodePtr &OpPC) { return OpPC.read<T>(); } template <typename T> inline std::enable_if_t<std::is_pointer<T>::value, T> ReadArg(InterpState &S, - CodePtr OpPC) { + CodePtr &OpPC) { uint32_t ID = OpPC.read<uint32_t>(); return reinterpret_cast<T>(S.P.getNativePointer(ID)); } diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h index 6acaf406b47ab..0d9780ca1c46a 100644 --- a/clang/lib/AST/Interp/Source.h +++ b/clang/lib/AST/Interp/Source.h @@ -22,7 +22,7 @@ namespace interp { class Function; /// Pointer into the code segment. -class CodePtr { +class CodePtr final { public: CodePtr() : Ptr(nullptr) {} @@ -43,6 +43,8 @@ class CodePtr { bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; } + operator bool() const { return Ptr; } + /// Reads data and advances the pointer. template <typename T> std::enable_if_t<!std::is_pointer<T>::value, T> read() { using namespace llvm::support; @@ -63,7 +65,7 @@ class CodePtr { }; /// Describes the statement/declaration an opcode was generated from. -class SourceInfo { +class SourceInfo final { public: SourceInfo() {} SourceInfo(const Stmt *E) : Source(E) {} diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp new file mode 100644 index 0000000000000..9aa51846019fa --- /dev/null +++ b/clang/test/AST/Interp/literals.cpp @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++11 -verify %s + +static_assert(true, ""); +static_assert(false, ""); // expected-error{{failed}} +static_assert(nullptr == nullptr, ""); +static_assert(1 == 1, ""); +static_assert(1 == 3, ""); // expected-error{{failed}} + +constexpr int number = 10; +static_assert(number == 10, ""); +static_assert(number != 10, ""); // expected-error{{failed}} + +constexpr bool getTrue() { return true; } +constexpr bool getFalse() { return false; } +constexpr void* getNull() { return nullptr; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits