llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Med Ismail Bennani (medismailben)

<details>
<summary>Changes</summary>

This patch allows threads to have multiple SyntheticFrameProviderSP instances 
that chain together sequentially. Each provider receives the output of the 
previous provider as input, creating a transformation pipeline.

It changes `Thread::m_frame_provider_sp` to a vector, adds provider parameter 
to SyntheticStackFrameList to avoid calling back into 
`Thread::GetFrameProvider()` during frame fetching, updated 
`LoadScriptedFrameProvider()` to chain providers by wrapping each previous 
provider's output in a `SyntheticStackFrameList` for the next provider and 
finally, loads ALL matching providers in priority order instead of just the 
first one.

The chaining works as follows:
```
  Real Unwinder Frames
      ↓
  Provider 1 (priority 10) → adds/transforms frames
      ↓
  Provider 2 (priority 20) → transforms Provider 1's output
      ↓
  Provider 3 (priority 30) → transforms Provider 2's output
      ↓
  Final frame list shown to user
  ```

This patch also adds a test for this (test_chained_frame_providers) to verify 
that 3 providers chain correctly: `AddFooFrameProvider`, `AddBarFrameProvider`, 
`AddBazFrameProvider`.

---

Patch is 26.49 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/172849.diff


14 Files Affected:

- (modified) lldb/examples/python/templates/scripted_frame_provider.py (+28) 
- (modified) 
lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h (+16) 
- (modified) lldb/include/lldb/Target/StackFrameList.h (+5-1) 
- (modified) lldb/include/lldb/Target/SyntheticFrameProvider.h (+21) 
- (modified) lldb/include/lldb/Target/Thread.h (+4-4) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp
 (+18) 
- (modified) 
lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h
 (+2) 
- (modified) 
lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.cpp
 (+7) 
- (modified) 
lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.h
 (+2) 
- (modified) lldb/source/Target/StackFrameList.cpp (+7-6) 
- (modified) lldb/source/Target/SyntheticFrameProvider.cpp (+14) 
- (modified) lldb/source/Target/Thread.cpp (+56-28) 
- (modified) 
lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
 (+92) 
- (modified) 
lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py 
(+78) 


``````````diff
diff --git a/lldb/examples/python/templates/scripted_frame_provider.py 
b/lldb/examples/python/templates/scripted_frame_provider.py
index 7a72f1a24c9da..a45ef9427a532 100644
--- a/lldb/examples/python/templates/scripted_frame_provider.py
+++ b/lldb/examples/python/templates/scripted_frame_provider.py
@@ -79,6 +79,34 @@ def get_description(self):
         """
         pass
 
+    @staticmethod
+    def get_priority():
+        """Get the priority of this frame provider.
+
+        This static method is called to determine the evaluation order when
+        multiple frame providers could apply to the same thread. Lower numbers
+        indicate higher priority (like Unix nice values).
+
+        Returns:
+            int or None: Priority value where 0 is highest priority.
+                Return None for default priority (UINT32_MAX - lowest 
priority).
+
+        Example:
+
+        .. code-block:: python
+
+            @staticmethod
+            def get_priority():
+                # High priority - runs before most providers
+                return 10
+
+            @staticmethod
+            def get_priority():
+                # Default priority - runs last
+                return None
+        """
+        return None  # Default/lowest priority
+
     def __init__(self, input_frames, args):
         """Construct a scripted frame provider.
 
diff --git 
a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h 
b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h
index 49b60131399d5..b04af0c817b6e 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h
@@ -39,6 +39,22 @@ class ScriptedFrameProviderInterface : public 
ScriptedInterface {
   ///         empty string if no description is available.
   virtual std::string GetDescription(llvm::StringRef class_name) { return {}; }
 
+  /// Get the priority of this frame provider.
+  ///
+  /// This is called by the descriptor to fetch the priority from the
+  /// scripted implementation. Implementations should call a static method
+  /// on the scripting class to retrieve the priority. Lower numbers indicate
+  /// higher priority (like Unix nice values).
+  ///
+  /// \param class_name The name of the scripting class implementing the
+  /// provider.
+  ///
+  /// \return Priority value where 0 is highest priority, or std::nullopt for
+  ///         default priority (UINT32_MAX - lowest priority).
+  virtual std::optional<uint32_t> GetPriority(llvm::StringRef class_name) {
+    return std::nullopt;
+  }
+
   virtual StructuredData::ObjectSP GetFrameAtIndex(uint32_t index) {
     return {};
   }
diff --git a/lldb/include/lldb/Target/StackFrameList.h 
b/lldb/include/lldb/Target/StackFrameList.h
index 539c070ff0f4b..42a0be9b196b9 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -243,7 +243,8 @@ class SyntheticStackFrameList : public StackFrameList {
 public:
   SyntheticStackFrameList(Thread &thread, lldb::StackFrameListSP input_frames,
                           const lldb::StackFrameListSP &prev_frames_sp,
-                          bool show_inline_frames);
+                          bool show_inline_frames,
+                          lldb::SyntheticFrameProviderSP provider);
 
 protected:
   /// Override FetchFramesUpTo to lazily return frames from the provider
@@ -255,6 +256,9 @@ class SyntheticStackFrameList : public StackFrameList {
   /// The input stack frame list that the provider transforms.
   /// This could be a real StackFrameList or another SyntheticStackFrameList.
   lldb::StackFrameListSP m_input_frames;
+
+  /// The provider that transforms the input frames.
+  lldb::SyntheticFrameProviderSP m_provider;
 };
 
 } // namespace lldb_private
diff --git a/lldb/include/lldb/Target/SyntheticFrameProvider.h 
b/lldb/include/lldb/Target/SyntheticFrameProvider.h
index 2d5330cb03105..bbd52b144412d 100644
--- a/lldb/include/lldb/Target/SyntheticFrameProvider.h
+++ b/lldb/include/lldb/Target/SyntheticFrameProvider.h
@@ -56,6 +56,16 @@ struct ScriptedFrameProviderDescriptor {
   ///         empty string if no description is available.
   std::string GetDescription() const;
 
+  /// Get the priority of this frame provider.
+  ///
+  /// Priority determines the order in which providers are evaluated when
+  /// multiple providers could apply to the same thread. Lower numbers indicate
+  /// higher priority (like Unix nice values).
+  ///
+  /// \return Priority value where 0 is highest priority, or std::nullopt for
+  ///         default priority (UINT32_MAX - lowest priority).
+  std::optional<uint32_t> GetPriority() const;
+
   /// Check if this descriptor applies to the given thread.
   bool AppliesToThread(Thread &thread) const {
     // If no thread specs specified, applies to all threads.
@@ -143,6 +153,17 @@ class SyntheticFrameProvider : public PluginInterface {
 
   virtual std::string GetDescription() const = 0;
 
+  /// Get the priority of this frame provider.
+  ///
+  /// Priority determines the order in which providers are evaluated when
+  /// multiple providers could apply to the same thread. Lower numbers indicate
+  /// higher priority (like Unix nice values).
+  ///
+  /// \return
+  ///     Priority value where 0 is highest priority, or std::nullopt for
+  ///     default priority (UINT32_MAX - lowest priority).
+  virtual std::optional<uint32_t> GetPriority() const { return std::nullopt; }
+
   /// Get a single stack frame at the specified index.
   ///
   /// This method is called lazily - frames are only created when requested.
diff --git a/lldb/include/lldb/Target/Thread.h 
b/lldb/include/lldb/Target/Thread.h
index 46ce192556756..808bb024d4d64 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -1302,8 +1302,8 @@ class Thread : public 
std::enable_shared_from_this<Thread>,
 
   void ClearScriptedFrameProvider();
 
-  lldb::SyntheticFrameProviderSP GetFrameProvider() const {
-    return m_frame_provider_sp;
+  const std::vector<lldb::SyntheticFrameProviderSP> &GetFrameProviders() const 
{
+    return m_frame_providers;
   }
 
 protected:
@@ -1409,8 +1409,8 @@ class Thread : public 
std::enable_shared_from_this<Thread>,
   /// The Thread backed by this thread, if any.
   lldb::ThreadWP m_backed_thread;
 
-  /// The Scripted Frame Provider, if any.
-  lldb::SyntheticFrameProviderSP m_frame_provider_sp;
+  /// The Scripted Frame Providers for this thread.
+  std::vector<lldb::SyntheticFrameProviderSP> m_frame_providers;
 
 private:
   bool m_extended_info_fetched; // Have we tried to retrieve the 
m_extended_info
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp
index 3dde5036453f4..2d87c1b10bfec 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.cpp
@@ -70,6 +70,24 @@ std::string 
ScriptedFrameProviderPythonInterface::GetDescription(
   return obj->GetStringValue().str();
 }
 
+std::optional<uint32_t>
+ScriptedFrameProviderPythonInterface::GetPriority(llvm::StringRef class_name) {
+  Status error;
+  StructuredData::ObjectSP obj =
+      CallStaticMethod(class_name, "get_priority", error);
+
+  if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
+                                                    error))
+    return std::nullopt;
+
+  // Try to extract as unsigned integer. Return nullopt if Python returned None
+  // or if extraction fails.
+  if (StructuredData::UnsignedInteger *int_obj = obj->GetAsUnsignedInteger())
+    return static_cast<uint32_t>(int_obj->GetValue());
+
+  return std::nullopt;
+}
+
 StructuredData::ObjectSP
 ScriptedFrameProviderPythonInterface::GetFrameAtIndex(uint32_t index) {
   Status error;
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h
index 97a5cc7c669ea..884b0355a659e 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFrameProviderPythonInterface.h
@@ -43,6 +43,8 @@ class ScriptedFrameProviderPythonInterface
 
   std::string GetDescription(llvm::StringRef class_name) override;
 
+  std::optional<uint32_t> GetPriority(llvm::StringRef class_name) override;
+
   StructuredData::ObjectSP GetFrameAtIndex(uint32_t index) override;
 
   static void Initialize();
diff --git 
a/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.cpp
 
b/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.cpp
index 739963e6f0c2f..4aad8f2cb628f 100644
--- 
a/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.cpp
+++ 
b/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.cpp
@@ -106,6 +106,13 @@ std::string ScriptedFrameProvider::GetDescription() const {
   return m_interface_sp->GetDescription(m_descriptor.GetName());
 }
 
+std::optional<uint32_t> ScriptedFrameProvider::GetPriority() const {
+  if (!m_interface_sp)
+    return std::nullopt;
+
+  return m_interface_sp->GetPriority(m_descriptor.GetName());
+}
+
 llvm::Expected<StackFrameSP>
 ScriptedFrameProvider::GetFrameAtIndex(uint32_t idx) {
   if (!m_interface_sp)
diff --git 
a/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.h
 
b/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.h
index 3434bf26ade24..6937f9acbc9a9 100644
--- 
a/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.h
+++ 
b/lldb/source/Plugins/SyntheticFrameProvider/ScriptedFrameProvider/ScriptedFrameProvider.h
@@ -40,6 +40,8 @@ class ScriptedFrameProvider : public SyntheticFrameProvider {
 
   std::string GetDescription() const override;
 
+  std::optional<uint32_t> GetPriority() const override;
+
   /// Get a single stack frame at the specified index.
   llvm::Expected<lldb::StackFrameSP> GetFrameAtIndex(uint32_t idx) override;
 
diff --git a/lldb/source/Target/StackFrameList.cpp 
b/lldb/source/Target/StackFrameList.cpp
index 896a760f61d26..b1af2bb65494a 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -58,23 +58,24 @@ StackFrameList::~StackFrameList() {
 
 SyntheticStackFrameList::SyntheticStackFrameList(
     Thread &thread, lldb::StackFrameListSP input_frames,
-    const lldb::StackFrameListSP &prev_frames_sp, bool show_inline_frames)
+    const lldb::StackFrameListSP &prev_frames_sp, bool show_inline_frames,
+    lldb::SyntheticFrameProviderSP provider)
     : StackFrameList(thread, prev_frames_sp, show_inline_frames),
-      m_input_frames(std::move(input_frames)) {}
+      m_input_frames(std::move(input_frames)), m_provider(std::move(provider)) 
{
+}
 
 bool SyntheticStackFrameList::FetchFramesUpTo(
     uint32_t end_idx, InterruptionControl allow_interrupt) {
 
   size_t num_synthetic_frames = 0;
-  // Check if the thread has a synthetic frame provider.
-  if (auto provider_sp = m_thread.GetFrameProvider()) {
-    // Use the synthetic frame provider to generate frames lazily.
+  // Use the provider to generate frames lazily.
+  if (m_provider) {
     // Keep fetching until we reach end_idx or the provider returns an error.
     for (uint32_t idx = m_frames.size(); idx <= end_idx; idx++) {
       if (allow_interrupt &&
           
m_thread.GetProcess()->GetTarget().GetDebugger().InterruptRequested())
         return true;
-      auto frame_or_err = provider_sp->GetFrameAtIndex(idx);
+      auto frame_or_err = m_provider->GetFrameAtIndex(idx);
       if (!frame_or_err) {
         // Provider returned error - we've reached the end.
         LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), frame_or_err.takeError(),
diff --git a/lldb/source/Target/SyntheticFrameProvider.cpp 
b/lldb/source/Target/SyntheticFrameProvider.cpp
index 97ff42d1ed53e..e799ad23b7512 100644
--- a/lldb/source/Target/SyntheticFrameProvider.cpp
+++ b/lldb/source/Target/SyntheticFrameProvider.cpp
@@ -34,6 +34,13 @@ void ScriptedFrameProviderDescriptor::Dump(Stream *s) const {
   if (!description.empty())
     s->Printf("  Description: %s\n", description.c_str());
 
+  // Show priority information.
+  std::optional<uint32_t> priority = GetPriority();
+  if (priority.has_value())
+    s->Printf("  Priority: %u\n", *priority);
+  else
+    s->PutCString("  Priority: Default (no priority specified)\n");
+
   // Show thread filter information.
   if (thread_specs.empty()) {
     s->PutCString("  Thread Filter: (applies to all threads)\n");
@@ -62,6 +69,13 @@ std::string 
ScriptedFrameProviderDescriptor::GetDescription() const {
   return {};
 }
 
+std::optional<uint32_t> ScriptedFrameProviderDescriptor::GetPriority() const {
+  // If we have an interface, call get_priority() to fetch it.
+  if (interface_sp && scripted_metadata_sp)
+    return interface_sp->GetPriority(scripted_metadata_sp->GetClassName());
+  return std::nullopt;
+}
+
 llvm::Expected<SyntheticFrameProviderSP> 
SyntheticFrameProvider::CreateInstance(
     StackFrameListSP input_frames,
     const ScriptedFrameProviderDescriptor &descriptor) {
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index b40e753aca1e9..53ce687fdace3 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -262,7 +262,7 @@ void Thread::DestroyThread() {
   std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
   m_curr_frames_sp.reset();
   m_prev_frames_sp.reset();
-  m_frame_provider_sp.reset();
+  m_frame_providers.clear();
   m_prev_framezero_pc.reset();
 }
 
@@ -1448,33 +1448,51 @@ StackFrameListSP Thread::GetStackFrameList() {
   if (m_curr_frames_sp)
     return m_curr_frames_sp;
 
-  // First, try to load a frame provider if we don't have one yet.
-  if (!m_frame_provider_sp) {
+  // First, try to load frame providers if we don't have any yet.
+  if (m_frame_providers.empty()) {
     ProcessSP process_sp = GetProcess();
     if (process_sp) {
       Target &target = process_sp->GetTarget();
       const auto &descriptors = target.GetScriptedFrameProviderDescriptors();
 
-      // Find first descriptor that applies to this thread.
+      // Collect all descriptors that apply to this thread.
+      std::vector<const ScriptedFrameProviderDescriptor *>
+          applicable_descriptors;
       for (const auto &entry : descriptors) {
         const ScriptedFrameProviderDescriptor &descriptor = entry.second;
         if (descriptor.IsValid() && descriptor.AppliesToThread(*this)) {
-          if (llvm::Error error = LoadScriptedFrameProvider(descriptor)) {
-            LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(error),
-                           "Failed to load scripted frame provider: {0}");
-          }
-          break; // Use first matching descriptor (success or failure).
+          applicable_descriptors.push_back(&descriptor);
+        }
+      }
+
+      // Sort by priority (lower number = higher priority).
+      std::sort(applicable_descriptors.begin(), applicable_descriptors.end(),
+                [](const ScriptedFrameProviderDescriptor *a,
+                   const ScriptedFrameProviderDescriptor *b) {
+                  // nullopt (no priority) sorts last (UINT32_MAX).
+                  uint32_t priority_a = a->GetPriority().value_or(UINT32_MAX);
+                  uint32_t priority_b = b->GetPriority().value_or(UINT32_MAX);
+                  return priority_a < priority_b;
+                });
+
+      // Load ALL matching providers in priority order.
+      for (const auto *descriptor : applicable_descriptors) {
+        if (llvm::Error error = LoadScriptedFrameProvider(*descriptor)) {
+          LLDB_LOG_ERROR(GetLog(LLDBLog::Thread), std::move(error),
+                         "Failed to load scripted frame provider: {0}");
+          continue; // Try next provider if this one fails.
         }
       }
     }
   }
 
-  // Create the frame list based on whether we have a provider.
-  if (m_frame_provider_sp) {
-    // We have a provider - create synthetic frame list.
-    StackFrameListSP input_frames = m_frame_provider_sp->GetInputFrames();
+  // Create the frame list based on whether we have providers.
+  if (!m_frame_providers.empty()) {
+    // We have providers - use the last one in the chain.
+    // The last provider has already been chained with all previous providers.
+    StackFrameListSP input_frames = m_frame_providers.back()->GetInputFrames();
     m_curr_frames_sp = std::make_shared<SyntheticStackFrameList>(
-        *this, input_frames, m_prev_frames_sp, true);
+        *this, input_frames, m_prev_frames_sp, true, m_frame_providers.back());
   } else {
     // No provider - use normal unwinder frames.
     m_curr_frames_sp =
@@ -1488,29 +1506,39 @@ llvm::Error Thread::LoadScriptedFrameProvider(
     const ScriptedFrameProviderDescriptor &descriptor) {
   std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
 
-  // Note: We don't create input_frames here - it will be created lazily
-  // by SyntheticStackFrameList when frames are first fetched.
-  // Creating them too early can cause crashes during thread initialization.
-
-  // Create a temporary StackFrameList just to get the thread reference for the
-  // provider. The provider won't actually use this - it will get real input
-  // frames from SyntheticStackFrameList later.
-  StackFrameListSP temp_frames =
-      std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true);
+  // Create input frames for this provider:
+  // - If no providers exist yet, use real unwinder frames
+  // - If providers exist, wrap the previous provider in a
+  // SyntheticStackFrameList
+  //   This creates the chain: each provider's OUTPUT becomes the next
+  //   provider's INPUT
+  StackFrameListSP input_frames;
+  if (m_frame_providers.empty()) {
+    // First provider gets real unwinder frames
+    input_frames =
+        std::make_shared<StackFrameList>(*this, m_prev_frames_sp, true);
+  } else {
+    // Subsequent providers get the previous provider's OUTPUT
+    // We create a SyntheticStackFrameList that wraps the previous provider
+    SyntheticFrameProviderSP prev_provider = m_frame_providers.back();
+    StackFrameListSP prev_input = prev_provider->GetInputFrames();
+    input_frames = std::make_shared<SyntheticStackFrameList>(
+        *this, prev_input, m_prev_frames_sp, true, prev_provider);
+  }
 
   auto provider_or_err =
-      SyntheticFrameProvider::CreateInstance(temp_frames, descriptor);
+      SyntheticFrameProvider::CreateInstance(input_frames, descriptor);
   if (!provider_or_err)
     return provider_or_err.takeError();
 
-  ClearScriptedFrameProvider();
-  m_frame_provider_sp = *provider_or_err;
+  // Append to the chain
+  m_frame_providers.push_back(*provider_or_err);
   return llvm::Error::success();
 }
 
 void Thread::ClearScriptedFrameProvider() {
   std::lock_guard<std::recursive_mutex> guard(m_frame_mutex);
-  m_frame_provider_sp.reset();
+  m_frame_providers.clear();
   m_curr_frames_sp.reset();
   m_prev_frames_sp.reset();
 }
@@ -1535,7 +1563,7 @@ void Thread::ClearStackFrames() {
     m_prev_frames_sp.swap(m_curr_frames_sp);
   m_curr_frames_sp.reset();
 
-  m_frame_provider_sp.reset();
+  m_frame_providers.clear();
   m_extended_info.reset();
   m_extended_info_fetched = false;
 }
diff --git 
a/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
 
b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
index e2b0f0f9cd50d..08991d42cef47 100644
--- 
a/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
+++ 
b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
@@ -638,3 +638,95 @@ def test_valid_pc_no_module_frames(self):
         frame2 = thread.GetFrameAtIndex(2)
         self.assertIsNotNone(frame2)
         self.assertIn("thread_func", frame2.GetFunctionName())
+
+    def te...
[truncated]

``````````

</details>


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

Reply via email to