https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/183513
>From 183c46f7177365757e3ae44eac5dc9873dd4f8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Thu, 26 Feb 2026 08:23:25 +0100 Subject: [PATCH] hasPtrField --- clang/lib/AST/ByteCode/EvaluationResult.cpp | 24 +++++++++++++++------ clang/lib/AST/ByteCode/Program.cpp | 9 ++++++-- clang/lib/AST/ByteCode/Record.cpp | 15 +++++++++---- clang/lib/AST/ByteCode/Record.h | 6 +++++- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp index 7c3c21cf28251..039848f00764e 100644 --- a/clang/lib/AST/ByteCode/EvaluationResult.cpp +++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp @@ -157,6 +157,15 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S, return true; } +static bool isOrHasPtr(const Descriptor *D) { + if ((D->isPrimitive() || D->isPrimitiveArray()) && D->getPrimType() == PT_Ptr) + return true; + + if (D->ElemRecord) + return D->ElemRecord->hasPtrField(); + return false; +} + static void collectBlocks(const Pointer &Ptr, llvm::SetVector<const Block *> &Blocks) { auto isUsefulPtr = [](const Pointer &P) -> bool { @@ -173,26 +182,29 @@ static void collectBlocks(const Pointer &Ptr, if (!Desc) return; - if (const Record *R = Desc->ElemRecord) { + if (const Record *R = Desc->ElemRecord; R && R->hasPtrField()) { + for (const Record::Field &F : R->fields()) { - const Pointer &FieldPtr = Ptr.atField(F.Offset); + if (!isOrHasPtr(F.Desc)) + continue; + Pointer FieldPtr = Ptr.atField(F.Offset); assert(FieldPtr.block() == Ptr.block()); collectBlocks(FieldPtr, Blocks); } } else if (Desc->isPrimitive() && Desc->getPrimType() == PT_Ptr) { - const Pointer &Pointee = Ptr.deref<Pointer>(); + Pointer Pointee = Ptr.deref<Pointer>(); if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.block())) collectBlocks(Pointee, Blocks); } else if (Desc->isPrimitiveArray() && Desc->getPrimType() == PT_Ptr) { for (unsigned I = 0; I != Desc->getNumElems(); ++I) { - const Pointer &ElemPointee = Ptr.elem<Pointer>(I); + Pointer ElemPointee = Ptr.elem<Pointer>(I); if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.block())) collectBlocks(ElemPointee, Blocks); } - } else if (Desc->isCompositeArray()) { + } else if (Desc->isCompositeArray() && isOrHasPtr(Desc->ElemDesc)) { for (unsigned I = 0; I != Desc->getNumElems(); ++I) { - const Pointer &ElemPtr = Ptr.atIndex(I).narrow(); + Pointer ElemPtr = Ptr.atIndex(I).narrow(); collectBlocks(ElemPtr, Blocks); } } diff --git a/clang/lib/AST/ByteCode/Program.cpp b/clang/lib/AST/ByteCode/Program.cpp index 9a7b38d4d828e..7eebb303d8553 100644 --- a/clang/lib/AST/ByteCode/Program.cpp +++ b/clang/lib/AST/ByteCode/Program.cpp @@ -356,6 +356,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { // Reserve space for fields. Record::FieldList Fields; Fields.reserve(RD->getNumFields()); + bool HasPtrField = false; for (const FieldDecl *FD : RD->fields()) { FD = FD->getFirstDecl(); // Note that we DO create fields and descriptors @@ -374,9 +375,12 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { if (OptPrimType T = Ctx.classify(FT)) { Desc = createDescriptor(FD, *T, nullptr, std::nullopt, IsConst, /*isTemporary=*/false, IsMutable, IsVolatile); + HasPtrField = HasPtrField || (T == PT_Ptr); } else { Desc = createDescriptor(FD, FT.getTypePtr(), std::nullopt, IsConst, /*isTemporary=*/false, IsMutable, IsVolatile); + HasPtrField = HasPtrField || (Desc && Desc->isPrimitiveArray() && + Desc->getPrimType() == PT_Ptr); } if (!Desc) return nullptr; @@ -384,8 +388,9 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { BaseSize += align(Desc->getAllocSize()); } - Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields), - std::move(VirtBases), VirtSize, BaseSize); + Record *R = new (Allocator) + Record(RD, std::move(Bases), std::move(Fields), std::move(VirtBases), + VirtSize, BaseSize, HasPtrField); Records[RD] = R; return R; } diff --git a/clang/lib/AST/ByteCode/Record.cpp b/clang/lib/AST/ByteCode/Record.cpp index 17cf629a91b60..f0ec33f54901c 100644 --- a/clang/lib/AST/ByteCode/Record.cpp +++ b/clang/lib/AST/ByteCode/Record.cpp @@ -14,17 +14,24 @@ using namespace clang::interp; Record::Record(const RecordDecl *Decl, BaseList &&SrcBases, FieldList &&SrcFields, VirtualBaseList &&SrcVirtualBases, - unsigned VirtualSize, unsigned BaseSize) + unsigned VirtualSize, unsigned BaseSize, bool HasPtrField) : Decl(Decl), Bases(std::move(SrcBases)), Fields(std::move(SrcFields)), BaseSize(BaseSize), VirtualSize(VirtualSize), IsUnion(Decl->isUnion()), - IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()) { + IsAnonymousUnion(IsUnion && Decl->isAnonymousStructOrUnion()), + HasPtrField(HasPtrField) { for (Base &V : SrcVirtualBases) VirtualBases.emplace_back(V.Decl, V.Desc, V.R, V.Offset + BaseSize); - for (Base &B : Bases) + for (Base &B : Bases) { BaseMap[B.Decl] = &B; - for (Base &V : VirtualBases) + if (!HasPtrField) + HasPtrField |= B.R->hasPtrField(); + } + for (Base &V : VirtualBases) { VirtualBaseMap[V.Decl] = &V; + if (!HasPtrField) + HasPtrField |= V.R->hasPtrField(); + } } std::string Record::getName() const { diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h index 29c500b9c29d5..e43f683364e26 100644 --- a/clang/lib/AST/ByteCode/Record.h +++ b/clang/lib/AST/ByteCode/Record.h @@ -75,6 +75,8 @@ class Record final { return CXXDecl->getDestructor(); return nullptr; } + /// If this record (or any of its bases) contains a field of type PT_Ptr. + bool hasPtrField() const { return HasPtrField; } /// Returns true for anonymous unions and records /// with no destructor or for those with a trivial destructor. @@ -125,7 +127,7 @@ class Record final { /// Constructor used by Program to create record descriptors. Record(const RecordDecl *, BaseList &&Bases, FieldList &&Fields, VirtualBaseList &&VirtualBases, unsigned VirtualSize, - unsigned BaseSize); + unsigned BaseSize, bool HasPtrField = true); private: friend class Program; @@ -151,6 +153,8 @@ class Record final { bool IsUnion; /// If this is an anonymous union. bool IsAnonymousUnion; + /// If any of the fields are pointers (or references). + bool HasPtrField = false; }; } // namespace interp _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
