Author: Michael Buch
Date: 2025-04-25T10:04:27+01:00
New Revision: 9c830cef3d7c2f1adfadcc0026a73ba2cdbeef05

URL: 
https://github.com/llvm/llvm-project/commit/9c830cef3d7c2f1adfadcc0026a73ba2cdbeef05
DIFF: 
https://github.com/llvm/llvm-project/commit/9c830cef3d7c2f1adfadcc0026a73ba2cdbeef05.diff

LOG: [lldb] Implement TrackingOutputBuffer to track demangled name information 
(#131836)

This patch implements a new `TrackingOutputBuffer` which tracks where the 
scope/basename/arguments begin and end in the demangled string.

The idea that a function name can be decomposed into <scope, base, arguments>. 
The assumption is that given the ranges of those three elements and the 
demangled name, LLDB will be able to to reconstruct the full demangled name. 
The tracking of those ranges is pretty simple. We don’t ever deal with nesting, 
so whenever we recurse into a template argument list or another function type, 
we just stop tracking any positions. Once we recursed out of those, and are 
back to printing the top-level function name, we continue tracking the 
positions.

We introduce a new structure `FunctionNameInfo` that holds all this information 
and is stored in the new `TrackingOutputBuffer` class.

Tests are in `ItaniumDemangleTest.cpp`.

https://github.com/llvm/llvm-project/pull/131836

Added: 
    lldb/include/lldb/Core/DemangledNameInfo.h
    lldb/source/Core/DemangledNameInfo.cpp

Modified: 
    lldb/source/Core/CMakeLists.txt
    lldb/unittests/Core/MangledTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Core/DemangledNameInfo.h 
b/lldb/include/lldb/Core/DemangledNameInfo.h
new file mode 100644
index 0000000000000..51cd152bf79d8
--- /dev/null
+++ b/lldb/include/lldb/Core/DemangledNameInfo.h
@@ -0,0 +1,153 @@
+//===-- DemangledNameInfo.h -------------------------------------*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_CORE_DEMANGLEDNAMEINFO_H
+#define LLDB_CORE_DEMANGLEDNAMEINFO_H
+
+#include "llvm/Demangle/ItaniumDemangle.h"
+#include "llvm/Demangle/Utility.h"
+
+#include <cstddef>
+#include <utility>
+
+namespace lldb_private {
+
+/// Stores information about where certain portions of a demangled
+/// function name begin and end.
+struct DemangledNameInfo {
+  /// A [start, end) pair for the function basename.
+  /// The basename is the name without scope qualifiers
+  /// and without template parameters. E.g.,
+  /// \code{.cpp}
+  ///    void foo::bar<int>::someFunc<float>(int) const &&
+  ///                        ^       ^
+  ///                      start    end
+  /// \endcode
+  std::pair<size_t, size_t> BasenameRange;
+
+  /// A [start, end) pair for the function scope qualifiers.
+  /// E.g., for
+  /// \code{.cpp}
+  ///    void foo::bar<int>::qux<float>(int) const &&
+  ///         ^              ^
+  ///       start           end
+  /// \endcode
+  std::pair<size_t, size_t> ScopeRange;
+
+  /// Indicates the [start, end) of the function argument lits.
+  /// E.g.,
+  /// \code{.cpp}
+  ///    int (*getFunc<float>(float, double))(int, int)
+  ///                        ^              ^
+  ///                      start           end
+  /// \endcode
+  std::pair<size_t, size_t> ArgumentsRange;
+
+  /// Returns \c true if this object holds a valid basename range.
+  bool hasBasename() const {
+    return BasenameRange.first != BasenameRange.second &&
+           BasenameRange.second > 0;
+  }
+
+  friend bool operator==(const DemangledNameInfo &lhs,
+                         const DemangledNameInfo &rhs) {
+    return std::tie(lhs.BasenameRange, lhs.ArgumentsRange, lhs.ScopeRange,
+                    lhs.QualifiersRange) ==
+           std::tie(rhs.BasenameRange, rhs.ArgumentsRange, rhs.ScopeRange,
+                    lhs.QualifiersRange);
+  }
+
+  friend bool operator!=(const DemangledNameInfo &lhs,
+                         const DemangledNameInfo &rhs) {
+    return !(lhs == rhs);
+  }
+};
+
+/// An OutputBuffer which keeps a record of where certain parts of a
+/// demangled name begin/end (e.g., basename, scope, argument list, etc.).
+/// The tracking occurs during printing of the Itanium demangle tree.
+///
+/// Usage:
+/// \code{.cpp}
+///
+/// Node *N = mangling_parser.parseType();
+///
+/// TrackingOutputBuffer buffer;
+/// N->printLeft(OB);
+///
+/// assert (buffer.NameInfo.hasBasename());
+///
+/// \endcode
+struct TrackingOutputBuffer : public llvm::itanium_demangle::OutputBuffer {
+  using OutputBuffer::OutputBuffer;
+
+  /// Holds information about the demangled name that is
+  /// being printed into this buffer.
+  DemangledNameInfo NameInfo;
+
+  void printLeft(const llvm::itanium_demangle::Node &N) override;
+  void printRight(const llvm::itanium_demangle::Node &N) override;
+
+private:
+  void printLeftImpl(const llvm::itanium_demangle::FunctionType &N);
+  void printRightImpl(const llvm::itanium_demangle::FunctionType &N);
+
+  void printLeftImpl(const llvm::itanium_demangle::FunctionEncoding &N);
+  void printRightImpl(const llvm::itanium_demangle::FunctionEncoding &N);
+
+  void printLeftImpl(const llvm::itanium_demangle::NestedName &N);
+  void printLeftImpl(const llvm::itanium_demangle::NameWithTemplateArgs &N);
+
+  /// Called whenever we start printing a function type in the Itanium
+  /// mangling scheme. Examples include \ref FunctionEncoding, \ref
+  /// FunctionType, etc.
+  ///
+  /// \returns A ScopedOverride which will update the nesting depth of
+  /// currently printed function types on destruction.
+  [[nodiscard]] llvm::itanium_demangle::ScopedOverride<unsigned>
+  enterFunctionTypePrinting();
+
+  /// Returns \c true if we're not printing any nested function types,
+  /// just a \ref FunctionEncoding in the Itanium mangling scheme.
+  bool isPrintingTopLevelFunctionType() const;
+
+  /// If this object \ref shouldTrack, then update the end of
+  /// the basename range to the current \c OB position.
+  void updateBasenameEnd();
+
+  /// If this object \ref shouldTrack, then update the beginning
+  /// of the scope range to the current \c OB position.
+  void updateScopeStart();
+
+  /// If this object \ref shouldTrack, then update the end of
+  /// the scope range to the current \c OB position.
+  void updateScopeEnd();
+
+  /// Returns \c true if the members of this object can be
+  /// updated. E.g., when we're printing nested template
+  /// arguments, we don't need to be tracking basename
+  /// locations.
+  bool shouldTrack() const;
+
+  /// Helpers called to track beginning and end of the function
+  /// arguments.
+  void finalizeArgumentEnd();
+  void finalizeStart();
+  void finalizeEnd();
+
+  /// Helper used in the finalize APIs.
+  bool canFinalize() const;
+
+  /// Incremented each time we start printing a function type node
+  /// in the Itanium mangling scheme (e.g., \ref FunctionEncoding
+  /// or \ref FunctionType).
+  unsigned FunctionPrintingDepth = 0;
+};
+} // namespace lldb_private
+
+#endif // LLDB_CORE_DEMANGLEDNAMEINFO_H

diff  --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt
index f09b451ac414d..c4c442dcb2043 100644
--- a/lldb/source/Core/CMakeLists.txt
+++ b/lldb/source/Core/CMakeLists.txt
@@ -27,6 +27,7 @@ add_lldb_library(lldbCore NO_PLUGIN_DEPENDENCIES
   Debugger.cpp
   DebuggerEvents.cpp
   Declaration.cpp
+  DemangledNameInfo.cpp
   Disassembler.cpp
   DumpDataExtractor.cpp
   DumpRegisterValue.cpp

diff  --git a/lldb/source/Core/DemangledNameInfo.cpp 
b/lldb/source/Core/DemangledNameInfo.cpp
new file mode 100644
index 0000000000000..89757032409c2
--- /dev/null
+++ b/lldb/source/Core/DemangledNameInfo.cpp
@@ -0,0 +1,213 @@
+//===-- DemangledNameInfo.cpp 
---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DemangledNameInfo.h"
+
+using namespace llvm::itanium_demangle;
+
+namespace lldb_private {
+
+bool TrackingOutputBuffer::shouldTrack() const {
+  if (!isPrintingTopLevelFunctionType())
+    return false;
+
+  if (isGtInsideTemplateArgs())
+    return false;
+
+  if (NameInfo.ArgumentsRange.first > 0)
+    return false;
+
+  return true;
+}
+
+bool TrackingOutputBuffer::canFinalize() const {
+  if (!isPrintingTopLevelFunctionType())
+    return false;
+
+  if (isGtInsideTemplateArgs())
+    return false;
+
+  if (NameInfo.ArgumentsRange.first == 0)
+    return false;
+
+  return true;
+}
+
+void TrackingOutputBuffer::updateBasenameEnd() {
+  if (!shouldTrack())
+    return;
+
+  NameInfo.BasenameRange.second = getCurrentPosition();
+}
+
+void TrackingOutputBuffer::updateScopeStart() {
+  if (!shouldTrack())
+    return;
+
+  NameInfo.ScopeRange.first = getCurrentPosition();
+}
+
+void TrackingOutputBuffer::updateScopeEnd() {
+  if (!shouldTrack())
+    return;
+
+  NameInfo.ScopeRange.second = getCurrentPosition();
+}
+
+void TrackingOutputBuffer::finalizeArgumentEnd() {
+  if (!canFinalize())
+    return;
+
+  NameInfo.ArgumentsRange.second = getCurrentPosition();
+}
+
+void TrackingOutputBuffer::finalizeStart() {
+  if (!shouldTrack())
+    return;
+
+  NameInfo.ArgumentsRange.first = getCurrentPosition();
+
+  // If nothing has set the end of the basename yet (for example when
+  // printing templates), then the beginning of the arguments is the end of
+  // the basename.
+  if (NameInfo.BasenameRange.second == 0)
+    NameInfo.BasenameRange.second = getCurrentPosition();
+
+  assert(!shouldTrack());
+  assert(canFinalize());
+}
+
+void TrackingOutputBuffer::finalizeEnd() {
+  if (!canFinalize())
+    return;
+
+  if (NameInfo.ScopeRange.first > NameInfo.ScopeRange.second)
+    NameInfo.ScopeRange.second = NameInfo.ScopeRange.first;
+  NameInfo.BasenameRange.first = NameInfo.ScopeRange.second;
+}
+
+ScopedOverride<unsigned> TrackingOutputBuffer::enterFunctionTypePrinting() {
+  return {FunctionPrintingDepth, FunctionPrintingDepth + 1};
+}
+
+bool TrackingOutputBuffer::isPrintingTopLevelFunctionType() const {
+  return FunctionPrintingDepth == 1;
+}
+
+void TrackingOutputBuffer::printLeft(const Node &N) {
+  switch (N.getKind()) {
+  case Node::KFunctionType:
+    printLeftImpl(static_cast<const FunctionType &>(N));
+    break;
+  case Node::KFunctionEncoding:
+    printLeftImpl(static_cast<const FunctionEncoding &>(N));
+    break;
+  case Node::KNestedName:
+    printLeftImpl(static_cast<const NestedName &>(N));
+    break;
+  case Node::KNameWithTemplateArgs:
+    printLeftImpl(static_cast<const NameWithTemplateArgs &>(N));
+    break;
+  default:
+    OutputBuffer::printLeft(N);
+  }
+}
+
+void TrackingOutputBuffer::printRight(const Node &N) {
+  switch (N.getKind()) {
+  case Node::KFunctionType:
+    printRightImpl(static_cast<const FunctionType &>(N));
+    break;
+  case Node::KFunctionEncoding:
+    printRightImpl(static_cast<const FunctionEncoding &>(N));
+    break;
+  default:
+    OutputBuffer::printRight(N);
+  }
+}
+
+void TrackingOutputBuffer::printLeftImpl(const FunctionType &N) {
+  auto Scoped = enterFunctionTypePrinting();
+  OutputBuffer::printLeft(N);
+}
+
+void TrackingOutputBuffer::printRightImpl(const FunctionType &N) {
+  auto Scoped = enterFunctionTypePrinting();
+  OutputBuffer::printRight(N);
+}
+
+void TrackingOutputBuffer::printLeftImpl(const FunctionEncoding &N) {
+  auto Scoped = enterFunctionTypePrinting();
+
+  const Node *Ret = N.getReturnType();
+  if (Ret) {
+    printLeft(*Ret);
+    if (!Ret->hasRHSComponent(*this))
+      *this += " ";
+  }
+
+  updateScopeStart();
+
+  N.getName()->print(*this);
+}
+
+void TrackingOutputBuffer::printRightImpl(const FunctionEncoding &N) {
+  auto Scoped = enterFunctionTypePrinting();
+  finalizeStart();
+
+  printOpen();
+  N.getParams().printWithComma(*this);
+  printClose();
+
+  finalizeArgumentEnd();
+
+  const Node *Ret = N.getReturnType();
+
+  if (Ret)
+    printRight(*Ret);
+
+  auto CVQuals = N.getCVQuals();
+  auto RefQual = N.getRefQual();
+  auto *Attrs = N.getAttrs();
+  auto *Requires = N.getRequires();
+
+  if (CVQuals & QualConst)
+    *this += " const";
+  if (CVQuals & QualVolatile)
+    *this += " volatile";
+  if (CVQuals & QualRestrict)
+    *this += " restrict";
+  if (RefQual == FrefQualLValue)
+    *this += " &";
+  else if (RefQual == FrefQualRValue)
+    *this += " &&";
+  if (Attrs != nullptr)
+    Attrs->print(*this);
+  if (Requires != nullptr) {
+    *this += " requires ";
+    Requires->print(*this);
+  }
+
+  finalizeEnd();
+}
+
+void TrackingOutputBuffer::printLeftImpl(const NestedName &N) {
+  N.Qual->print(*this);
+  *this += "::";
+  updateScopeEnd();
+  N.Name->print(*this);
+  updateBasenameEnd();
+}
+
+void TrackingOutputBuffer::printLeftImpl(const NameWithTemplateArgs &N) {
+  N.Name->print(*this);
+  updateBasenameEnd();
+  N.TemplateArgs->print(*this);
+}
+
+} // namespace lldb_private

diff  --git a/lldb/unittests/Core/MangledTest.cpp 
b/lldb/unittests/Core/MangledTest.cpp
index a3760ba43b3c9..b039299d032dd 100644
--- a/lldb/unittests/Core/MangledTest.cpp
+++ b/lldb/unittests/Core/MangledTest.cpp
@@ -11,6 +11,7 @@
 #include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/TestUtilities.h"
 
+#include "lldb/Core/DemangledNameInfo.h"
 #include "lldb/Core/Mangled.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -319,3 +320,145 @@ TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
   EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
   EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
 }
+
+struct DemanglingPartsTestCase {
+  const char *mangled;
+  DemangledNameInfo expected_info;
+  std::string_view basename;
+  std::string_view scope;
+  bool valid_basename = true;
+};
+
+DemanglingPartsTestCase g_demangling_parts_test_cases[] = {
+    // clang-format off
+   { 
"_ZNVKO3BarIN2ns3QuxIiEEE1CIPFi3FooIS_IiES6_EEE6methodIS6_EENS5_IT_SC_E5InnerIiEESD_SD_",
+     { .BasenameRange = {92, 98}, .ScopeRange = {36, 92}, .ArgumentsRange = { 
108, 158 } },
+     .basename = "method",
+     .scope = "Bar<ns::Qux<int>>::C<int (*)(Foo<Bar<int>, Bar<int>>)>::"
+   },
+   { "_Z7getFuncIfEPFiiiET_",
+     { .BasenameRange = {6, 13}, .ScopeRange = {6, 6}, .ArgumentsRange = { 20, 
27 } },
+     .basename = "getFunc",
+     .scope = ""
+   },
+   { "_ZN1f1b1c1gEv",
+     { .BasenameRange = {9, 10}, .ScopeRange = {0, 9}, .ArgumentsRange = { 10, 
12 } },
+     .basename = "g",
+     .scope = "f::b::c::"
+   },
+   { "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bEEEcvT__EES2_",
+     { .BasenameRange = {45, 48}, .ScopeRange = {38, 45}, .ArgumentsRange = { 
53, 58 } },
+     .basename = "fD1",
+     .scope = "test7::"
+   },
+   { "_ZN5test73fD1IiEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
+     { .BasenameRange = {61, 64}, .ScopeRange = {54, 61}, .ArgumentsRange = { 
69, 79 } },
+     .basename = "fD1",
+     .scope = "test7::"
+   },
+   { 
"_ZN5test7INDT1cE1dINDT1cE1dEEEE3fD1INDT1cE1dINDT1cE1dEEEEEDTcmtlNS_1DEL_ZNS_1bINDT1cE1dEEEEEcvT__EES2_",
+     { .BasenameRange = {120, 123}, .ScopeRange = {81, 120}, .ArgumentsRange = 
{ 155, 168 } },
+     .basename = "fD1",
+     .scope = "test7<decltype(c)::d<decltype(c)::d>>::"
+   },
+   { 
"_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvE5parseIRA29_KcEESE_OT_NS2_8functionIFbiNS0_6detail13parse_event_tERSE_EEEbb",
+     { .BasenameRange = {687, 692}, .ScopeRange = {343, 687}, .ArgumentsRange 
= { 713, 1174 } },
+     .basename = "parse",
+     .scope = "nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, 
std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, 
std::__1::allocator<char>>, bool, long long, unsigned long long, double, 
std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, 
std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::"
+   },
+   { 
"_ZN8nlohmann16json_abi_v3_11_310basic_jsonINSt3__13mapENS2_6vectorENS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEEbxydS8_NS0_14adl_serializerENS4_IhNS8_IhEEEEvEC1EDn",
+     { .BasenameRange = {344, 354}, .ScopeRange = {0, 344}, .ArgumentsRange = 
{ 354, 370 } },
+     .basename = "basic_json",
+     .scope = "nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, 
std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, 
std::__1::allocator<char>>, bool, long long, unsigned long long, double, 
std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, 
std::__1::vector<unsigned char, std::__1::allocator<unsigned char>>, void>::"
+   },
+   { "_Z3fppIiEPFPFvvEiEf",
+     { .BasenameRange = {10, 13}, .ScopeRange = {10, 10}, .ArgumentsRange = { 
18, 25 } },
+     .basename = "fpp",
+     .scope = ""
+   },
+   { "_Z3fppIiEPFPFvvEN2ns3FooIiEEEf",
+     { .BasenameRange = {10, 13}, .ScopeRange = {10, 10}, .ArgumentsRange = { 
18, 25 } },
+     .basename = "fpp",
+     .scope = ""
+   },
+   { "_Z3fppIiEPFPFvPFN2ns3FooIiEENS2_3BarIfE3QuxEEEPFS2_S2_EEf",
+     { .BasenameRange = {10, 13}, .ScopeRange = {10, 10}, .ArgumentsRange = { 
18, 25 } },
+     .basename = "fpp",
+     .scope = ""
+   },
+   { "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvEiEf",
+     { .BasenameRange = {64, 67}, .ScopeRange = {10, 64}, .ArgumentsRange = { 
72, 79 } },
+     .basename = "fpp",
+     .scope = "ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::"
+   },
+   { "_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvvES2_Ef",
+     { .BasenameRange = {64, 67}, .ScopeRange = {10, 64}, .ArgumentsRange = { 
72, 79 } },
+     .basename = "fpp",
+     .scope = "ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::"
+   },
+   { 
"_ZN2ns8HasFuncsINS_3FooINS1_IiE3BarIfE3QuxEEEE3fppIiEEPFPFvPFS2_S5_EEPFS2_S2_EEf",
+     { .BasenameRange = {64, 67}, .ScopeRange = {10, 64}, .ArgumentsRange = { 
72, 79 } },
+     .basename = "fpp",
+     .scope = "ns::HasFuncs<ns::Foo<ns::Foo<int>::Bar<float>::Qux>>::"
+   },
+   { "_ZTV11ImageLoader",
+     { .BasenameRange = {0, 0}, .ScopeRange = {0, 0}, .ArgumentsRange = { 0, 0 
} },
+     .basename = "",
+     .scope = "",
+     .valid_basename = false
+   }
+    // clang-format on
+};
+
+struct DemanglingPartsTestFixture
+    : public ::testing::TestWithParam<DemanglingPartsTestCase> {};
+
+namespace {
+class TestAllocator {
+  llvm::BumpPtrAllocator Alloc;
+
+public:
+  void reset() { Alloc.Reset(); }
+
+  template <typename T, typename... Args> T *makeNode(Args &&...args) {
+    return new (Alloc.Allocate(sizeof(T), alignof(T)))
+        T(std::forward<Args>(args)...);
+  }
+
+  void *allocateNodeArray(size_t sz) {
+    return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
+                          alignof(llvm::itanium_demangle::Node *));
+  }
+};
+} // namespace
+
+TEST_P(DemanglingPartsTestFixture, DemanglingParts) {
+  const auto &[mangled, info, basename, scope, valid_basename] = GetParam();
+
+  llvm::itanium_demangle::ManglingParser<TestAllocator> Parser(
+      mangled, mangled + ::strlen(mangled));
+
+  const auto *Root = Parser.parse();
+
+  ASSERT_NE(nullptr, Root);
+
+  TrackingOutputBuffer OB;
+  Root->print(OB);
+  auto demangled = std::string_view(OB);
+
+  ASSERT_EQ(OB.NameInfo.hasBasename(), valid_basename);
+
+  EXPECT_EQ(OB.NameInfo.BasenameRange, info.BasenameRange);
+  EXPECT_EQ(OB.NameInfo.ScopeRange, info.ScopeRange);
+  EXPECT_EQ(OB.NameInfo.ArgumentsRange, info.ArgumentsRange);
+
+  auto get_part = [&](const std::pair<size_t, size_t> &loc) {
+    return demangled.substr(loc.first, loc.second - loc.first);
+  };
+
+  EXPECT_EQ(get_part(OB.NameInfo.BasenameRange), basename);
+  EXPECT_EQ(get_part(OB.NameInfo.ScopeRange), scope);
+}
+
+INSTANTIATE_TEST_SUITE_P(DemanglingPartsTests, DemanglingPartsTestFixture,
+                         ::testing::ValuesIn(g_demangling_parts_test_cases));


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

Reply via email to