https://github.com/Michael137 updated 
https://github.com/llvm/llvm-project/pull/152134

>From d8d8e1dccecb941ff44cd820c0a8f6f238ec6726 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Tue, 5 Aug 2025 17:37:39 +0100
Subject: [PATCH] [lldb][CPlusPlusLanguage] Create public accessors for getting
 DemangledNameInfo components and use them in tests

This way we make sure that the logic to reconstruct demangled names in the 
tests is the same as the logic when reconstructing the actual frame-format 
variable.

`DemangledNameInfo::SuffixRange` is currently the only one which we can't test 
in the same way until we set it from inside the `TrackingOutputBuffer`. I added 
TODOs to track this.
---
 lldb/source/Core/Mangled.cpp                  |   1 +
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  | 132 +++++++++++++-----
 .../Language/CPlusPlus/CPlusPlusLanguage.h    |  26 ++++
 lldb/unittests/Core/MangledTest.cpp           |  56 +++++---
 4 files changed, 161 insertions(+), 54 deletions(-)

diff --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index 0027bfaeda4f7..3663f430111c2 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -172,6 +172,7 @@ GetItaniumDemangledStr(const char *M) {
 
     TrackingOutputBuffer OB(demangled_cstr, demangled_size);
     demangled_cstr = ipd.finishDemangle(&OB);
+    // TODO: we should set the SuffixRange inside the TrackingOutputBuffer.
     OB.NameInfo.SuffixRange.first = OB.NameInfo.QualifiersRange.second;
     OB.NameInfo.SuffixRange.second = std::string_view(OB).size();
     info = std::move(OB.NameInfo);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 3353d5a898898..3bc870810dc81 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Demangle/ItaniumDemangle.h"
 
+#include "lldb/Core/DemangledNameInfo.h"
 #include "lldb/Core/Mangled.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
@@ -271,8 +272,25 @@ GetDemangledBasename(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  return demangled_name.slice(info.BasenameRange.first,
-                              info.BasenameRange.second);
+  return CPlusPlusLanguage::GetDemangledBasename(demangled_name, info);
+}
+
+llvm::StringRef
+CPlusPlusLanguage::GetDemangledBasename(llvm::StringRef demangled,
+                                        const DemangledNameInfo &info) {
+  assert(info.hasBasename());
+  return demangled.slice(info.BasenameRange.first, info.BasenameRange.second);
+}
+
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledTemplateArguments(
+    llvm::StringRef demangled, const DemangledNameInfo &info) {
+  if (!info.hasTemplateArguments())
+    return llvm::createStringError(
+        "Template arguments range for '%s' is invalid.", demangled.data());
+
+  return demangled.slice(info.TemplateArgumentsRange.first,
+                         info.TemplateArgumentsRange.second);
 }
 
 static llvm::Expected<llvm::StringRef>
@@ -283,12 +301,17 @@ GetDemangledTemplateArguments(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  if (!info.hasTemplateArguments())
+  return CPlusPlusLanguage::GetDemangledTemplateArguments(demangled_name, 
info);
+}
+
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledReturnTypeLHS(llvm::StringRef demangled,
+                                             const DemangledNameInfo &info) {
+  if (info.ScopeRange.first >= demangled.size())
     return llvm::createStringError(
-        "Template arguments range for '%s' is invalid.", 
demangled_name.data());
+        "Scope range for '%s' LHS return type is invalid.", demangled.data());
 
-  return demangled_name.slice(info.TemplateArgumentsRange.first,
-                              info.TemplateArgumentsRange.second);
+  return demangled.substr(0, info.ScopeRange.first);
 }
 
 static llvm::Expected<llvm::StringRef>
@@ -299,12 +322,18 @@ GetDemangledReturnTypeLHS(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  if (info.ScopeRange.first >= demangled_name.size())
-    return llvm::createStringError(
-        "Scope range for '%s' LHS return type is invalid.",
-        demangled_name.data());
+  return CPlusPlusLanguage::GetDemangledReturnTypeLHS(demangled_name, info);
+}
+
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledFunctionQualifiers(
+    llvm::StringRef demangled, const DemangledNameInfo &info) {
+  if (!info.hasQualifiers())
+    return llvm::createStringError("Qualifiers range for '%s' is invalid.",
+                                   demangled.data());
 
-  return demangled_name.substr(0, info.ScopeRange.first);
+  return demangled.slice(info.QualifiersRange.first,
+                         info.QualifiersRange.second);
 }
 
 static llvm::Expected<llvm::StringRef>
