https://github.com/keinflue created https://github.com/llvm/llvm-project/pull/174132
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 >From c380cba7e742913bd6f3a7b142e4dd1d51e1a461 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..5bc72f580e380 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
