forked from OSchip/llvm-project
[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
This commit is contained in:
parent
515ece1a90
commit
a2a5470fc2
|
@ -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())
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -66,13 +66,17 @@ public:
|
|||
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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 @@ public:
|
|||
|
||||
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 @@ private:
|
|||
};
|
||||
|
||||
/// Describes the statement/declaration an opcode was generated from.
|
||||
class SourceInfo {
|
||||
class SourceInfo final {
|
||||
public:
|
||||
SourceInfo() {}
|
||||
SourceInfo(const Stmt *E) : Source(E) {}
|
||||
|
|
|
@ -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; }
|
Loading…
Reference in New Issue