@@ -315,12 +344,20 @@ GetDemangledFunctionQualifiers(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  if (!info.hasQualifiers())
-    return llvm::createStringError("Qualifiers range for '%s' is invalid.",
-                                   demangled_name.data());
+  return CPlusPlusLanguage::GetDemangledFunctionQualifiers(demangled_name,
+                                                           info);
+}
 
-  return demangled_name.slice(info.QualifiersRange.first,
-                              info.QualifiersRange.second);
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledReturnTypeRHS(llvm::StringRef demangled,
+                                             const DemangledNameInfo &info) {
+  if (info.QualifiersRange.first < info.ArgumentsRange.second)
+    return llvm::createStringError(
+        "Qualifiers range for '%s' RHS return type  is invalid.",
+        demangled.data());
+
+  return demangled.slice(info.ArgumentsRange.second,
+                         info.QualifiersRange.first);
 }
 
 static llvm::Expected<llvm::StringRef>
@@ -331,13 +368,17 @@ GetDemangledReturnTypeRHS(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  if (info.QualifiersRange.first < info.ArgumentsRange.second)
-    return llvm::createStringError(
-        "Qualifiers range for '%s' RHS return type  is invalid.",
-        demangled_name.data());
+  return CPlusPlusLanguage::GetDemangledReturnTypeRHS(demangled_name, info);
+}
 
-  return demangled_name.slice(info.ArgumentsRange.second,
-                              info.QualifiersRange.first);
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledScope(llvm::StringRef demangled,
+                                     const DemangledNameInfo &info) {
+  if (!info.hasScope())
+    return llvm::createStringError("Scope range for '%s' is invalid.",
+                                   demangled.data());
+
+  return demangled.slice(info.ScopeRange.first, info.ScopeRange.second);
 }
 
 static llvm::Expected<llvm::StringRef>
@@ -348,15 +389,16 @@ GetDemangledScope(const SymbolContext &sc) {
 
   auto [demangled_name, info] = *info_or_err;
 
-  if (!info.hasScope())
-    return llvm::createStringError("Scope range for '%s' is invalid.",
-                                   demangled_name.data());
-
-  return demangled_name.slice(info.ScopeRange.first, info.ScopeRange.second);
+  return CPlusPlusLanguage::GetDemangledScope(demangled_name, info);
 }
 
 /// Handles anything printed after the FunctionEncoding ItaniumDemangle
-/// node. Most notably the DotSUffix node.
+/// node. Most notably the DotSuffix node.
+///
+/// FIXME: the suffix should also have an associated
+/// CPlusPlusLanguage::GetDemangledFunctionSuffix
+/// once we start setting the `DemangledNameInfo::SuffixRange`
+/// from inside the `TrackingOutputBuffer`.
 static llvm::Expected<llvm::StringRef>
 GetDemangledFunctionSuffix(const SymbolContext &sc) {
   auto info_or_err = GetAndValidateInfo(sc);
@@ -372,6 +414,16 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) {
   return demangled_name.slice(info.SuffixRange.first, info.SuffixRange.second);
 }
 
+llvm::Expected<llvm::StringRef>
+CPlusPlusLanguage::GetDemangledFunctionArguments(
+    llvm::StringRef demangled, const DemangledNameInfo &info) {
+  if (!info.hasArguments())
+    return llvm::createStringError(
+        "Function arguments range for '%s' is invalid.", demangled.data());
+
+  return demangled.slice(info.ArgumentsRange.first, 
info.ArgumentsRange.second);
+}
+
 static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {
   assert(sc.symbol);
 
@@ -382,13 +434,19 @@ static bool PrintDemangledArgumentList(Stream &s, const 
SymbolContext &sc) {
                    "frame-format variable: {0}");
     return false;
   }
+
   auto [demangled_name, info] = *info_or_err;
 
