[Lldb-commits] [lldb] [LLDB][NativePDB] Set IsDynmaicCXXType metadata for records (PR #155853)

via lldb-commits lldb-commits at lists.llvm.org
Sat Aug 8 06:56:50 PDT 2026


https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/155853

>From 8c8271891df15699c6a13d3280e011206e407c70 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
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          | 19 +++++---
 .../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, 89 insertions(+), 21 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..ca02b298f9f4d 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilderClang.cpp
@@ -695,17 +695,24 @@ PdbAstBuilderClang::CreateModifierType(const ModifierRecord &modifier) {
 }
 
 clang::QualType PdbAstBuilderClang::CreateRecordType(PdbTypeSymId id,
-                                                     const TagRecord &record) {
+                                                     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 +895,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;
+}



More information about the lldb-commits mailing list