[clang] [clang][bytecode] Only allow lossless ptr-to-int casts (PR #111669)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 9 05:28:50 PDT 2024


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

Only allow those casts if the bitwidth of the two types match.

>From 6d68260682f723fa7a010e2fd381da32316ed5e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Wed, 9 Oct 2024 14:03:39 +0200
Subject: [PATCH] [clang][bytecode] Only allow lossless ptr-to-int casts

Only allow those casts if the bitwidth of the two types match.
---
 clang/lib/AST/ByteCode/Interp.cpp   | 41 +++++++++++++++++++++++++++
 clang/lib/AST/ByteCode/Interp.h     | 43 ++++-------------------------
 clang/test/AST/ByteCode/codegen.cpp |  4 +++
 3 files changed, 51 insertions(+), 37 deletions(-)

diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 050de67c2e77dd..82e11743cc5296 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/StringExtras.h"
 #include <limits>
@@ -1415,6 +1416,46 @@ bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {
   return false;
 }
 
+bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
+                                const Pointer &Ptr, unsigned BitWidth) {
+  if (Ptr.isDummy())
+    return false;
+
+  const SourceInfo &E = S.Current->getSource(OpPC);
+  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+      << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
+
+  if (Ptr.isBlockPointer() && !Ptr.isZero()) {
+    // Only allow based lvalue casts if they are lossless.
+    if (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) !=
+        BitWidth)
+      return Invalid(S, OpPC);
+  }
+  return true;
+}
+
+bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
+    return false;
+
+  S.Stk.push<IntegralAP<false>>(
+      IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
+  return true;
+}
+
+bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+  const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+  if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
+    return false;
+
+  S.Stk.push<IntegralAP<true>>(
+      IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
+  return true;
+}
+
 // https://github.com/llvm/llvm-project/issues/102513
 #if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
 #pragma optimize("", off)
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 2c5538d221bf0b..41708910024476 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2289,53 +2289,22 @@ static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
   return CheckFloatResult(S, OpPC, F, Status, FPO);
 }
 
+bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
+                                const Pointer &Ptr, unsigned BitWidth);
+bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
+bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
+
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
 
-  if (Ptr.isDummy())
+  if (!CheckPointerToIntegralCast(S, OpPC, Ptr, T::bitWidth()))
     return false;
 
-  const SourceInfo &E = S.Current->getSource(OpPC);
-  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
-      << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
-
   S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
   return true;
 }
 
-static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
-                                         uint32_t BitWidth) {
-  const Pointer &Ptr = S.Stk.pop<Pointer>();
-
-  if (Ptr.isDummy())
-    return false;
-
-  const SourceInfo &E = S.Current->getSource(OpPC);
-  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
-      << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
-
-  S.Stk.push<IntegralAP<false>>(
-      IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
-  return true;
-}
-
-static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
-                                          uint32_t BitWidth) {
-  const Pointer &Ptr = S.Stk.pop<Pointer>();
-
-  if (Ptr.isDummy())
-    return false;
-
-  const SourceInfo &E = S.Current->getSource(OpPC);
-  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
-      << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
-
-  S.Stk.push<IntegralAP<true>>(
-      IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
-  return true;
-}
-
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 static inline bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC,
                                           uint32_t FPS) {
diff --git a/clang/test/AST/ByteCode/codegen.cpp b/clang/test/AST/ByteCode/codegen.cpp
index 12d8b5a5c548e1..ea2c812f30f6f0 100644
--- a/clang/test/AST/ByteCode/codegen.cpp
+++ b/clang/test/AST/ByteCode/codegen.cpp
@@ -1,6 +1,10 @@
 // RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
 
+#ifdef __SIZEOF_INT128__
+// CHECK: @PR11705 = global i128 0
+__int128_t PR11705 = (__int128_t)&PR11705;
+#endif
 
 int arr[2];
 // CHECK: @pastEnd = constant ptr getelementptr (i8, ptr @arr, i64 8)



More information about the cfe-commits mailing list