https://github.com/Michael137 created 
https://github.com/llvm/llvm-project/pull/137408

This patch makes the frame-format variables introduced in 
https://github.com/llvm/llvm-project/pull/131836 also work when no debug-info 
is available. Previously, we assumed `sc.function` was available, but without 
debug-info we might only have `sc.symbol`. We don't really need the 
`sc.function` apart from when formatting arguments.

For the function arguments case I added a fallback that will just print the 
arguments we get from the demangler (which is what LLDB does for stacktraces 
with no debug-info anyway). Ideally we'd have a separate 
`FormatEntity::Entry::Type::FunctionArguments` that will just print the 
arguments from the demangler and have something like the following in the 
`plugin.cplusplus.display.function-name-format`:
```
{ ${function.formatted-arguments} || ${function.arguments} }
```
I.e., when we can't format the arguments, print the ones from the demangler. 
But we currently don't have the `||` operator in the frame-format language yet.

>From 63a74fe19a7079a1eff4b6387ead56e123b74ce4 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Fri, 25 Apr 2025 22:49:36 +0100
Subject: [PATCH] [lldb][CPlusPLus] Make C++ frame-format work without
 debug-info

---
 lldb/source/Core/FormatEntity.cpp             |  9 +++--
 .../Language/CPlusPlus/CPlusPlusLanguage.cpp  | 38 ++++++++++++++++++-
 .../TestFrameFormatFunctionBasename.test      |  6 ++-
 ...FrameFormatFunctionFormattedArguments.test | 11 +++++-
 .../TestFrameFormatFunctionQualifiers.test    |  6 ++-
 .../TestFrameFormatFunctionReturn.test        |  6 ++-
 .../TestFrameFormatFunctionScope.test         |  9 +++--
 ...tFrameFormatFunctionTemplateArguments.test |  8 +++-
 8 files changed, 78 insertions(+), 15 deletions(-)

