https://github.com/Nerixyz created 
https://github.com/llvm/llvm-project/pull/196509

`CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments` didn't support 
demangled names from the Microsoft ABI.

For one, the mangled name was ignored (only Itanium was supported). Secondly, 
`CPlusPlusNameParser` didn't account for `class`/`struct` being in type names.

This needs more tests, and maybe it should be split into two PRs.

>From a6cb684f22e14de1c3087f08f31d11baa0e455af Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Fri, 8 May 2026 13:00:26 +0200
Subject: [PATCH] [lldb] Support parsing MS demangled names

---
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  | 68 ++++++++++++++-----
 .../CPlusPlus/CPlusPlusNameParser.cpp         | 14 ++++
 .../CPlusPlus/CPlusPlusLanguageTest.cpp       |  4 ++
 3 files changed, 68 insertions(+), 18 deletions(-)

diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 7e68d25c0110f..20fc95ad2f123 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -111,28 +111,60 @@ bool CPlusPlusLanguage::SymbolNameFitsToLanguage(const 
Mangled &mangled) const {
          mangling_scheme == Mangled::eManglingSchemeMSVC;
 }
 
+static bool IsPossibleMangledFunction(llvm::StringRef name) {
+  // Itanium
+  if (name.starts_with("_Z")) {
+    return name.size() >= 3 &&
+           name[2] != 'T' && // avoid virtual table, VTT structure,
+                             // typeinfo structure, and typeinfo
+                             // mangled_name
+           name[2] != 'G' && // avoid guard variables
+           name[2] != 'Z';   // named local entities (if we
+                             // eventually handle eSymbolTypeData,
+                             // we will want this back)
+  }
+  // Microsoft
+  if (name.starts_with('?')) {
+    // Avoid any special intrinsics. This matches consumeSpecialIntrinsicKind()
+    // from MicrosoftDemangle.
+    if (name.size() < 4 || name[1] != '?' || name[2] != '_')
+      return true;
+
+    switch (name[3]) {
+    case '7': // vftable
+    case '8': // vbtable
+    case '9': // vcall thunk
+    case 'A': // typeof
+    case 'B': // local static guard
+    case 'C': // string literal symbol
+    case 'P': // udt returning
+    case 'R': // rtti
+    case 'S': // local vftable
+      return false;
+    case '_':
+      return name.size() < 5 || name[4] != 'E' || // dynamic initializer
+             name[4] != 'F' ||                    // dynamic atexit destructor
+             name[4] != 'J';                      // local static thread guard
+    }
+    return true;
+  }
+
+  return false;
+}
+
 ConstString CPlusPlusLanguage::GetDemangledFunctionNameWithoutArguments(
     Mangled mangled) const {
   const char *mangled_name_cstr = mangled.GetMangledName().GetCString();
   ConstString demangled_name = mangled.GetDemangledName();
-  if (demangled_name && mangled_name_cstr && mangled_name_cstr[0]) {
-    if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
-        (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,
-                                        // typeinfo structure, and typeinfo
-                                        // mangled_name
-         mangled_name_cstr[2] != 'G' && // avoid guard variables
-         mangled_name_cstr[2] != 'Z'))  // named local entities (if we
-                                        // eventually handle eSymbolTypeData,
-                                        // we will want this back)
-    {
-      CxxMethodName cxx_method(demangled_name);
-      if (!cxx_method.GetBasename().empty()) {
-        std::string shortname;
-        if (!cxx_method.GetContext().empty())
-          shortname = cxx_method.GetContext().str() + "::";
-        shortname += cxx_method.GetBasename().str();
-        return ConstString(shortname);
-      }
+  if (demangled_name && mangled_name_cstr &&
+      IsPossibleMangledFunction(mangled_name_cstr)) {
+    CxxMethodName cxx_method(demangled_name);
+    if (!cxx_method.GetBasename().empty()) {
+      std::string shortname;
+      if (!cxx_method.GetContext().empty())
+        shortname = cxx_method.GetContext().str() + "::";
+      shortname += cxx_method.GetBasename().str();
+      return ConstString(shortname);
     }
   }
   if (demangled_name)
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
index 4d283bb02e533..0d2e19013b64a 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp
@@ -700,6 +700,20 @@ CPlusPlusNameParser::ParseFullNameImpl() {
         continue_parsing = false;
       }
       break;
+    case tok::kw_class:
+    case tok::kw_struct: // MS ABI: class Foo::Bar
+      if (state != State::Beginning) {
+        continue_parsing = false;
+        break;
+      }
+      Advance();
+      if (ConsumeToken(tok::raw_identifier)) {
+        state = State::AfterIdentifier;
+      } else {
+        TakeBack();
+        continue_parsing = false;
+      }
+      break;
     default:
       continue_parsing = false;
       break;
diff --git a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp 
b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
index 41df35f67a790..3ed79a024a18e 100644
--- a/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ b/lldb/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -34,6 +34,10 @@ TEST(CPlusPlusLanguage, MethodNameParsing) {
        "foo::bar"},
       {"int foo::bar::func01(int a, double b)", "int", "foo::bar", "func01",
        "(int a, double b)", "", "foo::bar::func01"},
+      {"class std::_Func_base<bool, int> * std::_Func_class<bool, "
+       "int>::_Getimpl(void) const",
+       "class std::_Func_base<bool, int> *", "std::_Func_class<bool, int>",
+       "_Getimpl", "(void)", "const", "std::_Func_class<bool, int>::_Getimpl"},
 
       // Operators
       {"std::basic_ostream<char, std::char_traits<char> >& "

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to