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 @@ -69,6 +69,8 @@ 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/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -113,6 +113,7 @@ case CK_NonAtomicToAtomic: case CK_NoOp: case CK_UserDefinedConversion: + case CK_NullToPointer: return this->Visit(SubExpr); case CK_ToVoid: @@ -564,6 +565,24 @@ return this->bail(VD); } +template +bool ByteCodeExprGen::VisitCXXBoolLiteralExpr( + const CXXBoolLiteralExpr *E) { + if (DiscardResult) + return true; + + return this->emitConstBool(E->getValue(), E); +} + +template +bool ByteCodeExprGen::VisitCXXNullPtrLiteralExpr( + const CXXNullPtrLiteralExpr *E) { + if (DiscardResult) + return true; + + return this->emitNullPtr(E); +} + template void ByteCodeExprGen::emitCleanup() { for (VariableScope *C = VarScope; C; C = C->getParent()) diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -23,13 +23,13 @@ template inline std::enable_if_t::value, T> ReadArg(Program &P, - CodePtr OpPC) { + CodePtr &OpPC) { return OpPC.read(); } template inline std::enable_if_t::value, T> ReadArg(Program &P, - CodePtr OpPC) { + CodePtr &OpPC) { uint32_t ID = OpPC.read(); return reinterpret_cast(P.getNativePointer(ID)); } diff --git a/clang/lib/AST/Interp/Function.h b/clang/lib/AST/Interp/Function.h --- a/clang/lib/AST/Interp/Function.h +++ b/clang/lib/AST/Interp/Function.h @@ -66,13 +66,17 @@ 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/Function.cpp b/clang/lib/AST/Interp/Function.cpp --- a/clang/lib/AST/Interp/Function.cpp +++ b/clang/lib/AST/Interp/Function.cpp @@ -21,10 +21,6 @@ : 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/Interp.h b/clang/lib/AST/Interp/Interp.h --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -956,13 +956,13 @@ template inline std::enable_if_t::value, T> ReadArg(InterpState &S, - CodePtr OpPC) { + CodePtr &OpPC) { return OpPC.read(); } template inline std::enable_if_t::value, T> ReadArg(InterpState &S, - CodePtr OpPC) { + CodePtr &OpPC) { uint32_t ID = OpPC.read(); return reinterpret_cast(S.P.getNativePointer(ID)); } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -399,8 +399,13 @@ 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(); CodePtr OpPC = PC; diff --git a/clang/lib/AST/Interp/Source.h b/clang/lib/AST/Interp/Source.h --- a/clang/lib/AST/Interp/Source.h +++ b/clang/lib/AST/Interp/Source.h @@ -22,7 +22,7 @@ class Function; /// Pointer into the code segment. -class CodePtr { +class CodePtr final { public: CodePtr() : Ptr(nullptr) {} @@ -43,6 +43,8 @@ bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; } + operator bool() const { return Ptr; } + /// Reads data and advances the pointer. template std::enable_if_t::value, T> read() { using namespace llvm::support; @@ -63,7 +65,7 @@ }; /// 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 --- /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; }