[clang] a2a5470 - [clang][Interp] Implement boolean and nullptr literals
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 17 22:12:14 PDT 2022
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; }
More information about the cfe-commits
mailing list