tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add a new `InvalidCast` op for this purpose and emit a diagnostic.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153276

Files:
  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

Index: clang/test/AST/Interp/unsupported.cpp
===================================================================
--- clang/test/AST/Interp/unsupported.cpp
+++ clang/test/AST/Interp/unsupported.cpp
@@ -47,3 +47,11 @@
     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}}
+
+}
Index: clang/lib/AST/Interp/PrimType.h
===================================================================
--- clang/lib/AST/Interp/PrimType.h
+++ 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,12 @@
   PT_FnPtr,
 };
 
+enum class CastKind : uint8_t {
+  Reinterpret,
+  Dynamic,
+};
+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.
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -51,6 +51,7 @@
 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.
@@ -636,3 +637,6 @@
 
 // [] -> []
 def Invalid : Opcode {}
+def InvalidCast : Opcode {
+  let Args = [ArgCastKind];
+}
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -1847,6 +1847,14 @@
   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
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Disasm.cpp
===================================================================
--- clang/lib/AST/Interp/Disasm.cpp
+++ clang/lib/AST/Interp/Disasm.cpp
@@ -73,3 +73,15 @@
     Anon->dump();
   }
 }
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK) {
+  switch (CK) {
+  case interp::CastKind::Reinterpret:
+    OS << "reinterpret_cast";
+    break;
+  case interp::CastKind::Dynamic:
+    OS << "dynamic_cast";
+    break;
+  }
+  return OS;
+}
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -98,6 +98,7 @@
   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;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1115,6 +1115,15 @@
   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;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to