[clang] [clang][bytecode] Fix reinterpret_casts from pointer to non-pointers (PR #108811)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 16 03:01:08 PDT 2024


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/108811

We need to be a little more careful here with whether or nor we are able to do the cast at all or not.

>From 462cd5016c72728ed120773a0da0aab1895649b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sat, 14 Sep 2024 14:57:18 +0200
Subject: [PATCH] [clang][bytecode] Fix reinterpret_casts from pointer to
 non-pointers

We need to be a little more careful here with whether or nor we
are able to do the cast at all or not.
---
 clang/lib/AST/ByteCode/Compiler.cpp | 38 +++++++++++++++++++++++++----
 clang/test/AST/ByteCode/invalid.cpp |  3 +++
 2 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 265350e44d95b9..fe9da7801185e3 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2613,18 +2613,46 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
     const CXXReinterpretCastExpr *E) {
   const Expr *SubExpr = E->getSubExpr();
 
-  bool Fatal = false;
   std::optional<PrimType> FromT = classify(SubExpr);
   std::optional<PrimType> ToT = classify(E);
+
   if (!FromT || !ToT)
-    Fatal = true;
-  else
-    Fatal = (ToT != FromT);
+    return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
+
+  if (FromT == PT_Ptr || ToT == PT_Ptr) {
+    // Both types could be PT_Ptr because their expressions are glvalues.
+    std::optional<PrimType> PointeeFromT;
+    if (SubExpr->getType()->isPointerOrReferenceType())
+      PointeeFromT = classify(SubExpr->getType()->getPointeeType());
+    else
+      PointeeFromT = classify(SubExpr->getType());
+
+    std::optional<PrimType> PointeeToT;
+    if (E->getType()->isPointerOrReferenceType())
+      PointeeToT = classify(E->getType()->getPointeeType());
+    else
+      PointeeToT = classify(E->getType());
+
+    bool Fatal = true;
+    if (PointeeToT && PointeeFromT) {
+      if (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))
+        Fatal = false;
+    }
+
+    if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
+      return false;
+
+    if (E->getCastKind() == CK_LValueBitCast)
+      return this->delegate(SubExpr);
+    return this->VisitCastExpr(E);
+  }
 
+  // Try to actually do the cast.
+  bool Fatal = (ToT != FromT);
   if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
     return false;
 
-  return this->delegate(SubExpr);
+  return this->VisitCastExpr(E);
 }
 
 template <class Emitter>
diff --git a/clang/test/AST/ByteCode/invalid.cpp b/clang/test/AST/ByteCode/invalid.cpp
index 13ba84bcad1040..2a6c2d13e84673 100644
--- a/clang/test/AST/ByteCode/invalid.cpp
+++ b/clang/test/AST/ByteCode/invalid.cpp
@@ -54,4 +54,7 @@ namespace Casts {
     B b;
     (void)*reinterpret_cast<void*>(&b); // both-error {{indirection not permitted on operand of type 'void *'}}
   }
+
+  /// Just make sure this doesn't crash.
+  float PR9558 = reinterpret_cast<const float&>("asd");
 }



More information about the cfe-commits mailing list