diff --git a/lldb/source/Core/FormatEntity.cpp 
b/lldb/source/Core/FormatEntity.cpp
index e352d07fe487d..4ac50e2d30f3c 100644
--- a/lldb/source/Core/FormatEntity.cpp
+++ b/lldb/source/Core/FormatEntity.cpp
@@ -1809,11 +1809,12 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
   case Entry::Type::FunctionReturnRight:
   case Entry::Type::FunctionReturnLeft:
   case Entry::Type::FunctionQualifiers: {
-    if (!sc->function)
-      return false;
+    Language *language_plugin = nullptr;
+    if (sc->function)
+      language_plugin = Language::FindPlugin(sc->function->GetLanguage());
+    else if (sc->symbol)
+      language_plugin = Language::FindPlugin(sc->symbol->GetLanguage());
 
-    Language *language_plugin =
-        Language::FindPlugin(sc->function->GetLanguage());
     if (!language_plugin)
       return false;
 
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp 
b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 283e867d53bb7..ab8e9883868ce 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -381,6 +381,34 @@ GetDemangledScope(const SymbolContext &sc) {
   return demangled_name.slice(info->ScopeRange.first, info->ScopeRange.second);
 }
 
+static bool PrintDemangledArgumentList(Stream &s, const SymbolContext &sc) {
+  assert(sc.symbol);
+
+  Mangled mangled = sc.GetPossiblyInlinedFunctionName();
+  if (!mangled)
+    return false;
+
+  auto demangled_name = mangled.GetDemangledName().GetStringRef();
+  if (demangled_name.empty())
+    return false;
+
+  const std::optional<DemangledNameInfo> &info = mangled.GetDemangledInfo();
+  if (!info)
+    return false;
+
+  // Function without a basename is nonsense.
+  if (!info->hasBasename())
+    return false;
+
+  if (info->ArgumentsRange.second < info->ArgumentsRange.first)
+    return false;
+
+  s << demangled_name.slice(info->ArgumentsRange.first,
+                            info->ArgumentsRange.second);
+
+  return true;
+}
+
 bool CPlusPlusLanguage::CxxMethodName::TrySimplifiedParse() {
   // This method tries to parse simple method definitions which are presumably
   // most comman in user programs. Definitions that can be parsed by this
@@ -1890,8 +1918,6 @@ bool CPlusPlusLanguage::GetFunctionDisplayName(
 bool CPlusPlusLanguage::HandleFrameFormatVariable(
     const SymbolContext &sc, const ExecutionContext *exe_ctx,
     FormatEntity::Entry::Type type, Stream &s) {
-  assert(sc.function);
-
   switch (type) {
   case FormatEntity::Entry::Type::FunctionScope: {
     std::optional<llvm::StringRef> scope = GetDemangledScope(sc);
@@ -1925,6 +1951,14 @@ bool CPlusPlusLanguage::HandleFrameFormatVariable(
   }
 
   case FormatEntity::Entry::Type::FunctionFormattedArguments: {
+    // This ensures we print the arguments even when no debug-info is 
available.
+    //
+    // FIXME: we should have a Entry::Type::FunctionArguments and
+    // use it in the plugin.cplusplus.display.function-name-format
+    // once we have a "fallback operator" in the frame-format language.
+    if (!sc.function && sc.symbol)
+      return PrintDemangledArgumentList(s, sc);
+
     VariableList args;
     if (auto variable_list_sp = GetFunctionVariableList(sc))
       variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument,
diff --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionBasename.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionBasename.test
index 249a5fac5b55e..35d443d872c7d 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionBasename.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionBasename.test
@@ -1,10 +1,14 @@
 # Test the ${function.basename} frame-format variable.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.out
+# RUN: %clang_host -g %t/main.cpp -o %t.out
 # RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
 #
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
+
 #--- main.cpp
 namespace ns {
 template<typename T>
diff --git 
a/lldb/test/Shell/Settings/TestFrameFormatFunctionFormattedArguments.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionFormattedArguments.test
index 5554830d3a247..46fb518158ce2 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionFormattedArguments.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionFormattedArguments.test
@@ -1,9 +1,13 @@
 # Test the ${function.formatted-arguments} frame-format variable.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.out
+# RUN: %clang_host -g %t/main.cpp -o %t.out
 # RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
+#
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
+# RUN:       | FileCheck %s --check-prefix=CHECK-NODEBUG
 
 #--- main.cpp
 struct Foo {
@@ -40,3 +44,8 @@ bt
 # CHECK: custom-frame '((null)=5, x=10)'
 # CHECK: custom-frame '(str="hello", fptr=({{.*}}.out`foo(int, int) at 
main.cpp:{{[0-9]+}}))'
 # CHECK: custom-frame '(argc=1, argv={{.*}})'
+
+# CHECK-NODEBUG: custom-frame '()'
+# CHECK-NODEBUG: custom-frame '()'
+# CHECK-NODEBUG: custom-frame '(int, int)'
+# CHECK-NODEBUG: custom-frame '(char const*, void (*)(int, int))'
diff --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionQualifiers.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionQualifiers.test
index 95a3be3811d85..ad7ea65d0a261 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionQualifiers.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionQualifiers.test
@@ -1,9 +1,13 @@
 # Test the ${function.qualifiers} frame-format variable.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.out
+# RUN: %clang_host -g %t/main.cpp -o %t.out
 # RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
+#
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
 
 #--- main.cpp
 struct Foo {
diff --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionReturn.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionReturn.test
index a5e49a1054c86..dd4cc68817712 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionReturn.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionReturn.test
@@ -2,9 +2,13 @@
 # frame-format variables.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.out
+# RUN: %clang_host -g %t/main.cpp -o %t.out
 # RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
+#
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
 
 #--- main.cpp
 namespace ns::ns2 {
diff --git a/lldb/test/Shell/Settings/TestFrameFormatFunctionScope.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionScope.test
index 28f0ab7ca39e3..a1d4cc01054db 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionScope.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionScope.test
@@ -1,9 +1,12 @@
 # Test the ${function.scope} frame-format variable.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.out
-# RUN: %lldb -o "settings set interpreter.stop-command-source-on-error false" \
-# RUN:       -x -b -s %t/commands.input %t.out -o exit 2>&1 \
+# RUN: %clang_host -g %t/main.cpp -o %t.out
+# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
+#
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
 
 #--- main.cpp
diff --git 
a/lldb/test/Shell/Settings/TestFrameFormatFunctionTemplateArguments.test 
b/lldb/test/Shell/Settings/TestFrameFormatFunctionTemplateArguments.test
index 396dd29dfd02c..384ba0adc4ce9 100644
--- a/lldb/test/Shell/Settings/TestFrameFormatFunctionTemplateArguments.test
+++ b/lldb/test/Shell/Settings/TestFrameFormatFunctionTemplateArguments.test
@@ -1,8 +1,12 @@
 # Test the ${function.template-arguments} frame-format variable.
 
 # RUN: split-file %s %t
-# RUN: %build %t/main.cpp -o %t.cxx.out
-# RUN: %lldb -x -b -s %t/commands.input %t.cxx.out -o exit 2>&1 \
+# RUN: %clang_host -g %t/main.cpp -o %t.out
+# RUN: %lldb -x -b -s %t/commands.input %t.out -o exit 2>&1 \
+# RUN:       | FileCheck %s
+#
+# RUN: %clang_host -O0 %t/main.cpp -o %t-nodebug.out
+# RUN: %lldb -x -b -s %t/commands.input %t-nodebug.out -o exit 2>&1 \
 # RUN:       | FileCheck %s
 
 #--- main.cpp

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

Reply via email to