https://github.com/Nerixyz updated 
https://github.com/llvm/llvm-project/pull/204431

>From fb9e6efa387e56ba69d15bdf46e5764621913a9d Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Wed, 17 Jun 2026 21:44:16 +0200
Subject: [PATCH 1/6] [lldb] Treat synthetic variables as locals

---
 .../Process/scripted/ScriptedFrame.cpp        |  5 ++--
 .../TestScriptedFrameProvider.py              | 25 ++++++++++++++++---
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp 
b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
index 72a7169d01188..2bb47dd29c2df 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -307,10 +307,11 @@ void ScriptedFrame::PopulateVariableListFromInterface(
 
     VariableSP var = v->GetVariable();
     if (!var && include_synthetic_vars) {
-      // Construct the value type as an synthetic verison of what the value 
type
+      // Construct the value type as an synthetic version of what the value 
type
       // is. That'll allow the user to tell the scope and the 'synthetic-ness'
       // of the variable.
-      lldb::ValueType vt = GetSyntheticValueType(v->GetValueType());
+      // Any variable we create here will be treated as a local variable.
+      lldb::ValueType vt = GetSyntheticValueType(eValueTypeVariableLocal);
 
       // Just make up a variable - the frame variable dumper just passes it
       // back in to GetValueObjectForFrameVariable, so we really just need to
diff --git 
a/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
 
b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
index 597447723047e..b715d99964569 100644
--- 
a/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
+++ 
b/lldb/test/API/functionalities/scripted_frame_provider/TestScriptedFrameProvider.py
@@ -824,26 +824,43 @@ def test_get_values(self):
         options = lldb.SBVariablesOptions()
         options.SetIncludeSynthetic(True)
         variables = frame0.GetVariables(options)
+        self.assertFalse(variables.IsValid())
+        self.assertEqual(variables.GetSize(), 0)
+
+        options.SetIncludeLocals(True)
+        variables = frame0.GetVariables(options)
         self.assertTrue(variables.IsValid())
-        self.assertTrue(variables.GetValueAtIndex(0).name == "_handler_one")
+        self.assertEqual(variables.GetSize(), 2)
+        self.assertEqual(variables.GetValueAtIndex(0).name, "variable_in_main")
+        self.assertEqual(variables.GetValueAtIndex(1).name, "_handler_one")
 
         # Ensure that we get synthetic variables in the other overloads.
         # (arguments, locals, statics, in_scope_only)
         variables = frame0.GetVariables(False, False, False, False)
+        self.assertFalse(variables.IsValid())
+        self.assertEqual(variables.GetSize(), 0)
+        variables = frame0.GetVariables(False, True, False, False)
         self.assertTrue(variables.IsValid())
-        self.assertTrue(variables.GetValueAtIndex(0).name == "_handler_one")
+        self.assertEqual(variables.GetSize(), 2)
+        self.assertEqual(variables.GetValueAtIndex(0).name, "variable_in_main")
+        self.assertEqual(variables.GetValueAtIndex(1).name, "_handler_one")
 
         # (arguments, locals, statics, in_scope_only, use_dynamic)
         variables = frame0.GetVariables(
-            False, False, False, False, lldb.eNoDynamicValues
+            False, True, False, False, lldb.eNoDynamicValues
         )
         self.assertTrue(variables.IsValid())
-        self.assertTrue(variables.GetValueAtIndex(0).name == "_handler_one")
+        self.assertEqual(variables.GetSize(), 2)
+        self.assertEqual(variables.GetValueAtIndex(0).name, "variable_in_main")
+        self.assertEqual(variables.GetValueAtIndex(1).name, "_handler_one")
 
         # FIXME: Synthetic variables are never in scope.
         variables = frame0.GetVariables(False, False, False, True)
         self.assertFalse(variables.IsValid())
         self.assertEqual(variables.GetSize(), 0)
+        variables = frame0.GetVariables(False, True, False, True)
+        self.assertFalse(variables.IsValid())
+        self.assertEqual(variables.GetSize(), 0)
 
         # Check the `frame variable` command(s) handle synthetic variables the
         # way we expect by printing them.

>From 49965ff92280208c435f224732df48f7d18754fd Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Wed, 24 Jun 2026 17:52:51 +0200
Subject: [PATCH 2/6] refactor: Ask the frame what value type it wants

---
 .../Interfaces/ScriptedFrameInterface.h       |  5 ++
 .../Process/scripted/ScriptedFrame.cpp        | 50 ++++++++++---------
 .../ScriptedFramePythonInterface.cpp          | 16 ++++++
 .../Interfaces/ScriptedFramePythonInterface.h |  3 ++
 .../Interfaces/ScriptedPythonInterface.cpp    | 21 ++++++++
 .../Interfaces/ScriptedPythonInterface.h      |  5 ++
 .../test_frame_providers.py                   |  5 ++
 7 files changed, 82 insertions(+), 23 deletions(-)

diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h 
b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h
index 00994d65fd601..43914ef705dbf 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h
@@ -53,6 +53,11 @@ class ScriptedFrameInterface : virtual public 
ScriptedInterface {
 
   virtual lldb::ValueObjectListSP GetVariables() { return nullptr; }
 
+  virtual std::optional<lldb::ValueType>
+  GetValueTypeForVariable(lldb::ValueObjectSP value) {
+    return std::nullopt;
+  }
+
   virtual lldb::ValueObjectSP
   GetValueObjectForVariableExpression(llvm::StringRef expr, uint32_t options,
                                       Status &error) {
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp 
b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
index 2bb47dd29c2df..8adc69b1f6cc6 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -300,35 +300,39 @@ void ScriptedFrame::PopulateVariableListFromInterface(
 
   // Convert what we can into a variable.
   m_variable_list_sp = std::make_shared<VariableList>();
+
   for (uint32_t i = 0, e = value_list_sp->GetSize(); i < e; ++i) {
     ValueObjectSP v = value_list_sp->GetValueObjectAtIndex(i);
     if (!v)
       continue;
 
-    VariableSP var = v->GetVariable();
-    if (!var && include_synthetic_vars) {
-      // Construct the value type as an synthetic version of what the value 
type
-      // is. That'll allow the user to tell the scope and the 'synthetic-ness'
-      // of the variable.
-      // Any variable we create here will be treated as a local variable.
-      lldb::ValueType vt = GetSyntheticValueType(eValueTypeVariableLocal);
-
-      // Just make up a variable - the frame variable dumper just passes it
-      // back in to GetValueObjectForFrameVariable, so we really just need to
-      // make sure the name and type are correct. We create IDs based on
-      // value_list_sp in order to make sure they're unique.
-      var = std::make_shared<lldb_private::Variable>(
-          (lldb::user_id_t)value_list_sp->GetSize() + i,
-          v->GetName().GetCString(), v->GetName().GetCString(), nullptr, vt,
-          /*owner_scope=*/nullptr,
-          /*scope_range=*/Variable::RangeList{},
-          /*decl=*/nullptr, DWARFExpressionList{}, /*external=*/false,
-          /*artificial=*/true, /*location_is_constant_data=*/false);
-    }
+    // Ask the interface about the value type of this variable. If it doesn't
+    // specify any, use the original value type. If we encounter a variable, 
use
+    // a non-synthetic type unless it's overwritten.
+    std::optional<lldb::ValueType> desired_vt =
+        GetInterface()->GetValueTypeForVariable(v);
+    lldb::ValueType vt = [&] {
+      if (desired_vt)
+        return GetSyntheticValueType(*desired_vt);
+      if (v->GetVariable())
+        return v->GetValueType();
+      return GetSyntheticValueType(v->GetValueType());
+    }();
+
+    if (IsSyntheticValueType(vt) && !include_synthetic_vars)
+      continue;
 
-    // Only append the variable if we have one (had already, or just created).
-    if (var)
-      m_variable_list_sp->AddVariable(var);
+    // Just make up a variable - the frame variable dumper just passes it
+    // back in to GetValueObjectForFrameVariable, so we really just need to
+    // make sure the name and type are correct. We create IDs based on
+    // value_list_sp in order to make sure they're unique.
+    m_variable_list_sp->AddVariable(std::make_shared<lldb_private::Variable>(
+        (lldb::user_id_t)value_list_sp->GetSize() + i,
+        v->GetName().GetCString(), v->GetName().GetCString(), nullptr, vt,
+        /*owner_scope=*/nullptr,
+        /*scope_range=*/Variable::RangeList{},
+        /*decl=*/nullptr, DWARFExpressionList{}, /*external=*/false,
+        /*artificial=*/true, /*location_is_constant_data=*/false));
   }
 }
 
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp
index de987c3773d88..6cc5ebff2c10b 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.cpp
@@ -11,6 +11,7 @@
 #include "lldb/Host/Config.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Utility/Log.h"
+#include "lldb/ValueObject/ValueObject.h"
 #include "lldb/lldb-enumerations.h"
 
 #include "../SWIGPythonBridge.h"
@@ -163,6 +164,21 @@ lldb::ValueObjectListSP 
ScriptedFramePythonInterface::GetVariables() {
   return vals;
 }
 
+std::optional<lldb::ValueType>
+ScriptedFramePythonInterface::GetValueTypeForVariable(
+    lldb::ValueObjectSP value) {
+  Status error;
+  auto val = Dispatch<std::optional<lldb::ValueType>>(
+      "get_value_type_for_variable", error, std::move(value));
+
+  if (error.Fail()) {
+    return ErrorWithMessage<std::optional<lldb::ValueType>>(
+        LLVM_PRETTY_FUNCTION, error.AsCString(), error);
+  }
+
+  return val;
+}
+
 lldb::ValueObjectSP
 ScriptedFramePythonInterface::GetValueObjectForVariableExpression(
     llvm::StringRef expr, uint32_t options, Status &status) {
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h
index 2e215bbe6aea2..9320c6762b35f 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedFramePythonInterface.h
@@ -51,6 +51,9 @@ class ScriptedFramePythonInterface : public 
ScriptedFrameInterface,
 
   lldb::ValueObjectListSP GetVariables() override;
 
+  std::optional<lldb::ValueType>
+  GetValueTypeForVariable(lldb::ValueObjectSP value) override;
+
   lldb::ValueObjectSP
   GetValueObjectForVariableExpression(llvm::StringRef expr, uint32_t options,
                                       Status &status) override;
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 84dbbbe7270d8..25d0c0dac5be0 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -322,3 +322,24 @@ 
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectListSP>(
 
   return out;
 }
+
+template <>
+std::optional<lldb::ValueType>
+ScriptedPythonInterface::ExtractValueFromPythonObject<
+    std::optional<lldb::ValueType>>(python::PythonObject &p, Status &error) {
+  if (p.IsNone())
+    return std::nullopt;
+
+  llvm::Expected<unsigned long long> val = p.AsUnsignedLongLong();
+  if (!val) {
+    error = Status::FromError(val.takeError());
+    return std::nullopt;
+  }
+  if (*val > std::numeric_limits<std::underlying_type_t<ValueType>>::max()) {
+    error =
+        Status::FromErrorStringWithFormatv("value too large (got {0})", *val);
+    return std::nullopt;
+  }
+
+  return static_cast<ValueType>(*val);
+}
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index 28ed5745ca55f..7d0d4cdd3c6d1 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -836,6 +836,11 @@ lldb::ValueObjectListSP
 ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectListSP>(
     python::PythonObject &p, Status &error);
 
+template <>
+std::optional<lldb::ValueType>
+ScriptedPythonInterface::ExtractValueFromPythonObject<
+    std::optional<lldb::ValueType>>(python::PythonObject &p, Status &error);
+
 } // namespace lldb_private
 
 #endif // 
LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H
diff --git 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
index f9f673f80abcf..91b3830fd195f 100644
--- 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
+++ 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
@@ -554,6 +554,11 @@ def is_hidden(self):
     def get_register_context(self):
         """No register context."""
         return None
+    
+    def get_value_type_for_variable(self, var):
+        if var.GetName() == "_handler_one":
+            return lldb.eValueTypeVariableLocal
+        return None # Inherit the value type for others.
 
     def get_variables(self):
         """"""

>From e76abb5fa54d6fb33cbd9c7001c046b5c88fe7c5 Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Wed, 24 Jun 2026 17:57:39 +0200
Subject: [PATCH 3/6] fix: formatting

---
 .../scripted_frame_provider/test_frame_providers.py           | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
index 91b3830fd195f..13a7d152f87ed 100644
--- 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
+++ 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
@@ -554,11 +554,11 @@ def is_hidden(self):
     def get_register_context(self):
         """No register context."""
         return None
-    
+
     def get_value_type_for_variable(self, var):
         if var.GetName() == "_handler_one":
             return lldb.eValueTypeVariableLocal
-        return None # Inherit the value type for others.
+        return None  # Inherit the value type for others.
 
     def get_variables(self):
         """"""

>From 0017be2659a048796eea301cc52ccef29799d0a5 Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Wed, 24 Jun 2026 21:00:48 +0200
Subject: [PATCH 4/6] fix: use maximum value type

---
 lldb/include/lldb/lldb-enumerations.h                       | 2 ++
 .../Python/Interfaces/ScriptedPythonInterface.cpp           | 6 +++---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/lldb/include/lldb/lldb-enumerations.h 
b/lldb/include/lldb/lldb-enumerations.h
index 32a341b354d9f..0480e115cd771 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -389,6 +389,8 @@ enum ValueType : uint32_t {
   eValueTypeVTable = 9,
   /// function pointer in virtual function table
   eValueTypeVTableEntry = 10,
+
+  kLastValueType = eValueTypeVTableEntry
 };
 
 /// A mask that we can use to check if the value type is synthetic or not.
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 25d0c0dac5be0..0744dbaed9271 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -335,9 +335,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<
     error = Status::FromError(val.takeError());
     return std::nullopt;
   }
-  if (*val > std::numeric_limits<std::underlying_type_t<ValueType>>::max()) {
-    error =
-        Status::FromErrorStringWithFormatv("value too large (got {0})", *val);
+  if (*val == eValueTypeInvalid || *val > kLastValueType) {
+    error = Status::FromErrorStringWithFormatv(
+        "value type invalid or too large (got {0})", *val);
     return std::nullopt;
   }
 

>From 7964d076618a3de7ba3b8784f1dc4cc406f9bea9 Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Sat, 27 Jun 2026 13:42:49 +0200
Subject: [PATCH 5/6] refactor: allow python to set the flags

---
 lldb/include/lldb/Utility/ValueType.h            |  6 +++---
 lldb/include/lldb/lldb-enumerations.h            | 16 +++++++++-------
 .../Plugins/Process/scripted/ScriptedFrame.cpp   | 14 +++-----------
 .../Interfaces/ScriptedPythonInterface.cpp       |  8 +++++---
 .../test_frame_providers.py                      |  7 +++++--
 5 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/lldb/include/lldb/Utility/ValueType.h 
b/lldb/include/lldb/Utility/ValueType.h
index 307be07a3fc81..a96768af14439 100644
--- a/lldb/include/lldb/Utility/ValueType.h
+++ b/lldb/include/lldb/Utility/ValueType.h
@@ -15,17 +15,17 @@ namespace lldb_private {
 /// Get the base value type - for when we don't care if the value is synthetic
 /// or not, or when we've already handled that case.
 constexpr lldb::ValueType GetBaseValueType(lldb::ValueType vt) {
-  return lldb::ValueType(vt & ~lldb::ValueTypeSyntheticMask);
+  return lldb::ValueType(vt & ~lldb::eValueTypeSyntheticFlag);
 }
 
 /// Given a base value type, return a version that carries the synthetic bit.
 constexpr lldb::ValueType GetSyntheticValueType(lldb::ValueType base) {
-  return lldb::ValueType(base | lldb::ValueTypeSyntheticMask);
+  return lldb::ValueType(base | lldb::eValueTypeSyntheticFlag);
 }
 
 /// Return true if vt represents a synthetic value, false if not.
 constexpr bool IsSyntheticValueType(lldb::ValueType vt) {
-  return vt & lldb::ValueTypeSyntheticMask;
+  return vt & lldb::eValueTypeSyntheticFlag;
 }
 } // namespace lldb_private
 
diff --git a/lldb/include/lldb/lldb-enumerations.h 
b/lldb/include/lldb/lldb-enumerations.h
index 0480e115cd771..c246a4bc915ba 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -390,14 +390,16 @@ enum ValueType : uint32_t {
   /// function pointer in virtual function table
   eValueTypeVTableEntry = 10,
 
-  kLastValueType = eValueTypeVTableEntry
-};
+  kLastValueType = eValueTypeVTableEntry,
+
+  /// A flag that indicates if the value type is synthetic or not.
+  // NOTE: This limits the number of value types to 31, but that's 3x more than
+  // what we currently have now. See lldb/Utility/ValueType.h for helpers for
+  // working with synthetic value types.
+  eValueTypeSyntheticFlag = 0x20,
 
-/// A mask that we can use to check if the value type is synthetic or not.
-// NOTE: This limits the number of value types to 31, but that's 3x more than
-// what we currently have now. See lldb/Utility/ValueType.h for helpers for
-// working with synthetic value types.
-static constexpr unsigned ValueTypeSyntheticMask = 0x20;
+  kValueTypeFlagsMask = eValueTypeSyntheticFlag,
+};
 
 /// Token size/granularities for Input Readers.
 
diff --git a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp 
b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
index 8adc69b1f6cc6..d6288b6eadb1c 100644
--- a/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
+++ b/lldb/source/Plugins/Process/scripted/ScriptedFrame.cpp
@@ -307,17 +307,9 @@ void ScriptedFrame::PopulateVariableListFromInterface(
       continue;
 
     // Ask the interface about the value type of this variable. If it doesn't
-    // specify any, use the original value type. If we encounter a variable, 
use
-    // a non-synthetic type unless it's overwritten.
-    std::optional<lldb::ValueType> desired_vt =
-        GetInterface()->GetValueTypeForVariable(v);
-    lldb::ValueType vt = [&] {
-      if (desired_vt)
-        return GetSyntheticValueType(*desired_vt);
-      if (v->GetVariable())
-        return v->GetValueType();
-      return GetSyntheticValueType(v->GetValueType());
-    }();
+    // specify any, use the original value type.
+    lldb::ValueType vt = GetInterface()->GetValueTypeForVariable(v).value_or(
+        GetSyntheticValueType(v->GetValueType()));
 
     if (IsSyntheticValueType(vt) && !include_synthetic_vars)
       continue;
diff --git 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index 0744dbaed9271..4612b1939b5db 100644
--- 
a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ 
b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -335,11 +335,13 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<
     error = Status::FromError(val.takeError());
     return std::nullopt;
   }
-  if (*val == eValueTypeInvalid || *val > kLastValueType) {
+  unsigned long long unmasked = *val & ~kValueTypeFlagsMask;
+  unsigned long long flags = *val & kValueTypeFlagsMask;
+  if (unmasked == eValueTypeInvalid || unmasked > kLastValueType) {
     error = Status::FromErrorStringWithFormatv(
-        "value type invalid or too large (got {0})", *val);
+        "value type invalid or too large (got {0} | {1:x})", unmasked, flags);
     return std::nullopt;
   }
 
-  return static_cast<ValueType>(*val);
+  return static_cast<ValueType>(unmasked | flags);
 }
diff --git 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
index 13a7d152f87ed..a0da39402ca6d 100644
--- 
a/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
+++ 
b/lldb/test/API/functionalities/scripted_frame_provider/test_frame_providers.py
@@ -556,9 +556,12 @@ def get_register_context(self):
         return None
 
     def get_value_type_for_variable(self, var):
-        if var.GetName() == "_handler_one":
+        name = var.GetName()
+        if name == "_handler_one":
+            return lldb.eValueTypeVariableLocal | lldb.eValueTypeSyntheticFlag
+        if name == "variable_in_main":
             return lldb.eValueTypeVariableLocal
-        return None  # Inherit the value type for others.
+        return None
 
     def get_variables(self):
         """"""

>From 3931734ef4c7863210bf0891782cbc1b0b617b2b Mon Sep 17 00:00:00 2001
From: Nerixyz <[email protected]>
Date: Sat, 27 Jun 2026 14:02:46 +0200
Subject: [PATCH 6/6] fix: add unreachable

---
 lldb/source/Commands/CommandObjectFrame.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lldb/source/Commands/CommandObjectFrame.cpp 
b/lldb/source/Commands/CommandObjectFrame.cpp
index 5c79d758bafd7..5d565709fe6fc 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -568,6 +568,8 @@ may even involve JITing and running code in the target 
program.)");
       // modifiers above that should apply equally to synthetic and normal
       // variables, any other synthetic variable we should default to showing.
       return is_synthetic;
+    case eValueTypeSyntheticFlag:
+      llvm_unreachable("This flag was unset");
     }
     llvm_unreachable("Unexpected scope value");
   }

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

Reply via email to