Author: keinflue Date: 2026-01-02T19:07:19+01:00 New Revision: 2d45a910959e45242c0e12e81781033c87923919
URL: https://github.com/llvm/llvm-project/commit/2d45a910959e45242c0e12e81781033c87923919 DIFF: https://github.com/llvm/llvm-project/commit/2d45a910959e45242c0e12e81781033c87923919.diff LOG: [clang][bytecode] Fix void*-to-ptr casts originating from new/new[] (#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 Added: Modified: clang/lib/AST/ByteCode/Descriptor.cpp clang/lib/AST/ByteCode/Descriptor.h clang/lib/AST/ByteCode/Pointer.h clang/test/AST/ByteCode/cxx26.cpp Removed: ################################################################################ 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..64461ee9e12cd 100644 --- a/clang/test/AST/ByteCode/cxx26.cpp +++ b/clang/test/AST/ByteCode/cxx26.cpp @@ -9,6 +9,15 @@ 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)); + + static_assert((delete (float*)(void*)new int, true)); // both-error {{not an integral constant expression}} \ + // both-note {{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)); // both-error {{not an integral constant expression}} \ + // both-note {{cast from 'void *' is not allowed in a constant expression because the pointed object type 'int' is not similar to the target type 'float'}} } namespace ReplaceableAlloc { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
