[clang] 8c0246c - [clang][Interp] Reject reinterpret_casts
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 26 00:59:17 PDT 2023
Author: Timm Bäder
Date: 2023-07-26T09:56:29+02:00
New Revision: 8c0246c7f517a9b901224474f1a608d7e5193583
URL: https://github.com/llvm/llvm-project/commit/8c0246c7f517a9b901224474f1a608d7e5193583
DIFF: https://github.com/llvm/llvm-project/commit/8c0246c7f517a9b901224474f1a608d7e5193583.diff
LOG: [clang][Interp] Reject reinterpret_casts
Add a new InvalidCast op for this purpose and emit a diagnostic.
Differential Revision: https://reviews.llvm.org/D153276
Added:
Modified:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/ByteCodeExprGen.h
clang/lib/AST/Interp/Disasm.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Opcodes.td
clang/lib/AST/Interp/PrimType.h
clang/test/AST/Interp/unsupported.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index bd8e3304c5893b..7970cb63484855 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -997,6 +997,15 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
return this->emitInvalid(E);
}
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr(
+ const CXXReinterpretCastExpr *E) {
+ if (!this->discard(E->getSubExpr()))
+ return false;
+
+ return this->emitInvalidCast(CastKind::Reinterpret, E);
+}
+
template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h
index 6e29bc32ba3830..c828f319cc04cd 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.h
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -98,6 +98,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitLambdaExpr(const LambdaExpr *E);
bool VisitPredefinedExpr(const PredefinedExpr *E);
bool VisitCXXThrowExpr(const CXXThrowExpr *E);
+ bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *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 35ed5d12869719..ef4c81326d2db8 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -73,3 +73,12 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream &OS) const {
Anon->dump();
}
}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK) {
+ switch (CK) {
+ case interp::CastKind::Reinterpret:
+ OS << "reinterpret_cast";
+ break;
+ }
+ return OS;
+}
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 4058d43c0bced5..33ab0cdedeae42 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1754,6 +1754,14 @@ inline bool Invalid(InterpState &S, CodePtr OpPC) {
return false;
}
+/// Same here, but only for casts.
+inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
+ const SourceLocation &Loc = S.Current->getLocation(OpPC);
+ S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
+ << static_cast<uint8_t>(Kind) << S.Current->getRange(OpPC);
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Read opcode arguments
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index bc81dfedfc6353..6d12823990cf2c 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -51,6 +51,7 @@ def ArgRecordField : ArgType { let Name = "const Record::Field *"; }
def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; }
def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; }
+def ArgCastKind : ArgType { let Name = "CastKind"; }
//===----------------------------------------------------------------------===//
// Classes of types instructions operate on.
@@ -604,3 +605,6 @@ def Dup : Opcode {
// [] -> []
def Invalid : Opcode {}
+def InvalidCast : Opcode {
+ let Args = [ArgCastKind];
+}
diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/Interp/PrimType.h
index 693e57210608d9..c7078c6f19c1a2 100644
--- a/clang/lib/AST/Interp/PrimType.h
+++ b/clang/lib/AST/Interp/PrimType.h
@@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_AST_INTERP_TYPE_H
#define LLVM_CLANG_AST_INTERP_TYPE_H
+#include "llvm/Support/raw_ostream.h"
#include <climits>
#include <cstddef>
#include <cstdint>
@@ -42,6 +43,11 @@ enum PrimType : unsigned {
PT_FnPtr,
};
+enum class CastKind : uint8_t {
+ Reinterpret,
+};
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK);
+
constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; }
/// Mapping from primitive types to their representation.
diff --git a/clang/test/AST/Interp/unsupported.cpp b/clang/test/AST/Interp/unsupported.cpp
index 0182b33a7fdc42..9f3477e397eb5c 100644
--- a/clang/test/AST/Interp/unsupported.cpp
+++ b/clang/test/AST/Interp/unsupported.cpp
@@ -47,3 +47,11 @@ namespace Asm {
return 0;
}
}
+
+namespace Casts {
+ constexpr int a = reinterpret_cast<int>(12); // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{reinterpret_cast is not allowed}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{reinterpret_cast is not allowed}}
+
+}
More information about the cfe-commits
mailing list