https://github.com/keinflue updated 
https://github.com/llvm/llvm-project/pull/174132

>From f925d36a27650e755c6ede3da6e989e10ef2884b Mon Sep 17 00:00:00 2001
From: keinflue <[email protected]>
Date: Thu, 1 Jan 2026 07:49:21 +0100
Subject: [PATCH] [Clang][Bytecode] Fix void*-to-ptr casts originating from
 new/new[]

In void*-to-ptr casts, the type of the pointed-to object in the source
operand needs to be compared to the target pointee type.

If a block was created for a `new`/`new[]`/`std::allocator` expression,
then a pointer needs to be stripped from the type of the expression
(which points to the single-object allocation or first element of the
allocation) to get the former.

`Descriptor::getType` did not do this and `Descriptor::getDataType`
returns an array type for array allocations. Therefore this introduces
a new function `Descriptor::getDataElemType` with the same behavior as
`Descriptor::getDataType`, except that it always produces the element
type in the array case and avoids the need for an `ASTContext`
reference. Make `Pointer::getType` use this function instead.

Fixes #174131
---
 clang/lib/AST/ByteCode/Descriptor.cpp | 16 ++++++++++++++++
 clang/lib/AST/ByteCode/Descriptor.h   |  1 +
 clang/lib/AST/ByteCode/Pointer.h      |  3 ++-
 clang/test/AST/ByteCode/cxx26.cpp     | 11 +++++++++++
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp 
b/clang/lib/AST/ByteCode/Descriptor.cpp
index 2864be8115637..a3cee034191d2 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -433,6 +433,22 @@ QualType Descriptor::getDataType(const ASTContext &Ctx) 
const {
   return getType();
 }
 
+QualType Descriptor::getDataElemType() const {
+  if (const auto *E = asExpr()) {
+    if (isa<CXXNewExpr>(E))
+      return E->getType()->getPointeeType();
+
+    // std::allocator.allocate() call.
+    if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
+        ME && ME->getRecordDecl()->getName() == "allocator" &&
+        ME->getMethodDecl()->getName() == "allocate")
+      return E->getType()->getPointeeType();
+    return E->getType();
+  }
+
+  return getType();
+}
+
 SourceLocation Descriptor::getLocation() const {
   if (auto *D = dyn_cast<const Decl *>(Source))
     return D->getLocation();
diff --git a/clang/lib/AST/ByteCode/Descriptor.h 
b/clang/lib/AST/ByteCode/Descriptor.h
index 057f40f8f1f69..5bf550ffe1172 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -203,6 +203,7 @@ struct Descriptor final {
   QualType getType() const;
   QualType getElemQualType() const;
   QualType getDataType(const ASTContext &Ctx) const;
+  QualType getDataElemType() const;
   SourceLocation getLocation() const;
   SourceInfo getLoc() const;
 
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 9032bdade850f..202508cb71e5a 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -354,7 +354,8 @@ class Pointer {
       if (const auto *CT = getFieldDesc()->getType()->getAs<VectorType>())
         return CT->getElementType();
     }
-    return getFieldDesc()->getType();
+
+    return getFieldDesc()->getDataElemType();
   }
 
   [[nodiscard]] Pointer getDeclPtr() const { return Pointer(BS.Pointee); }
diff --git a/clang/test/AST/ByteCode/cxx26.cpp 
b/clang/test/AST/ByteCode/cxx26.cpp
index cd786b17ca9ab..bc000c0d8b178 100644
--- a/clang/test/AST/ByteCode/cxx26.cpp
+++ b/clang/test/AST/ByteCode/cxx26.cpp
@@ -9,6 +9,17 @@ namespace VoidCast {
   constexpr void* p = nullptr;
   constexpr int* q = static_cast<int*>(p);
   static_assert(q == nullptr);
+
+  static_assert((delete (int*)(void*)new int, true));
+  static_assert((delete[] (int*)(void*)new int[2], true));
+
+  // both-error@+2 {{not an integral constant expression}}
+  // both-note@+1 {{cast from 'void *' is not allowed in a constant expression 
because the pointed object type 'int' is not similar to the target type 
'float'}}
+  static_assert((delete (float*)(void*)new int, true));
+
+  // both-error@+2 {{not an integral constant expression}}
+  // both-note@+1 {{cast from 'void *' is not allowed in a constant expression 
because the pointed object type 'int' is not similar to the target type 
'float'}}
+  static_assert((delete[] (float*)(void*)new int[2], true));
 }
 
 namespace ReplaceableAlloc {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to