https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/155853
>From 7aa8e2560c5c4d27687e634aaae3f7411a5e2182 Mon Sep 17 00:00:00 2001 From: Nerixyz <[email protected]> Date: Sat, 8 Aug 2026 15:56:33 +0200 Subject: [PATCH] [LLDB][NativePDB] Set IsDynmaicCXXType metadata for records --- .../Clang/ClangASTMetadata.cpp | 10 ++--- .../NativePDB/PdbAstBuilderClang.cpp | 22 ++++++---- .../SymbolFile/NativePDB/PdbAstBuilderClang.h | 5 ++- .../NativePDB/UdtRecordCompleter.cpp | 7 +++ .../SymbolFile/NativePDB/UdtRecordCompleter.h | 1 + .../TypeSystem/Clang/TypeSystemClang.cpp | 25 ++++++++--- .../SymbolFile/NativePDB/dynamic-types.cpp | 43 +++++++++++++++++++ 7 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp index 2c5dacb60a9b8..d77509ef248d4 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTMetadata.cpp @@ -31,12 +31,12 @@ void ClangASTMetadata::Dump(Stream *s) { lldb::user_id_t uid = GetUserID(); if (uid != LLDB_INVALID_UID) { - s->Printf("uid=0x%" PRIx64, uid); + s->Printf("uid=0x%" PRIx64 " ", uid); } uint64_t isa_ptr = GetISAPtr(); if (isa_ptr != 0) { - s->Printf("isa_ptr=0x%" PRIx64, isa_ptr); + s->Printf("isa_ptr=0x%" PRIx64 " ", isa_ptr); } const char *obj_ptr_name = GetObjectPtrName(); @@ -44,8 +44,8 @@ void ClangASTMetadata::Dump(Stream *s) { s->Printf("obj_ptr_name=\"%s\" ", obj_ptr_name); } - if (m_is_dynamic_cxx) { - s->Printf("is_dynamic_cxx=%i ", m_is_dynamic_cxx); - } + if (m_is_dynamic_cxx) + *s << "is_dynamic_cxx=" << (m_is_dynamic_cxx == 2) << ' '; + s->EOL(); } diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp index 673bd2826b455..c44ed246e6f64 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp @@ -694,18 +694,26 @@ PdbAstBuilderClang::CreateModifierType(const ModifierRecord &modifier) { return unmodified_type; } -clang::QualType PdbAstBuilderClang::CreateRecordType(PdbTypeSymId id, - const TagRecord &record) { +clang::QualType +PdbAstBuilderClang::CreateRecordType(PdbTypeSymId id, + const CVTagRecord &record) { clang::DeclContext *context = nullptr; std::string uname; - std::tie(context, uname) = CreateDeclInfoForType(record, id.index); + std::tie(context, uname) = CreateDeclInfoForType(record.asTag(), id.index); if (!context) return {}; - clang::TagTypeKind ttk = TranslateUdtKind(record); + clang::TagTypeKind ttk = TranslateUdtKind(record.asTag()); ClangASTMetadata metadata; metadata.SetUserID(toOpaqueUid(id)); - metadata.SetIsDynamicCXXType(false); + // unions can't be dynamic + if (record.contextKind() != CompilerContextKind::ClassOrStruct) + metadata.SetIsDynamicCXXType(false); + // If a class has a vtable, it is dynamic. + else if (!record.asClass().getVTableShape().isNoneType()) + metadata.SetIsDynamicCXXType(true); + // else + // wait until the record is completed as it might have virtual bases CompilerType ct = m_clang.CreateRecordType( context, OptionalClangModuleID(), uname, llvm::to_underlying(ttk), @@ -888,11 +896,9 @@ clang::QualType PdbAstBuilderClang::CreateType(PdbTypeSymId type) { if (IsTagRecord(cvt)) { CVTagRecord tag = CVTagRecord::create(cvt); - if (tag.kind() == CVTagRecord::Union) - return CreateRecordType(type.index, tag.asUnion()); if (tag.kind() == CVTagRecord::Enum) return CreateEnumType(type.index, tag.asEnum()); - return CreateRecordType(type.index, tag.asClass()); + return CreateRecordType(type.index, tag); } if (cvt.kind() == LF_ARRAY) { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h index 0d214cb57f820..2abf1eb58f3ac 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.h @@ -50,6 +50,8 @@ struct DeclStatus { bool resolved = false; }; +struct CVTagRecord; + class PdbAstBuilderClang : public PdbAstBuilder { public: PdbAstBuilderClang(TypeSystemClang &clang); @@ -114,8 +116,7 @@ class PdbAstBuilderClang : public PdbAstBuilder { clang::QualType CreateModifierType(const llvm::codeview::ModifierRecord &modifier); clang::QualType CreateArrayType(const llvm::codeview::ArrayRecord &array); - clang::QualType CreateRecordType(PdbTypeSymId id, - const llvm::codeview::TagRecord &record); + clang::QualType CreateRecordType(PdbTypeSymId id, const CVTagRecord &record); clang::QualType CreateEnumType(PdbTypeSymId id, const llvm::codeview::EnumRecord &record); clang::QualType diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 871b053151c61..2476928eb5a3e 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -133,6 +133,7 @@ Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr, // LF_VBCLASS. if (cvr.Kind == LF_VBCLASS) AddBaseClassForTypeIndex(base.BaseType, base.getAccess(), base.VTableIndex); + m_any_virtual_base = true; return Error::success(); } @@ -384,6 +385,12 @@ void UdtRecordCompleter::complete() { if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) { m_ast_builder.GetClangASTImporter().SetRecordLayout(record_decl, m_layout); } + + if (auto meta = m_ast_builder.clang().GetMetadata(&m_tag_decl)) { + meta->SetIsDynamicCXXType(meta->GetIsDynamicCXXType().value_or(false) || + m_any_virtual_base); + m_ast_builder.clang().SetMetadata(&m_tag_decl, *meta); + } } uint64_t diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h index 0a6aedefa69e8..54029e1e4d28a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h @@ -53,6 +53,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks { llvm::DenseMap<lldb::opaque_compiler_type_t, llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>> &m_cxx_record_map; + bool m_any_virtual_base = false; public: UdtRecordCompleter( diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 4a637f0817759..54d4d3f26b47a 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -8784,12 +8784,6 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, lldb::DescriptionLevel level) { StreamFile s(stdout, false); DumpTypeDescription(type, s, level); - - CompilerType ct(weak_from_this(), type); - const clang::Type *clang_type = ClangUtil::GetQualType(ct).getTypePtr(); - if (std::optional<ClangASTMetadata> metadata = GetMetadata(clang_type)) { - metadata->Dump(&s); - } } void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, @@ -8878,7 +8872,24 @@ void TypeSystemClang::DumpTypeDescription(lldb::opaque_compiler_type_t type, if (buf.size() > 0) { s.Write(buf.data(), buf.size()); } -} + + if (level == eDescriptionLevelVerbose) { + std::optional<ClangASTMetadata> metadata = + GetMetadata(qual_type.getTypePtr()); + if (metadata) { + s << "type-metadata = "; + metadata->Dump(&s); + } + + if (const clang::TagDecl *tag = qual_type->getAsTagDecl()) + metadata = GetMetadata(tag); + + if (metadata) { + s << "decl-metadata = "; + metadata->Dump(&s); + } + } + } } void TypeSystemClang::DumpTypeName(const CompilerType &type) { diff --git a/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp new file mode 100644 index 0000000000000..576a601c7190e --- /dev/null +++ b/lldb/test/Shell/SymbolFile/NativePDB/dynamic-types.cpp @@ -0,0 +1,43 @@ +// clang-format off +// REQUIRES: lld, x86 + +// RUN: %clang_cl --target=x86_64-windows-msvc -Od -GS- -GR- -std:c++20 -Z7 -c /Fo%t.obj -- %s +// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb + +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=Base %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingBase %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingVBase %t.exe | FileCheck %s --check-prefix=DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=UsingUsingVBase %t.exe | FileCheck %s --check-prefix=DYNAMIC + +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=VBase %t.exe | FileCheck %s --check-prefix=NOT-DYNAMIC +// RUN: lldb-test symbols --dump-clang-ast --find=type --name=NotDynamic %t.exe | FileCheck %s --check-prefix=NOT-DYNAMIC + +// DYNAMIC: Found 1 types: +// DYNAMIC: decl-metadata = uid={{.*}} is_dynamic_cxx=true + +// NOT-DYNAMIC: Found 1 types: +// NOT-DYNAMIC: decl-metadata = uid={{.*}} is_dynamic_cxx=false + +struct Base { + virtual ~Base() = default; +}; + +struct UsingBase : public Base {}; + +struct VBase {}; + +struct UsingVBase : public virtual VBase {}; + +struct UsingUsingVBase : public UsingVBase {}; + +struct NotDynamic : public VBase {}; + +void operator delete(void *, unsigned __int64 i) throw() {} + +int main() { + UsingBase ub; + UsingVBase uvb; + UsingUsingVBase uuvb; + NotDynamic nd; + return 0; +} _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