-  if (!info.hasArguments())
+  auto args_or_err =
+      CPlusPlusLanguage::GetDemangledFunctionArguments(demangled_name, info);
+  if (!args_or_err) {
+    LLDB_LOG_ERROR(GetLog(LLDBLog::Language), args_or_err.takeError(),
+                   "Failed to handle ${{function.formatted-arguments}} "
+                   "frame-format variable: {0}");
     return false;
+  }
 
-  s << demangled_name.slice(info.ArgumentsRange.first,
-                            info.ArgumentsRange.second);
+  s << *args_or_err;
 
   return true;
 }
@@ -2261,7 +2319,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
     FormatEntity::Entry::Type type, Stream &s) {
   switch (type) {
   case FormatEntity::Entry::Type::FunctionScope: {
-    auto scope_or_err = GetDemangledScope(sc);
+    auto scope_or_err = ::GetDemangledScope(sc);
     if (!scope_or_err) {
       LLDB_LOG_ERROR(
           GetLog(LLDBLog::Language), scope_or_err.takeError(),
@@ -2275,7 +2333,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
   }
 
   case FormatEntity::Entry::Type::FunctionBasename: {
-    auto name_or_err = GetDemangledBasename(sc);
+    auto name_or_err = ::GetDemangledBasename(sc);
     if (!name_or_err) {
       LLDB_LOG_ERROR(
           GetLog(LLDBLog::Language), name_or_err.takeError(),
@@ -2289,7 +2347,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
   }
 
   case FormatEntity::Entry::Type::FunctionTemplateArguments: {
-    auto template_args_or_err = GetDemangledTemplateArguments(sc);
+    auto template_args_or_err = ::GetDemangledTemplateArguments(sc);
     if (!template_args_or_err) {
       LLDB_LOG_ERROR(GetLog(LLDBLog::Language),
                      template_args_or_err.takeError(),
@@ -2327,7 +2385,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
     return true;
   }
   case FormatEntity::Entry::Type::FunctionReturnRight: {
-    auto return_rhs_or_err = GetDemangledReturnTypeRHS(sc);
+    auto return_rhs_or_err = ::GetDemangledReturnTypeRHS(sc);
     if (!return_rhs_or_err) {
       LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_rhs_or_err.takeError(),
                      "Failed to handle ${{function.return-right}} frame-format 
"
@@ -2340,7 +2398,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
     return true;
   }
   case FormatEntity::Entry::Type::FunctionReturnLeft: {
-    auto return_lhs_or_err = GetDemangledReturnTypeLHS(sc);
+    auto return_lhs_or_err = ::GetDemangledReturnTypeLHS(sc);
     if (!return_lhs_or_err) {
       LLDB_LOG_ERROR(GetLog(LLDBLog::Language), return_lhs_or_err.takeError(),
                      "Failed to handle ${{function.return-left}} frame-format "
@@ -2353,7 +2411,7 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
     return true;
   }
   case FormatEntity::Entry::Type::FunctionQualifiers: {
-    auto quals_or_err = GetDemangledFunctionQualifiers(sc);
+    auto quals_or_err = ::GetDemangledFunctionQualifiers(sc);
     if (!quals_or_err) {
       LLDB_LOG_ERROR(GetLog(LLDBLog::Language), quals_or_err.takeError(),
                      "Failed to handle ${{function.qualifiers}} frame-format "
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 22acdf3e8efe9..4f449f11257a6 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -112,6 +112,32 @@ class CPlusPlusLanguage : public Language {
 
   static bool IsCPPMangledName(llvm::StringRef name);
 
+  static llvm::StringRef GetDemangledBasename(llvm::StringRef demangled,
+                                              const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledTemplateArguments(llvm::StringRef demangled,
+                                const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledReturnTypeLHS(llvm::StringRef demangled,
+                            const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledFunctionQualifiers(llvm::StringRef demangled,
+                                 const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledScope(llvm::StringRef demangled, const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledReturnTypeRHS(llvm::StringRef demangled,
+                            const DemangledNameInfo &info);
+
+  static llvm::Expected<llvm::StringRef>
+  GetDemangledFunctionArguments(llvm::StringRef demangled,
+                                const DemangledNameInfo &info);
+
   // Extract C++ context and identifier from a string using heuristic matching
   // (as opposed to
   // CPlusPlusLanguage::CxxMethodName which has to have a fully qualified C++
diff --git a/lldb/unittests/Core/MangledTest.cpp 
b/lldb/unittests/Core/MangledTest.cpp
index eecef033aa349..a6e6e75fde145 100644
--- a/lldb/unittests/Core/MangledTest.cpp
+++ b/lldb/unittests/Core/MangledTest.cpp
@@ -6,6 +6,7 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
 #include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
 #include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
 #include "TestingSupport/SubsystemRAII.h"
@@ -19,6 +20,7 @@
 #include "lldb/Host/HostInfo.h"
 #include "lldb/Symbol/SymbolContext.h"
 
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
@@ -852,25 +854,45 @@ TEST_P(DemanglingInfoCorrectnessTestFixutre, Correctness) 
{
 
   auto tracked_name = llvm::StringRef(*OB);
 
-  auto return_left = tracked_name.slice(0, OB->NameInfo.ScopeRange.first);
-  auto scope = tracked_name.slice(OB->NameInfo.ScopeRange.first,
-                                  OB->NameInfo.ScopeRange.second);
-  auto basename = tracked_name.slice(OB->NameInfo.BasenameRange.first,
-                                     OB->NameInfo.BasenameRange.second);
-  auto template_args = tracked_name.slice(OB->NameInfo.BasenameRange.second,
-                                          OB->NameInfo.ArgumentsRange.first);
-  auto args = tracked_name.slice(OB->NameInfo.ArgumentsRange.first,
-                                 OB->NameInfo.ArgumentsRange.second);
-  auto return_right = tracked_name.slice(OB->NameInfo.ArgumentsRange.second,
-                                         OB->NameInfo.QualifiersRange.first);
-  auto qualifiers = tracked_name.slice(OB->NameInfo.QualifiersRange.first,
-                                       OB->NameInfo.QualifiersRange.second);
+  std::string reconstructed_name;
+
+  auto return_left =
+      CPlusPlusLanguage::GetDemangledReturnTypeLHS(tracked_name, OB->NameInfo);
+  EXPECT_THAT_EXPECTED(return_left, llvm::Succeeded());
+  reconstructed_name += *return_left;
+
+  auto scope = CPlusPlusLanguage::GetDemangledScope(tracked_name, 
OB->NameInfo);
+  EXPECT_THAT_EXPECTED(scope, llvm::Succeeded());
+  reconstructed_name += *scope;
+
+  auto basename =
+      CPlusPlusLanguage::GetDemangledBasename(tracked_name, OB->NameInfo);
+  reconstructed_name += basename;
+
+  auto template_args = CPlusPlusLanguage::GetDemangledTemplateArguments(
+      tracked_name, OB->NameInfo);
+  EXPECT_THAT_EXPECTED(template_args, llvm::Succeeded());
+  reconstructed_name += *template_args;
+
+  auto args = CPlusPlusLanguage::GetDemangledFunctionArguments(tracked_name,
+                                                               OB->NameInfo);
+  EXPECT_THAT_EXPECTED(args, llvm::Succeeded());
+  reconstructed_name += *args;
+
+  auto return_right =
+      CPlusPlusLanguage::GetDemangledReturnTypeRHS(tracked_name, OB->NameInfo);
+  EXPECT_THAT_EXPECTED(return_right, llvm::Succeeded());
+  reconstructed_name += *return_right;
+
+  auto qualifiers = CPlusPlusLanguage::GetDemangledFunctionQualifiers(
+      tracked_name, OB->NameInfo);
+  EXPECT_THAT_EXPECTED(qualifiers, llvm::Succeeded());
+  reconstructed_name += *qualifiers;
+
+  // TODO: should retrieve suffix using the plugin too.
   auto suffix = tracked_name.slice(OB->NameInfo.QualifiersRange.second,
                                    llvm::StringRef::npos);
-
-  auto reconstructed_name =
-      llvm::join_items("", return_left, scope, basename, template_args, args,
-                       return_right, qualifiers, suffix);
+  reconstructed_name += suffix;
 
   EXPECT_EQ(reconstructed_name, demangled);
 }

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to