Skip to content

Conversation

@Nerixyz
Copy link
Contributor

@Nerixyz Nerixyz commented Nov 6, 2025

We used to search for constants using the name we parsed. For C++, this would mean using the demangled struct name (from the unique name). This name is not always equal to the one used for the struct's name by the compiler. For example:

  0x105E | LF_STRUCTURE [size = 120, hash = 0xF38F] ``anonymous namespace'::Anonymous<A::B::C<void> >::D`
           unique name: `.?AUD@?$Anonymous@U?$C@X@B@A@@@?A0x8C295248@@`

We would use the unique name and get to (anonymous namespace)::Anonymous<struct A::B::C<void>>::D. Then, when finding the constant in the field list, we'd search for (anonymous namespace)::Anonymous<struct A::B::C<void>>::D::StaticMember. This wouldn't yield any results, because the constant will use the demangled name as given by the compiler.

With this PR, we use the struct's name as given in the PDB and append the member name.

@Nerixyz Nerixyz requested a review from ZequanWu November 6, 2025 20:54
@Nerixyz Nerixyz requested a review from JDevlieghere as a code owner November 6, 2025 20:54
@llvmbot llvmbot added the lldb label Nov 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 6, 2025

@llvm/pr-subscribers-lldb

Author: nerix (Nerixyz)

Changes

We used to search for constants using the name we parsed. For C++, this would mean using the demangled struct name (from the unique name). This name is not always equal to the one used for the struct's name by the compiler. For example:

  0x105E | LF_STRUCTURE [size = 120, hash = 0xF38F] ``anonymous namespace'::Anonymous&lt;A::B::C&lt;void&gt; &gt;::D`
           unique name: `.?AUD@?$Anonymous@<!-- -->U?$C@<!-- -->X@<!-- -->B@<!-- -->A@@@?A0x8C295248@@`

We would use the unique name and get to (anonymous namespace)::Anonymous&lt;struct A::B::C&lt;void&gt;&gt;::D. Then, when finding the constant in the field list, we'd search for (anonymous namespace)::Anonymous&lt;struct A::B::C&lt;void&gt;&gt;::D::StaticMember. This wouldn't yield any results, because the constant will use the demangled name as given by the compiler.

With this PR, we use the struct's name as given in the PDB and append the member name.


Full diff: https://github.com/llvm/llvm-project/pull/166845.diff

2 Files Affected:

  • (modified) lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp (+7-1)
  • (modified) lldb/test/Shell/SymbolFile/NativePDB/ast-types.cpp (+4-1)
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;
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants