https://github.com/charles-zablit updated 
https://github.com/llvm/llvm-project/pull/181143

>From 92d5420bce652a524c297283ee0386ed5ffe4181 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Mon, 19 Jan 2026 10:43:45 +0000
Subject: [PATCH 1/5] [lldb] add a marker before hidden frames (#167550)

**This patch adds a marker to make hidden frames more explicit.**

---

Hidden frames can be confusing for some users, who see that the indexes
of the frames in a backtrace are not contiguous. This patch aims to
lessen the confusion by adding a delimiter for the first and last non
hidden frame, i.e the boundaries.

IDE's like Xcode and VSCode represent those in the UI by having the
hidden frames either greyed out or collapsed.

It's not possible to do this in the CLI, therefore, this patch makes use
of 2 unicode characters to mark the beginning and end of the hidden
frames range.

This patch depends on:
- https://github.com/llvm/llvm-project/pull/168603

# Examples

In the example below, frame `#2` to `#7` are is hidden, and therefore,
frame `#1` is the first non hidden frame of the range while frame `#8`
is the last non hidden frame:
<img width="488" height="112" alt="Screenshot 2025-11-18 at 18 41 11"
src="https://github.com/user-attachments/assets/a21431da-9729-4cf0-a6bc-024aa306fc45";
/>

If the selected frame is one of the 2 boundary frames, we replace the
delimiter character with the select character (`*`).

<img width="487" height="111" alt="Screenshot 2025-11-18 at 18 41 03"
src="https://github.com/user-attachments/assets/5616fa81-6db6-457d-9d1e-bbe46e710c26";
/>
<img width="488" height="111" alt="Screenshot 2025-11-18 at 18 40 55"
src="https://github.com/user-attachments/assets/93dfa6cf-0956-4718-b31c-f965ec72b56d";
/>
---
 lldb/include/lldb/Core/Debugger.h             |  2 +
 lldb/include/lldb/Target/StackFrame.h         |  4 +-
 lldb/include/lldb/Target/StackFrameList.h     | 19 +++-
 .../Python/lldbsuite/test/decorators.py       | 29 ++++++
 lldb/source/Core/CoreProperties.td            |  4 +
 lldb/source/Core/Debugger.cpp                 |  7 ++
 lldb/source/Target/StackFrame.cpp             |  5 +-
 lldb/source/Target/StackFrameList.cpp         | 53 +++++++---
 lldb/source/Target/Thread.cpp                 | 23 +++--
 .../terminal/hidden_frame_markers/Makefile    |  3 +
 .../TestHiddenFrameMarkers.py                 | 97 +++++++++++++++++++
 .../terminal/hidden_frame_markers/main.cpp    | 12 +++
 12 files changed, 231 insertions(+), 27 deletions(-)
 create mode 100644 lldb/test/API/terminal/hidden_frame_markers/Makefile
 create mode 100644 
lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
 create mode 100644 lldb/test/API/terminal/hidden_frame_markers/main.cpp

diff --git a/lldb/include/lldb/Core/Debugger.h 
b/lldb/include/lldb/Core/Debugger.h
index 87a57f7f1a538..a38caa7ac594e 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -347,6 +347,8 @@ class Debugger : public 
std::enable_shared_from_this<Debugger>,
 
   bool SetUseSourceCache(bool use_source_cache);
 
+  bool GetMarkHiddenFrames() const;
+
   bool GetHighlightSource() const;
 
   lldb::StopShowColumn GetStopShowColumn() const;
diff --git a/lldb/include/lldb/Target/StackFrame.h 
b/lldb/include/lldb/Target/StackFrame.h
index 5cba9afe2a7e8..17563ee6ada98 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -363,7 +363,7 @@ class StackFrame : public ExecutionContextScope,
   /// \param [in] frame_marker
   ///   Optional string that will be prepended to the frame output description.
   virtual void DumpUsingSettingsFormat(Stream *strm, bool show_unique = false,
-                                       const char *frame_marker = nullptr);
+                                       const llvm::StringRef frame_marker = 
"");
 
   /// Print a description for this frame using a default format.
   ///
@@ -400,7 +400,7 @@ class StackFrame : public ExecutionContextScope,
   ///   Returns true if successful.
   virtual bool GetStatus(Stream &strm, bool show_frame_info, bool show_source,
                          bool show_unique = false,
-                         const char *frame_marker = nullptr);
+                         const llvm::StringRef frame_marker = "");
 
   /// Query whether this frame is a concrete frame on the call stack, or if it
   /// is an inlined frame derived from the debug information and presented by
diff --git a/lldb/include/lldb/Target/StackFrameList.h 
b/lldb/include/lldb/Target/StackFrameList.h
index 715781abb83a3..223aa3ddab731 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -50,6 +50,22 @@ class StackFrameList : public 
std::enable_shared_from_this<StackFrameList> {
   /// Resets the selected frame index of this object.
   void ClearSelectedFrameIndex();
 
+  /// Returns \p true if the next frame is hidden.
+  bool IsNextFrameHidden(lldb_private::StackFrame &frame);
+
+  /// Returns \p true if the previous frame is hidden.
+  bool IsPreviousFrameHidden(lldb_private::StackFrame &frame);
+
+  /// Returns the stack frame marker depending on if \p frame_sp:
+  /// @li is selected: *
+  /// @li is the first non hidden frame: ﹍
+  /// @li is the last non hidden frame: ﹉
+  ///
+  /// If the terminal does not support Unicode rendering, the hidden frame
+  /// markers are replaced with whitespaces.
+  std::string FrameMarker(lldb::StackFrameSP frame_sp,
+                          lldb::StackFrameSP selected_frame_sp);
+
   /// Get the currently selected frame index.
   /// We should only call SelectMostRelevantFrame if (a) the user hasn't 
already
   /// selected a frame, and (b) if this really is a user facing
@@ -97,7 +113,8 @@ class StackFrameList : public 
std::enable_shared_from_this<StackFrameList> {
   size_t GetStatus(Stream &strm, uint32_t first_frame, uint32_t num_frames,
                    bool show_frame_info, uint32_t num_frames_with_source,
                    bool show_unique = false, bool show_hidden = false,
-                   const char *frame_marker = nullptr);
+                   bool show_hidden_marker = true,
+                   bool show_selected_frame = false);
 
   /// Returns whether we have currently fetched all the frames of a stack.
   bool WereAllFramesFetched() const;
diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py 
b/lldb/packages/Python/lldbsuite/test/decorators.py
index df0b2cba4c573..b4658b149af90 100644
--- a/lldb/packages/Python/lldbsuite/test/decorators.py
+++ b/lldb/packages/Python/lldbsuite/test/decorators.py
@@ -442,6 +442,35 @@ def impl(func):
     return impl
 
 
+def unicode_test(func):
+    """Decorate the item as a test which requires Unicode to be enabled.
+
+    lldb checks the value of the `LANG` environment variable for the substring 
"utf-8"
+    to determine if the terminal supports Unicode (except on Windows, were we 
assume
+    it's always supported).
+    This decorator sets LANG to `utf-8` before running the test and resets it 
to its
+    previous value afterwards.
+    """
+
+    def unicode_wrapped(*args, **kwargs):
+        import os
+
+        previous_lang = os.environ.get("LANG", None)
+        os.environ["LANG"] = "en_US.UTF-8"
+        try:
+            func(*args, **kwargs)
+        except Exception as err:
+            raise err
+        finally:
+            # Reset the value, whether the test failed or not.
+            if previous_lang is not None:
+                os.environ["LANG"] = previous_lang
+            else:
+                del os.environ["LANG"]
+
+    return unicode_wrapped
+
+
 def no_debug_info_test(func):
     """Decorate the item as a test what don't use any debug info. If this 
annotation is specified
     then the test runner won't generate a separate test for each debug info 
format."""
diff --git a/lldb/source/Core/CoreProperties.td 
b/lldb/source/Core/CoreProperties.td
index 383834eea22a5..e029da6467fce 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -128,6 +128,10 @@ let Definition = "debugger", Path = "" in {
     Global,
     DefaultTrue,
     Desc<"If true, LLDB will highlight the displayed source code.">;
+  def MarkHiddenFrames: Property<"mark-hidden-frames", "Boolean">,
+    Global,
+    DefaultTrue,
+    Desc<"If true, LLDB will add a marker to delimit hidden frames in 
backtraces.">;
   def StopShowColumn: Property<"stop-show-column", "Enum">,
     DefaultEnumValue<"eStopShowColumnAnsiOrCaret">,
     EnumValues<"OptionEnumValues(s_stop_show_column_values)">,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 00dea7da3497e..12f8039da947e 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -612,6 +612,13 @@ bool Debugger::SetUseSourceCache(bool b) {
   }
   return ret;
 }
+
+bool Debugger::GetMarkHiddenFrames() const {
+  const uint32_t idx = ePropertyMarkHiddenFrames;
+  return GetPropertyAtIndexAs<bool>(
+      idx, g_debugger_properties[idx].default_uint_value != 0);
+}
+
 bool Debugger::GetHighlightSource() const {
   const uint32_t idx = ePropertyHighlightSource;
   return GetPropertyAtIndexAs<bool>(
diff --git a/lldb/source/Target/StackFrame.cpp 
b/lldb/source/Target/StackFrame.cpp
index 340607e14abed..3ef96a46517c9 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -1945,7 +1945,7 @@ bool StackFrame::DumpUsingFormat(Stream &strm,
 }
 
 void StackFrame::DumpUsingSettingsFormat(Stream *strm, bool show_unique,
-                                         const char *frame_marker) {
+                                         const llvm::StringRef frame_marker) {
   if (strm == nullptr)
     return;
 
@@ -2044,7 +2044,8 @@ bool StackFrame::HasCachedData() const {
 }
 
 bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool 
show_source,
-                           bool show_unique, const char *frame_marker) {
+                           bool show_unique,
+                           const llvm::StringRef frame_marker) {
   if (show_frame_info) {
     strm.Indent();
     DumpUsingSettingsFormat(&strm, show_unique, frame_marker);
diff --git a/lldb/source/Target/StackFrameList.cpp 
b/lldb/source/Target/StackFrameList.cpp
index 4f4b06f30460b..d573d23c318fb 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -27,6 +27,7 @@
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/ConvertUTF.h"
 
 #include <memory>
 
@@ -947,11 +948,43 @@ 
StackFrameList::GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr) {
   return ret_sp;
 }
 
+bool StackFrameList::IsNextFrameHidden(lldb_private::StackFrame &frame) {
+  uint32_t frame_idx = frame.GetFrameIndex();
+  StackFrameSP frame_sp = GetFrameAtIndex(frame_idx + 1);
+  if (!frame_sp)
+    return false;
+  return frame_sp->IsHidden();
+}
+
+bool StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
+  uint32_t frame_idx = frame.GetFrameIndex();
+  if (frame_idx == 0)
+    return false;
+  StackFrameSP frame_sp = GetFrameAtIndex(frame_idx - 1);
+  if (!frame_sp)
+    return false;
+  return frame_sp->IsHidden();
+}
+
+std::string StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
+                                        lldb::StackFrameSP selected_frame_sp) {
+  if (frame_sp == selected_frame_sp)
+    return Terminal::SupportsUnicode() ? u8" * " : u8"* ";
+  else if (!Terminal::SupportsUnicode())
+    return u8"  ";
+  else if (IsPreviousFrameHidden(*frame_sp))
+    return u8"﹉ ";
+  else if (IsNextFrameHidden(*frame_sp))
+    return u8"﹍ ";
+  return u8"   ";
+}
+
 size_t StackFrameList::GetStatus(Stream &strm, uint32_t first_frame,
                                  uint32_t num_frames, bool show_frame_info,
                                  uint32_t num_frames_with_source,
                                  bool show_unique, bool show_hidden,
-                                 const char *selected_frame_marker) {
+                                 bool show_hidden_marker,
+                                 bool show_selected_frame) {
   size_t num_frames_displayed = 0;
 
   if (num_frames == 0)
@@ -969,25 +1002,17 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t 
first_frame,
 
   StackFrameSP selected_frame_sp =
       m_thread.GetSelectedFrame(DoNoSelectMostRelevantFrame);
-  const char *unselected_marker = nullptr;
   std::string buffer;
-  if (selected_frame_marker) {
-    size_t len = strlen(selected_frame_marker);
-    buffer.insert(buffer.begin(), len, ' ');
-    unselected_marker = buffer.c_str();
-  }
-  const char *marker = nullptr;
+  std::string marker;
   for (frame_idx = first_frame; frame_idx < last_frame; ++frame_idx) {
     frame_sp = GetFrameAtIndex(frame_idx);
     if (!frame_sp)
       break;
 
-    if (selected_frame_marker != nullptr) {
-      if (frame_sp == selected_frame_sp)
-        marker = selected_frame_marker;
-      else
-        marker = unselected_marker;
-    }
+    if (show_selected_frame)
+      marker = FrameMarker(frame_sp, selected_frame_sp);
+    else
+      marker = FrameMarker(frame_sp, nullptr);
 
     // Hide uninteresting frames unless it's the selected frame.
     if (!show_hidden && frame_sp != selected_frame_sp && frame_sp->IsHidden())
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index 44b664ac70d29..aa005a2b9b3db 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -1961,9 +1961,9 @@ size_t Thread::GetStatus(Stream &strm, uint32_t 
start_frame,
                          uint32_t num_frames, uint32_t num_frames_with_source,
                          bool stop_format, bool show_hidden, bool only_stacks) 
{
 
+  ExecutionContext exe_ctx(shared_from_this());
+  Target *target = exe_ctx.GetTargetPtr();
   if (!only_stacks) {
-    ExecutionContext exe_ctx(shared_from_this());
-    Target *target = exe_ctx.GetTargetPtr();
     Process *process = exe_ctx.GetProcessPtr();
     strm.Indent();
     bool is_selected = false;
@@ -1997,16 +1997,19 @@ size_t Thread::GetStatus(Stream &strm, uint32_t 
start_frame,
 
     const bool show_frame_info = true;
     const bool show_frame_unique = only_stacks;
-    const char *selected_frame_marker = nullptr;
+    bool show_selected_frame = false;
     if (num_frames == 1 || only_stacks ||
         (GetID() != 
GetProcess()->GetThreadList().GetSelectedThread()->GetID()))
       strm.IndentMore();
     else
-      selected_frame_marker = "* ";
+      show_selected_frame = true;
 
+    bool show_hidden_marker =
+        target && target->GetDebugger().GetMarkHiddenFrames();
     num_frames_shown = GetStackFrameList()->GetStatus(
         strm, start_frame, num_frames, show_frame_info, num_frames_with_source,
-        show_frame_unique, show_hidden, selected_frame_marker);
+        show_frame_unique, show_hidden, show_hidden_marker,
+        show_selected_frame);
     if (num_frames == 1)
       strm.IndentLess();
     strm.IndentLess();
@@ -2106,9 +2109,13 @@ size_t Thread::GetStackFrameStatus(Stream &strm, 
uint32_t first_frame,
                                    uint32_t num_frames, bool show_frame_info,
                                    uint32_t num_frames_with_source,
                                    bool show_hidden) {
-  return GetStackFrameList()->GetStatus(strm, first_frame, num_frames,
-                                        show_frame_info, 
num_frames_with_source,
-                                        /*show_unique*/ false, show_hidden);
+  ExecutionContext exe_ctx(shared_from_this());
+  Target *target = exe_ctx.GetTargetPtr();
+  bool show_hidden_marker =
+      target && target->GetDebugger().GetMarkHiddenFrames();
+  return GetStackFrameList()->GetStatus(
+      strm, first_frame, num_frames, show_frame_info, num_frames_with_source,
+      /*show_unique*/ false, show_hidden, show_hidden_marker);
 }
 
 Unwind &Thread::GetUnwinder() {
diff --git a/lldb/test/API/terminal/hidden_frame_markers/Makefile 
b/lldb/test/API/terminal/hidden_frame_markers/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git 
a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py 
b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
new file mode 100644
index 0000000000000..178d97fce17c2
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -0,0 +1,97 @@
+"""
+Test that hidden frames are delimited with markers.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class HiddenFrameMarkerTest(TestBase):
+    @unicode_test
+    def test_hidden_frame_markers(self):
+        """Test that hidden frame markers are rendered in backtraces"""
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+        self.expect(
+            "bt",
+            substrs=[
+                "   * frame #0:",
+                "  ﹍ frame #1:",
+                "  ﹉ frame #7:",
+                "     frame #8:",
+                "     frame #9:",
+            ],
+        )
+
+        self.runCmd("f 1")
+        self.expect(
+            "bt",
+            substrs=[
+                "     frame #0:",
+                "   * frame #1:",
+                "  ﹉ frame #7:",
+                "     frame #8:",
+                "     frame #9:",
+            ],
+        )
+
+        self.runCmd("f 7")
+        self.expect(
+            "bt",
+            substrs=[
+                "     frame #0:",
+                "  ﹍ frame #1:",
+                "   * frame #7:",
+                "     frame #8:",
+                "     frame #9:",
+            ],
+        )
+
+    def test_hidden_frame_markers(self):
+        """
+        Test that hidden frame markers are not rendered in backtraces when
+        mark-hidden-frames is set to false
+        """
+        self.build()
+        self.runCmd("settings set mark-hidden-frames 0")
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here", lldb.SBFileSpec("main.cpp")
+        )
+        self.expect(
+            "bt",
+            substrs=[
+                "  * frame #0:",
+                "    frame #1:",
+                "    frame #7:",
+                "    frame #8:",
+                "    frame #9:",
+            ],
+        )
+
+        self.runCmd("f 1")
+        self.expect(
+            "bt",
+            substrs=[
+                "    frame #0:",
+                "  * frame #1:",
+                "    frame #7:",
+                "    frame #8:",
+                "    frame #9:",
+            ],
+        )
+
+        self.runCmd("f 7")
+        self.expect(
+            "bt",
+            substrs=[
+                "    frame #0:",
+                "    frame #1:",
+                "  * frame #7:",
+                "    frame #8:",
+                "    frame #9:",
+            ],
+        )
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp 
b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
new file mode 100644
index 0000000000000..c0b7e0884538a
--- /dev/null
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -0,0 +1,12 @@
+#include <functional>
+#include <iostream>
+
+static void target() {
+  int a = 0; // break here
+}
+
+int main() {
+  std::function<void()> fn = [] { target(); };
+  fn();
+  return 0;
+}

>From b0df9aba9fa7e589c63979df29e2bc284578227f Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Thu, 12 Feb 2026 17:06:44 +0100
Subject: [PATCH 2/5] fixup! [lldb] add a marker before hidden frames (#167550)

---
 lldb/include/lldb/Target/StackFrameList.h     |  3 +-
 lldb/source/Target/StackFrameList.cpp         | 13 +++---
 .../TestHiddenFrameMarkers.py                 | 42 ++++++++-----------
 .../terminal/hidden_frame_markers/main.cpp    | 16 ++++---
 4 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/lldb/include/lldb/Target/StackFrameList.h 
b/lldb/include/lldb/Target/StackFrameList.h
index 223aa3ddab731..149b1cb87222c 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -64,7 +64,8 @@ class StackFrameList : public 
std::enable_shared_from_this<StackFrameList> {
   /// If the terminal does not support Unicode rendering, the hidden frame
   /// markers are replaced with whitespaces.
   std::string FrameMarker(lldb::StackFrameSP frame_sp,
-                          lldb::StackFrameSP selected_frame_sp);
+                          lldb::StackFrameSP selected_frame_sp,
+                          bool show_hidden_marker);
 
   /// Get the currently selected frame index.
   /// We should only call SelectMostRelevantFrame if (a) the user hasn't 
already
diff --git a/lldb/source/Target/StackFrameList.cpp 
b/lldb/source/Target/StackFrameList.cpp
index d573d23c318fb..af14ede08f3b8 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -967,10 +967,12 @@ bool 
StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
 }
 
 std::string StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
-                                        lldb::StackFrameSP selected_frame_sp) {
+                                        lldb::StackFrameSP selected_frame_sp,
+                                        bool show_hidden_marker) {
+  bool show_unicode_marker = Terminal::SupportsUnicode() && show_hidden_marker;
   if (frame_sp == selected_frame_sp)
-    return Terminal::SupportsUnicode() ? u8" * " : u8"* ";
-  else if (!Terminal::SupportsUnicode())
+    return show_unicode_marker ? u8" * " : u8"* ";
+  else if (!show_unicode_marker)
     return u8"  ";
   else if (IsPreviousFrameHidden(*frame_sp))
     return u8"﹉ ";
@@ -1010,9 +1012,10 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t 
first_frame,
       break;
 
     if (show_selected_frame)
-      marker = FrameMarker(frame_sp, selected_frame_sp);
+      marker = FrameMarker(frame_sp, selected_frame_sp, show_hidden_marker);
     else
-      marker = FrameMarker(frame_sp, nullptr);
+      marker = FrameMarker(frame_sp, /*selected_frame_sp=*/nullptr,
+                           show_hidden_marker);
 
     // Hide uninteresting frames unless it's the selected frame.
     if (!show_hidden && frame_sp != selected_frame_sp && frame_sp->IsHidden())
diff --git 
a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py 
b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index 178d97fce17c2..394bba41a0d77 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -20,10 +20,9 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "   * frame #0:",
-                "  ﹍ frame #1:",
-                "  ﹉ frame #7:",
-                "     frame #8:",
-                "     frame #9:",
+                "  ﹍ frame #2:",
+                "  ﹉ frame #3:",
+                "     frame #4:",
             ],
         )
 
@@ -32,10 +31,9 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "     frame #0:",
-                "   * frame #1:",
-                "  ﹉ frame #7:",
-                "     frame #8:",
-                "     frame #9:",
+                "   * frame #2:",
+                "  ﹉ frame #3:",
+                "     frame #4:",
             ],
         )
 
@@ -44,10 +42,9 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "     frame #0:",
-                "  ﹍ frame #1:",
-                "   * frame #7:",
-                "     frame #8:",
-                "     frame #9:",
+                "  ﹍ frame #2:",
+                "   * frame #3:",
+                "     frame #4:",
             ],
         )
 
@@ -65,10 +62,9 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "  * frame #0:",
-                "    frame #1:",
-                "    frame #7:",
-                "    frame #8:",
-                "    frame #9:",
+                "    frame #2:",
+                "    frame #3:",
+                "    frame #4:",
             ],
         )
 
@@ -77,10 +73,9 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "    frame #0:",
-                "  * frame #1:",
-                "    frame #7:",
-                "    frame #8:",
-                "    frame #9:",
+                "  * frame #2:",
+                "    frame #3:",
+                "    frame #4:",
             ],
         )
 
@@ -89,9 +84,8 @@ def test_hidden_frame_markers(self):
             "bt",
             substrs=[
                 "    frame #0:",
-                "    frame #1:",
-                "  * frame #7:",
-                "    frame #8:",
-                "    frame #9:",
+                "    frame #2:",
+                "  * frame #3:",
+                "    frame #4:",
             ],
         )
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp 
b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
index c0b7e0884538a..f489bcb275aae 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/main.cpp
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -1,12 +1,16 @@
-#include <functional>
-#include <iostream>
-
-static void target() {
+static void foo() {
   int a = 0; // break here
 }
 
+namespace std {
+namespace __1 {
+void __test_hidden_frame() { foo(); }
+
+void outer_function() { __test_hidden_frame(); }
+}
+}
+
 int main() {
-  std::function<void()> fn = [] { target(); };
-  fn();
+  std::__1::outer_function();
   return 0;
 }

>From d18b844ea2e676cca95733ee02ad9709f28f04b3 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 13 Feb 2026 11:19:11 +0100
Subject: [PATCH 3/5] fix test

---
 .../hidden_frame_markers/TestHiddenFrameMarkers.py        | 8 ++++----
 lldb/test/API/terminal/hidden_frame_markers/main.cpp      | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git 
a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py 
b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index 394bba41a0d77..d5cf3ee29363a 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -26,7 +26,7 @@ def test_hidden_frame_markers(self):
             ],
         )
 
-        self.runCmd("f 1")
+        self.runCmd("f 2")
         self.expect(
             "bt",
             substrs=[
@@ -37,7 +37,7 @@ def test_hidden_frame_markers(self):
             ],
         )
 
-        self.runCmd("f 7")
+        self.runCmd("f 3")
         self.expect(
             "bt",
             substrs=[
@@ -68,7 +68,7 @@ def test_hidden_frame_markers(self):
             ],
         )
 
-        self.runCmd("f 1")
+        self.runCmd("f 2")
         self.expect(
             "bt",
             substrs=[
@@ -79,7 +79,7 @@ def test_hidden_frame_markers(self):
             ],
         )
 
-        self.runCmd("f 7")
+        self.runCmd("f 3")
         self.expect(
             "bt",
             substrs=[
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp 
b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
index f489bcb275aae..874e4034dc053 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/main.cpp
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -7,8 +7,8 @@ namespace __1 {
 void __test_hidden_frame() { foo(); }
 
 void outer_function() { __test_hidden_frame(); }
-}
-}
+} // namespace __1
+} // namespace std
 
 int main() {
   std::__1::outer_function();

>From d51893366ca2040537ddb012a9dd53c304d8bfe5 Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 13 Feb 2026 11:20:22 +0100
Subject: [PATCH 4/5] switch to GetFrameMarker

---
 lldb/include/lldb/Target/StackFrameList.h |  6 +++---
 lldb/source/Target/StackFrameList.cpp     | 18 +++++++++---------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/lldb/include/lldb/Target/StackFrameList.h 
b/lldb/include/lldb/Target/StackFrameList.h
index 149b1cb87222c..f8822a8dadc9b 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -63,9 +63,9 @@ class StackFrameList : public 
std::enable_shared_from_this<StackFrameList> {
   ///
   /// If the terminal does not support Unicode rendering, the hidden frame
   /// markers are replaced with whitespaces.
-  std::string FrameMarker(lldb::StackFrameSP frame_sp,
-                          lldb::StackFrameSP selected_frame_sp,
-                          bool show_hidden_marker);
+  std::string GetFrameMarker(lldb::StackFrameSP frame_sp,
+                             lldb::StackFrameSP selected_frame_sp,
+                             bool show_hidden_marker);
 
   /// Get the currently selected frame index.
   /// We should only call SelectMostRelevantFrame if (a) the user hasn't 
already
diff --git a/lldb/source/Target/StackFrameList.cpp 
b/lldb/source/Target/StackFrameList.cpp
index af14ede08f3b8..48a8ac0a24ca9 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -966,17 +966,17 @@ bool 
StackFrameList::IsPreviousFrameHidden(lldb_private::StackFrame &frame) {
   return frame_sp->IsHidden();
 }
 
-std::string StackFrameList::FrameMarker(lldb::StackFrameSP frame_sp,
-                                        lldb::StackFrameSP selected_frame_sp,
-                                        bool show_hidden_marker) {
+std::string StackFrameList::GetFrameMarker(lldb::StackFrameSP frame_sp,
+                                           lldb::StackFrameSP 
selected_frame_sp,
+                                           bool show_hidden_marker) {
   bool show_unicode_marker = Terminal::SupportsUnicode() && show_hidden_marker;
   if (frame_sp == selected_frame_sp)
     return show_unicode_marker ? u8" * " : u8"* ";
-  else if (!show_unicode_marker)
+  if (!show_unicode_marker)
     return u8"  ";
-  else if (IsPreviousFrameHidden(*frame_sp))
+  if (IsPreviousFrameHidden(*frame_sp))
     return u8"﹉ ";
-  else if (IsNextFrameHidden(*frame_sp))
+  if (IsNextFrameHidden(*frame_sp))
     return u8"﹍ ";
   return u8"   ";
 }
@@ -1012,10 +1012,10 @@ size_t StackFrameList::GetStatus(Stream &strm, uint32_t 
first_frame,
       break;
 
     if (show_selected_frame)
-      marker = FrameMarker(frame_sp, selected_frame_sp, show_hidden_marker);
+      marker = GetFrameMarker(frame_sp, selected_frame_sp, show_hidden_marker);
     else
-      marker = FrameMarker(frame_sp, /*selected_frame_sp=*/nullptr,
-                           show_hidden_marker);
+      marker = GetFrameMarker(frame_sp, /*selected_frame_sp=*/nullptr,
+                              show_hidden_marker);
 
     // Hide uninteresting frames unless it's the selected frame.
     if (!show_hidden && frame_sp != selected_frame_sp && frame_sp->IsHidden())

>From 59f64ce8625ef802963e4bfd96ad166fb919e8ec Mon Sep 17 00:00:00 2001
From: Charles Zablit <[email protected]>
Date: Fri, 13 Feb 2026 11:40:23 +0100
Subject: [PATCH 5/5] expand test

---
 .../TestHiddenFrameMarkers.py                 | 84 +++++++++++++++++--
 .../terminal/hidden_frame_markers/main.cpp    | 15 +++-
 2 files changed, 87 insertions(+), 12 deletions(-)

diff --git 
a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py 
b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
index d5cf3ee29363a..50e648befa65b 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
+++ b/lldb/test/API/terminal/hidden_frame_markers/TestHiddenFrameMarkers.py
@@ -14,14 +14,14 @@ def test_hidden_frame_markers(self):
         """Test that hidden frame markers are rendered in backtraces"""
         self.build()
         lldbutil.run_to_source_breakpoint(
-            self, "// break here", lldb.SBFileSpec("main.cpp")
+            self, "// break here first", lldb.SBFileSpec("main.cpp")
         )
         self.expect(
             "bt",
             substrs=[
                 "   * frame #0:",
-                "  ﹍ frame #2:",
-                "  ﹉ frame #3:",
+                "  ﹉ frame #2:",
+                "     frame #3:",
                 "     frame #4:",
             ],
         )
@@ -30,9 +30,9 @@ def test_hidden_frame_markers(self):
         self.expect(
             "bt",
             substrs=[
-                "     frame #0:",
+                "  ﹍ frame #0:",
                 "   * frame #2:",
-                "  ﹉ frame #3:",
+                "     frame #3:",
                 "     frame #4:",
             ],
         )
@@ -41,14 +41,80 @@ def test_hidden_frame_markers(self):
         self.expect(
             "bt",
             substrs=[
-                "     frame #0:",
-                "  ﹍ frame #2:",
+                "  ﹍ frame #0:",
+                "  ﹉ frame #2:",
                 "   * frame #3:",
                 "     frame #4:",
             ],
         )
 
-    def test_hidden_frame_markers(self):
+    @unicode_test
+    def test_nested_hidden_frame_markers(self):
+        """Test that nested hidden frame markers are rendered in backtraces"""
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "// break here after", lldb.SBFileSpec("main.cpp")
+        )
+        self.expect(
+            "bt",
+            substrs=[
+                "   * frame #0:",
+                "  ﹉ frame #2:",
+                "  ﹍ frame #3:",
+                "  ﹉ frame #5:",
+                "     frame #6:",
+            ],
+        )
+
+        self.runCmd("f 2")
+        self.expect(
+            "bt",
+            substrs=[
+                "  ﹍ frame #0:",
+                "   * frame #2:",
+                "  ﹍ frame #3:",
+                "  ﹉ frame #5:",
+                "     frame #6:",
+            ],
+        )
+
+        self.runCmd("f 3")
+        self.expect(
+            "bt",
+            substrs=[
+                "  ﹍ frame #0:",
+                "  ﹉ frame #2:",
+                "   * frame #3:",
+                "  ﹉ frame #5:",
+                "     frame #6:",
+            ],
+        )
+
+        self.runCmd("f 5")
+        self.expect(
+            "bt",
+            substrs=[
+                "  ﹍ frame #0:",
+                "  ﹉ frame #2:",
+                "  ﹍ frame #3:",
+                "   * frame #5:",
+                "     frame #6:",
+            ],
+        )
+
+        self.runCmd("f 6")
+        self.expect(
+            "bt",
+            substrs=[
+                "  ﹍ frame #0:",
+                "  ﹉ frame #2:",
+                "  ﹍ frame #3:",
+                "  ﹉ frame #5:",
+                "   * frame #6:",
+            ],
+        )
+
+    def test_deactivated_hidden_frame_markers(self):
         """
         Test that hidden frame markers are not rendered in backtraces when
         mark-hidden-frames is set to false
@@ -56,7 +122,7 @@ def test_hidden_frame_markers(self):
         self.build()
         self.runCmd("settings set mark-hidden-frames 0")
         lldbutil.run_to_source_breakpoint(
-            self, "// break here", lldb.SBFileSpec("main.cpp")
+            self, "// break here first", lldb.SBFileSpec("main.cpp")
         )
         self.expect(
             "bt",
diff --git a/lldb/test/API/terminal/hidden_frame_markers/main.cpp 
b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
index 874e4034dc053..0523d3cacf581 100644
--- a/lldb/test/API/terminal/hidden_frame_markers/main.cpp
+++ b/lldb/test/API/terminal/hidden_frame_markers/main.cpp
@@ -1,15 +1,24 @@
-static void foo() {
-  int a = 0; // break here
-}
+void foo();
+void bar();
 
 namespace std {
 namespace __1 {
 void __test_hidden_frame() { foo(); }
+void __test_nested_hidden_frame() { bar(); }
 
 void outer_function() { __test_hidden_frame(); }
+void other_outer_function() { __test_nested_hidden_frame(); }
 } // namespace __1
 } // namespace std
 
+void foo() {
+  std::__1::other_outer_function(); // break here first
+}
+
+void bar() {
+  int a = 0; // break here after
+}
+
 int main() {
   std::__1::outer_function();
   return 0;

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

Reply via email to