[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