[Lldb-commits] [lldb] [LLDB][NativePDB] Use original struct name when searching for constants (PR #166845)

via lldb-commits lldb-commits at lists.llvm.org
Wed Dec 10 08:35:47 PST 2025


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

>From 7566542a194db8d8516432e0213d4f9d43aa488d Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Thu, 6 Nov 2025 21:45:05 +0100
Subject: [PATCH 1/3] [LLDB][NativePDB] Use original struct name when searching
 for constants

---
 .../Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp   | 8 +++++++-
 lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp        | 5 ++++-
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index 46cf9b8524ede..bfaba7f91b711 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -168,7 +168,13 @@ Error UdtRecordCompleter::visitKnownMember(
   // Static constant members may be a const[expr] declaration.
   // Query the symbol's value as the variable initializer if valid.
   if (member_ct.IsConst() && member_ct.IsCompleteType()) {
-    std::string qual_name = decl->getQualifiedNameAsString();
+    std::string qual_name;
+    if (m_record.record.kind == Member::Struct)
+      qual_name = (m_cvr.cr.Name + "::" + static_data_member.Name).str();
+    else if (m_record.record.kind == Member::Union)
+      qual_name = (m_cvr.ur.Name + "::" + static_data_member.Name).str();
+    else
+      qual_name = decl->getQualifiedNameAsString();
 
     auto results =
         m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
index ac0d87e95dbf9..4b267c398e766 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
@@ -56,6 +56,7 @@ namespace {
     int AnonymousMember;
     // And a nested class within an anonymous namespace
     struct D {
+      static constexpr int StaticMember = 1;
       int AnonymousDMember;
     };
   };
@@ -177,6 +178,8 @@ int SI::*mp9 = nullptr;
 // CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition
 // CHECK: |   |-FieldDecl {{.*}} AnonymousMember 'int'
 // CHECK: |   `-CXXRecordDecl {{.*}} struct D definition
+// CHECK: |     |-VarDecl {{.*}} StaticMember 'const int' static cinit
+// CHECK: |     | `-IntegerLiteral {{.*}} 'int' 1
 // CHECK: |     `-FieldDecl {{.*}} AnonymousDMember 'int'
 
 int main(int argc, char **argv) {
@@ -184,5 +187,5 @@ int main(int argc, char **argv) {
   AnonABCVoid.AnonymousMember = 2;
   AnonABCVoidD.AnonymousDMember = 3;
 
-  return 0;
+  return AnonABCVoidD.StaticMember;
 }

>From be1123fa94dee98e2a01293cbed7245b56ba7d33 Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 10 Dec 2025 17:35:04 +0100
Subject: [PATCH 2/3] refactor: use `CVTagRecord` to store the record

---
 .../NativePDB/UdtRecordCompleter.cpp          | 38 +++++++------------
 .../SymbolFile/NativePDB/UdtRecordCompleter.h |  9 +----
 2 files changed, 16 insertions(+), 31 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
index bfaba7f91b711..8ab06e09b024e 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -41,30 +41,22 @@ UdtRecordCompleter::UdtRecordCompleter(
     llvm::DenseMap<lldb::opaque_compiler_type_t,
                    llvm::SmallSet<std::pair<llvm::StringRef, CompilerType>, 8>>
         &cxx_record_map)
-    : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
+    : m_cv_tag_record(CVTagRecord::create(index.tpi().getType(id.index))),
+      m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
       m_ast_builder(ast_builder), m_index(index),
       m_decl_to_status(decl_to_status), m_cxx_record_map(cxx_record_map) {
-  CVType cvt = m_index.tpi().getType(m_id.index);
-  switch (cvt.kind()) {
-  case LF_ENUM:
-    m_cvr.er.Options = ClassOptions::None;
-    llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
+  switch (m_cv_tag_record.kind()) {
+  case CVTagRecord::Enum:
     break;
-  case LF_UNION:
-    m_cvr.ur.Options = ClassOptions::None;
-    llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
-    m_layout.bit_size = m_cvr.ur.getSize() * 8;
+  case CVTagRecord::Union:
+    m_layout.bit_size = m_cv_tag_record.asUnion().getSize() * 8;
     m_record.record.kind = Member::Union;
     break;
-  case LF_CLASS:
-  case LF_STRUCTURE:
-    m_cvr.cr.Options = ClassOptions::None;
-    llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
-    m_layout.bit_size = m_cvr.cr.getSize() * 8;
+  case CVTagRecord::Class:
+  case CVTagRecord::Struct:
+    m_layout.bit_size = m_cv_tag_record.asClass().getSize() * 8;
     m_record.record.kind = Member::Struct;
     break;
-  default:
-    llvm_unreachable("unreachable!");
   }
 }
 
@@ -168,13 +160,11 @@ Error UdtRecordCompleter::visitKnownMember(
   // Static constant members may be a const[expr] declaration.
   // Query the symbol's value as the variable initializer if valid.
   if (member_ct.IsConst() && member_ct.IsCompleteType()) {
-    std::string qual_name;
-    if (m_record.record.kind == Member::Struct)
-      qual_name = (m_cvr.cr.Name + "::" + static_data_member.Name).str();
-    else if (m_record.record.kind == Member::Union)
-      qual_name = (m_cvr.ur.Name + "::" + static_data_member.Name).str();
-    else
-      qual_name = decl->getQualifiedNameAsString();
+    // Reconstruct the full name for the static member. Use the names as given
+    // in the PDB. This ensures we match the compiler's style of names (e.g.
+    // "A<B<int> >::Foo" vs "A<B<int>>::Foo").
+    std::string qual_name =
+        (m_cv_tag_record.name() + "::" + static_data_member.Name).str();
 
     auto results =
         m_index.globals().findRecordsByName(qual_name, m_index.symrecords());
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
index e6e91d0f2c3e4..73c45456899e4 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
@@ -11,6 +11,7 @@
 
 #include "PdbAstBuilder.h"
 #include "PdbSymUid.h"
+#include "PdbUtil.h"
 #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
@@ -41,13 +42,7 @@ class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks {
   using IndexedBase =
       std::pair<uint64_t, std::unique_ptr<clang::CXXBaseSpecifier>>;
 
-  union UdtTagRecord {
-    UdtTagRecord() {}
-    llvm::codeview::UnionRecord ur;
-    llvm::codeview::ClassRecord cr;
-    llvm::codeview::EnumRecord er;
-  } m_cvr;
-
+  CVTagRecord m_cv_tag_record;
   PdbTypeSymId m_id;
   CompilerType &m_derived_ct;
   clang::TagDecl &m_tag_decl;

>From 3aade9c0a43ae3c880743ac461d98c9e7615f41b Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Wed, 10 Dec 2025 17:35:27 +0100
Subject: [PATCH 3/3] test: Add check for static member in union

---
 .../NativePDB/Inputs/ast-types.lldbinit       |  1 +
 .../Shell/SymbolFile/NativePDB/ast-types.cpp  | 23 +++++++++++++++----
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
index a79d18fcfbe70..5062faa97db00 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
+++ b/lldb/test/Shell/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
@@ -19,6 +19,7 @@ target variable ADE
 target variable AnonInt
 target variable AnonABCVoid
 target variable AnonABCVoidD
+target variable AnonABCVoidU
 
 target variable mp1 mp2 mp3 mp4 mp5 mp6 mp7 mp8 mp9
 
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
index 4b267c398e766..e3af6d21893a7 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp
@@ -59,6 +59,11 @@ namespace {
       static constexpr int StaticMember = 1;
       int AnonymousDMember;
     };
+
+    union U {
+      static constexpr int StaticMember = 2;
+      int AnonymousUMember;
+    };
   };
 }
 
@@ -86,6 +91,7 @@ A::D::E ADE;
 Anonymous<int> AnonInt;
 Anonymous<A::B::C<void>> AnonABCVoid;
 Anonymous<A::B::C<void>>::D AnonABCVoidD;
+Anonymous<A::B::C<void>>::U AnonABCVoidU;
 
 // The following tests that MSInheritanceAttr are set for record decls.
 class  SI { int si; };
@@ -132,6 +138,7 @@ int SI::*mp9 = nullptr;
 // CHECK: (Anonymous<int>) AnonInt = (AnonymousMember = 0)
 // CHECK: (Anonymous<A::B::C<void>>) AnonABCVoid = (AnonymousMember = 0)
 // CHECK: (Anonymous<A::B::C<void>>::D) AnonABCVoidD = (AnonymousDMember = 0)
+// CHECK: (Anonymous<A::B::C<void>>::U) AnonABCVoidU = (AnonymousUMember = 0)
 // CHECK: (void (SI::*)()) mp1 = 0x0000000000000000
 // CHECK: (void (MI::*)()) mp2 = 0x0000000000000000
 // CHECK: (void (MI2::*)()) mp3 = 0x0000000000000000
@@ -177,15 +184,21 @@ int SI::*mp9 = nullptr;
 // CHECK: | | `-FieldDecl {{.*}} AnonymousMember 'int'
 // CHECK: | `-CXXRecordDecl {{.*}} struct Anonymous<A::B::C<void>> definition
 // CHECK: |   |-FieldDecl {{.*}} AnonymousMember 'int'
-// CHECK: |   `-CXXRecordDecl {{.*}} struct D definition
-// CHECK: |     |-VarDecl {{.*}} StaticMember 'const int' static cinit
-// CHECK: |     | `-IntegerLiteral {{.*}} 'int' 1
-// CHECK: |     `-FieldDecl {{.*}} AnonymousDMember 'int'
+// CHECK: |   |-CXXRecordDecl {{.*}} struct D definition
+// CHECK: |   | |-VarDecl {{.*}} StaticMember 'const int' static cinit
+// CHECK: |   | | `-IntegerLiteral {{.*}} 'int' 1
+// CHECK: |   | `-FieldDecl {{.*}} AnonymousDMember 'int'
+// CHECK: |   `-CXXRecordDecl {{.*}} union U definition
+// CHECK: |     |-VarDecl {{.*}} StaticMember 'const int' static
+// CHECK: |     | `-IntegerLiteral {{.*}} 'int' 2
+// CHECK: |     `-FieldDecl {{.*}} AnonymousUMember 'int'
+
 
 int main(int argc, char **argv) {
   AnonInt.AnonymousMember = 1;
   AnonABCVoid.AnonymousMember = 2;
   AnonABCVoidD.AnonymousDMember = 3;
+  AnonABCVoidU.AnonymousUMember = 4;
 
-  return AnonABCVoidD.StaticMember;
+  return AnonABCVoidD.StaticMember + AnonABCVoidU.StaticMember;
 }



More information about the lldb-commits mailing list