[Lldb-commits] [lldb] b8997c0 - [Demangling] Refactor Demangler range tracking (#140762)

via lldb-commits lldb-commits at lists.llvm.org
Wed May 28 05:53:05 PDT 2025


Author: Charles Zablit
Date: 2025-05-28T13:53:02+01:00
New Revision: b8997c07d9783bbf81bf144b5982d43ba804f5ac

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

LOG: [Demangling] Refactor Demangler range tracking (#140762)

This PR is a subset of the commits made in
https://github.com/swiftlang/llvm-project/pull/10710.

The most notable change is the addition of `PrefixRange` and
`SuffixRange` which are a catch-all to track anything after or before a
function's demangled name. In the case of Swift, this allows to add
support for name highlighting without having to track the range of the
scope and specifiers of a function (this will come in another PR).

Added: 
    lldb/test/Shell/Settings/TestFrameFormatFunctionPrefix.test

Modified: 
    lldb/docs/use/formatting.rst
    lldb/include/lldb/Core/DemangledNameInfo.h
    lldb/include/lldb/Core/FormatEntity.h
    lldb/source/Core/FormatEntity.cpp
    lldb/source/Core/Mangled.cpp
    lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/docs/use/formatting.rst b/lldb/docs/use/formatting.rst
index 61f51812d2ea9..e71b08780eb3d 100644
--- a/lldb/docs/use/formatting.rst
+++ b/lldb/docs/use/formatting.rst
@@ -91,7 +91,9 @@ A complete list of currently supported format string variables is listed below:
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | ``function.basename``                             | The basename of the current function depending on the frame's language. E.g., for C++ the basename for ``void ns::foo<float>::bar<int>(int) const`` is ``bar``.                                                                                                                             |
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-| ``function.scope``                                |  The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``.                                                                                                            |
+| ``function.prefix``                               | Any prefix added to the demangled function name of the current function. This depends on the frame's language. E.g., for C++ the prefix will always be empty.                                                                                                                               |
++---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| ``function.scope``                                | The scope qualifiers of the current function depending on the frame's language. E.g., for C++ the scope for ``void ns::foo<float>::bar<int>(int) const`` is ``ns::foo<float>``.                                                                                                             |
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
 | ``function.template-arguments``                   | The template arguments of the current function depending on the frame's language. E.g., for C++ the template arguments for ``void ns::foo<float>::bar<int>(int) const`` are ``<float>``.                                                                                                    |
 +---------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
@@ -325,6 +327,7 @@ _____________________
 The function names displayed in backtraces/``frame info``/``thread info`` are the demangled names of functions. On some platforms (like ones using Itanium the mangling scheme), LLDB supports decomposing these names into fine-grained components. These are currently:
 
 - ``${function.return-left}``
+- ``${function.prefix}``
 - ``${function.scope}``
 - ``${function.basename}``
 - ``${function.template-arguments}``

diff  --git a/lldb/include/lldb/Core/DemangledNameInfo.h b/lldb/include/lldb/Core/DemangledNameInfo.h
index 11d3bb58871b8..ab9bb3e211b66 100644
--- a/lldb/include/lldb/Core/DemangledNameInfo.h
+++ b/lldb/include/lldb/Core/DemangledNameInfo.h
@@ -39,7 +39,7 @@ struct DemangledNameInfo {
   /// \endcode
   std::pair<size_t, size_t> ScopeRange;
 
-  /// Indicates the [start, end) of the function argument lits.
+  /// Indicates the [start, end) of the function argument list.
   /// E.g.,
   /// \code{.cpp}
   ///    int (*getFunc<float>(float, double))(int, int)
@@ -59,6 +59,16 @@ struct DemangledNameInfo {
   /// \endcode
   std::pair<size_t, size_t> QualifiersRange;
 
+  /// Indicates the [start, end) of the function's prefix. This is a
+  /// catch-all range for anything that is not tracked by the rest of
+  /// the pairs.
+  std::pair<size_t, size_t> PrefixRange;
+
+  /// Indicates the [start, end) of the function's suffix. This is a
+  /// catch-all range for anything that is not tracked by the rest of
+  /// the pairs.
+  std::pair<size_t, size_t> SuffixRange;
+
   /// Returns \c true if this object holds a valid basename range.
   bool hasBasename() const {
     return BasenameRange.second > BasenameRange.first &&

diff  --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index 6acf6fbe43239..1aed3c6ff9e9d 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -88,6 +88,7 @@ struct Entry {
     FunctionNameWithArgs,
     FunctionNameNoArgs,
     FunctionMangledName,
+    FunctionPrefix,
     FunctionScope,
     FunctionBasename,
     FunctionTemplateArguments,

diff  --git a/lldb/source/Core/FormatEntity.cpp b/lldb/source/Core/FormatEntity.cpp
index 4f2d39873c7fb..4dcfa43a7bb04 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -124,6 +124,7 @@ constexpr Definition g_function_child_entries[] = {
     Definition("initial-function", EntryType::FunctionInitial),
     Definition("changed", EntryType::FunctionChanged),
     Definition("is-optimized", EntryType::FunctionIsOptimized),
+    Definition("prefix", EntryType::FunctionPrefix),
     Definition("scope", EntryType::FunctionScope),
     Definition("basename", EntryType::FunctionBasename),
     Definition("template-arguments", EntryType::FunctionTemplateArguments),
@@ -385,6 +386,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
     ENUM_TO_CSTR(FunctionNameWithArgs);
     ENUM_TO_CSTR(FunctionNameNoArgs);
     ENUM_TO_CSTR(FunctionMangledName);
+    ENUM_TO_CSTR(FunctionPrefix);
     ENUM_TO_CSTR(FunctionScope);
     ENUM_TO_CSTR(FunctionBasename);
     ENUM_TO_CSTR(FunctionTemplateArguments);
@@ -1835,6 +1837,7 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
     return true;
   }
 
+  case Entry::Type::FunctionPrefix:
   case Entry::Type::FunctionScope:
   case Entry::Type::FunctionBasename:
   case Entry::Type::FunctionTemplateArguments:

diff  --git a/lldb/source/Core/Mangled.cpp b/lldb/source/Core/Mangled.cpp
index ce4db4e0daa8b..0027bfaeda4f7 100644
--- a/lldb/source/Core/Mangled.cpp
+++ b/lldb/source/Core/Mangled.cpp
@@ -172,6 +172,8 @@ GetItaniumDemangledStr(const char *M) {
 
     TrackingOutputBuffer OB(demangled_cstr, demangled_size);
     demangled_cstr = ipd.finishDemangle(&OB);
+    OB.NameInfo.SuffixRange.first = OB.NameInfo.QualifiersRange.second;
+    OB.NameInfo.SuffixRange.second = std::string_view(OB).size();
     info = std::move(OB.NameInfo);
 
     assert(demangled_cstr &&

diff  --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index b178e06a975cd..7485577ae67e0 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -401,8 +401,8 @@ GetDemangledFunctionSuffix(const SymbolContext &sc) {
   if (!info->hasBasename())
     return std::nullopt;
 
-  return demangled_name.slice(info->QualifiersRange.second,
-                              llvm::StringRef::npos);
+  return demangled_name.slice(info->SuffixRange.first,
+                              info->SuffixRange.second);
 }
 
 static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {

diff  --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionPrefix.test b/lldb/test/Shell/Settings/TestFrameFormatFunctionPrefix.test
new file mode 100644
index 0000000000000..5bf1990d24c32
--- /dev/null
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionPrefix.test
@@ -0,0 +1,24 @@
+# Check that we have an appropriate fallback for ${function.prefix} in languages that
+# don't implement this frame format variable (in this case Objective-C).
+#
+# RUN: split-file %s %t
+# RUN: %clang_host -g -gdwarf %t/main.m -o %t.objc.out
+# RUN: %lldb -x -b -s %t/commands.input %t.objc.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
+
+#--- main.m
+
+int func() {}
+int bar() { func(); }
+
+int main() { return bar(); }
+
+#--- commands.input
+settings set -f frame-format "custom-frame '${function.prefix}'\n"
+break set -n bar
+
+run
+bt
+
+# CHECK: bt
+# CHECK-NOT: custom-frame


        


More information about the lldb-commits mailing list