Index: include/lldb/API/SBValue.h =================================================================== --- include/lldb/API/SBValue.h +++ include/lldb/API/SBValue.h @@ -330,6 +330,9 @@ uint32_t GetNumChildren (); + uint32_t + GetNumChildren (uint32_t max); + void * GetOpaqueType(); Index: include/lldb/Core/ValueObject.h =================================================================== --- include/lldb/Core/ValueObject.h +++ include/lldb/Core/ValueObject.h @@ -595,7 +595,7 @@ GetIndexOfChildWithName (const ConstString &name); size_t - GetNumChildren (); + GetNumChildren (uint32_t max=UINT32_MAX); const Value & GetValue() const; @@ -1204,7 +1204,7 @@ // Should only be called by ValueObject::GetNumChildren() virtual size_t - CalculateNumChildren() = 0; + CalculateNumChildren(uint32_t max=UINT32_MAX) = 0; void SetNumChildren (size_t num_children); Index: include/lldb/Core/ValueObjectCast.h =================================================================== --- include/lldb/Core/ValueObjectCast.h +++ include/lldb/Core/ValueObjectCast.h @@ -35,7 +35,7 @@ GetByteSize() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; lldb::ValueType GetValueType() const override; Index: include/lldb/Core/ValueObjectChild.h =================================================================== --- include/lldb/Core/ValueObjectChild.h +++ include/lldb/Core/ValueObjectChild.h @@ -56,7 +56,7 @@ GetValueType() const override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; ConstString GetTypeName() override; Index: include/lldb/Core/ValueObjectConstResult.h =================================================================== --- include/lldb/Core/ValueObjectConstResult.h +++ include/lldb/Core/ValueObjectConstResult.h @@ -76,7 +76,7 @@ GetValueType() const override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; ConstString GetTypeName() override; Index: include/lldb/Core/ValueObjectDynamicValue.h =================================================================== --- include/lldb/Core/ValueObjectDynamicValue.h +++ include/lldb/Core/ValueObjectDynamicValue.h @@ -41,7 +41,7 @@ GetDisplayTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; lldb::ValueType GetValueType() const override; Index: include/lldb/Core/ValueObjectMemory.h =================================================================== --- include/lldb/Core/ValueObjectMemory.h +++ include/lldb/Core/ValueObjectMemory.h @@ -50,7 +50,7 @@ GetDisplayTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; lldb::ValueType GetValueType() const override; Index: include/lldb/Core/ValueObjectRegister.h =================================================================== --- include/lldb/Core/ValueObjectRegister.h +++ include/lldb/Core/ValueObjectRegister.h @@ -48,7 +48,7 @@ GetDisplayTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; ValueObject * CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; @@ -94,7 +94,7 @@ GetQualifiedTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; ValueObject * CreateChildAtIndex(size_t idx, bool synthetic_array_member, int32_t synthetic_index) override; @@ -148,7 +148,7 @@ GetTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; bool SetValueFromCString(const char *value_str, Error& error) override; Index: include/lldb/Core/ValueObjectSyntheticFilter.h =================================================================== --- include/lldb/Core/ValueObjectSyntheticFilter.h +++ include/lldb/Core/ValueObjectSyntheticFilter.h @@ -49,7 +49,7 @@ MightHaveChildren() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; lldb::ValueType GetValueType() const override; Index: include/lldb/Core/ValueObjectVariable.h =================================================================== --- include/lldb/Core/ValueObjectVariable.h +++ include/lldb/Core/ValueObjectVariable.h @@ -43,7 +43,7 @@ GetDisplayTypeName() override; size_t - CalculateNumChildren() override; + CalculateNumChildren(uint32_t max) override; lldb::ValueType GetValueType() const override; Index: include/lldb/DataFormatters/TypeSynthetic.h =================================================================== --- include/lldb/DataFormatters/TypeSynthetic.h +++ include/lldb/DataFormatters/TypeSynthetic.h @@ -56,13 +56,20 @@ ~SyntheticChildrenFrontEnd () { } - + virtual size_t CalculateNumChildren () = 0; + + virtual size_t + CalculateNumChildren (uint32_t max) + { + auto count = CalculateNumChildren (); + return count <= max ? count : max; + } virtual lldb::ValueObjectSP GetChildAtIndex (size_t idx) = 0; - + virtual size_t GetIndexOfChildWithName (const ConstString &name) = 0; @@ -454,7 +461,7 @@ return lldb::ValueObjectSP(); return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), true); } - + bool Update() override { return false; } @@ -589,13 +596,16 @@ IsValid (); ~FrontEnd() override; - + size_t CalculateNumChildren() override; + + size_t + CalculateNumChildren(uint32_t max) override; lldb::ValueObjectSP GetChildAtIndex(size_t idx) override; - + bool Update() override; Index: include/lldb/Interpreter/ScriptInterpreter.h =================================================================== --- include/lldb/Interpreter/ScriptInterpreter.h +++ include/lldb/Interpreter/ScriptInterpreter.h @@ -349,7 +349,7 @@ } virtual size_t - CalculateNumChildren(const StructuredData::ObjectSP &implementor) + CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) { return 0; } Index: scripts/Python/python-wrapper.swig =================================================================== --- scripts/Python/python-wrapper.swig +++ scripts/Python/python-wrapper.swig @@ -113,9 +113,18 @@ argc GetNumArguments () { - if (m_callable && PyFunction_Check(m_callable)) + PyObject *py_func_obj = NULL; + if (m_callable) { - PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(m_callable); + if (PyMethod_Check(m_callable)) + py_func_obj = PyMethod_GET_FUNCTION(m_callable); + else + py_func_obj = m_callable; + } + + if (py_func_obj) + { + PyCodeObject* code = (PyCodeObject*)PyFunction_GET_CODE(py_func_obj); if (code) { size_t args = code->co_argcount; @@ -632,15 +641,24 @@ SWIGEXPORT size_t LLDBSwigPython_CalculateNumChildren ( - PyObject *implementor + PyObject *implementor, + uint32_t max ) { - size_t ret_val = UINT32_MAX; + size_t ret_val = 0; bool int_match = false; - static char callee_name[] = "num_children"; + PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor, "num_children"); - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, NULL); + if (!pfunc) + return ret_val; + + PyObject* py_return = NULL; + auto argc = pfunc.GetNumArguments(); + if (argc.num_args == 1) + py_return = pfunc(); + else if (argc.num_args == 2) + py_return = pfunc(max); if (!py_return) return ret_val; @@ -675,6 +693,9 @@ PyErr_Clear(); } + if (argc.num_args == 1 && ret_val > max) + ret_val = max; + return ret_val; } Index: scripts/interface/SBValue.i =================================================================== --- scripts/interface/SBValue.i +++ scripts/interface/SBValue.i @@ -238,7 +238,7 @@ GetChildAtIndex (uint32_t idx, lldb::DynamicValueType use_dynamic, bool can_create_synthetic); - + lldb::SBValue CreateChildAtOffset (const char *name, uint32_t offset, lldb::SBType type); @@ -321,6 +321,21 @@ uint32_t GetNumChildren (); + %feature("doctstring", " + //------------------------------------------------------------------ + /// Returns the number for children. + /// + /// @param[in] max + /// If max is less the lldb.UINT32_MAX, then the returned value is + /// capped to max. + /// + /// @return + /// An integer value capped to the argument max. + //------------------------------------------------------------------ + ") GetNumChildren; + uint32_t + GetNumChildren (uint32_t max); + void * GetOpaqueType(); Index: source/API/SBValue.cpp =================================================================== --- source/API/SBValue.cpp +++ source/API/SBValue.cpp @@ -1266,22 +1266,27 @@ uint32_t SBValue::GetNumChildren () { + return GetNumChildren (UINT32_MAX); +} + +uint32_t +SBValue::GetNumChildren (uint32_t max) +{ uint32_t num_children = 0; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); ValueLocker locker; lldb::ValueObjectSP value_sp(GetSP(locker)); if (value_sp) - num_children = value_sp->GetNumChildren(); + num_children = value_sp->GetNumChildren(max); if (log) - log->Printf ("SBValue(%p)::GetNumChildren () => %u", - static_cast(value_sp.get()), num_children); + log->Printf ("SBValue(%p)::GetNumChildren (%u) => %u", + static_cast(value_sp.get()), max, num_children); return num_children; } - SBValue SBValue::Dereference () { Index: source/API/SystemInitializerFull.cpp =================================================================== --- source/API/SystemInitializerFull.cpp +++ source/API/SystemInitializerFull.cpp @@ -149,7 +149,7 @@ bool &got_error); extern "C" size_t -LLDBSwigPython_CalculateNumChildren (void *implementor); +LLDBSwigPython_CalculateNumChildren (void *implementor, uint32_t max); extern "C" void * LLDBSwigPython_GetChildAtIndex (void *implementor, uint32_t idx); Index: source/Core/ValueObject.cpp =================================================================== --- source/Core/ValueObject.cpp +++ source/Core/ValueObject.cpp @@ -770,9 +770,21 @@ size_t -ValueObject::GetNumChildren () +ValueObject::GetNumChildren (uint32_t max) { UpdateValueIfNeeded(); + + if (max < UINT32_MAX) + { + if (m_children_count_valid) + { + size_t children_count = m_children.GetChildrenCount(); + return children_count <= max ? children_count : max; + } + else + return CalculateNumChildren(max); + } + if (!m_children_count_valid) { SetNumChildren (CalculateNumChildren()); Index: source/Core/ValueObjectCast.cpp =================================================================== --- source/Core/ValueObjectCast.cpp +++ source/Core/ValueObjectCast.cpp @@ -68,9 +68,10 @@ } size_t -ValueObjectCast::CalculateNumChildren() +ValueObjectCast::CalculateNumChildren(uint32_t max) { - return GetCompilerType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } uint64_t Index: source/Core/ValueObjectChild.cpp =================================================================== --- source/Core/ValueObjectChild.cpp +++ source/Core/ValueObjectChild.cpp @@ -62,9 +62,10 @@ } size_t -ValueObjectChild::CalculateNumChildren() +ValueObjectChild::CalculateNumChildren(uint32_t max) { - return GetCompilerType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } static void Index: source/Core/ValueObjectConstResult.cpp =================================================================== --- source/Core/ValueObjectConstResult.cpp +++ source/Core/ValueObjectConstResult.cpp @@ -270,9 +270,10 @@ } size_t -ValueObjectConstResult::CalculateNumChildren() +ValueObjectConstResult::CalculateNumChildren(uint32_t max) { - return GetCompilerType().GetNumChildren (true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } ConstString Index: source/Core/ValueObjectDynamicValue.cpp =================================================================== --- source/Core/ValueObjectDynamicValue.cpp +++ source/Core/ValueObjectDynamicValue.cpp @@ -113,13 +113,16 @@ } size_t -ValueObjectDynamicValue::CalculateNumChildren() +ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { const bool success = UpdateValueIfNeeded(false); if (success && m_dynamic_type_info.HasType()) - return GetCompilerType().GetNumChildren (true); + { + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; + } else - return m_parent->GetNumChildren(); + return m_parent->GetNumChildren(max); } uint64_t Index: source/Core/ValueObjectMemory.cpp =================================================================== --- source/Core/ValueObjectMemory.cpp +++ source/Core/ValueObjectMemory.cpp @@ -156,12 +156,17 @@ } size_t -ValueObjectMemory::CalculateNumChildren() +ValueObjectMemory::CalculateNumChildren(uint32_t max) { if (m_type_sp) - return m_type_sp->GetNumChildren(true); + { + auto child_count = m_type_sp->GetNumChildren(true); + return child_count <= max ? child_count : max; + } + const bool omit_empty_base_classes = true; - return m_compiler_type.GetNumChildren (omit_empty_base_classes); + auto child_count = m_compiler_type.GetNumChildren (omit_empty_base_classes); + return child_count <= max ? child_count : max; } uint64_t Index: source/Core/ValueObjectRegister.cpp =================================================================== --- source/Core/ValueObjectRegister.cpp +++ source/Core/ValueObjectRegister.cpp @@ -67,9 +67,10 @@ } size_t -ValueObjectRegisterContext::CalculateNumChildren() +ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) { - return m_reg_ctx_sp->GetRegisterSetCount(); + auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount(); + return reg_set_count <= max ? reg_set_count : max; } uint64_t @@ -163,11 +164,14 @@ } size_t -ValueObjectRegisterSet::CalculateNumChildren() +ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) { const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); if (reg_set) - return reg_set->num_registers; + { + auto reg_count = reg_set->num_registers; + return reg_count <= max ? reg_count : max; + } return 0; } @@ -338,9 +342,10 @@ } size_t -ValueObjectRegister::CalculateNumChildren() +ValueObjectRegister::CalculateNumChildren(uint32_t max) { - return GetCompilerType().GetNumChildren(true); + auto children_count = GetCompilerType().GetNumChildren (true); + return children_count <= max ? children_count : max; } uint64_t Index: source/Core/ValueObjectSyntheticFilter.cpp =================================================================== --- source/Core/ValueObjectSyntheticFilter.cpp +++ source/Core/ValueObjectSyntheticFilter.cpp @@ -26,7 +26,7 @@ {} size_t - CalculateNumChildren() + CalculateNumChildren () { return m_backend.GetNumChildren(); } @@ -36,7 +36,7 @@ { return m_backend.GetChildAtIndex(idx, true); } - + size_t GetIndexOfChildWithName (const ConstString &name) { @@ -107,12 +107,16 @@ } size_t -ValueObjectSynthetic::CalculateNumChildren() +ValueObjectSynthetic::CalculateNumChildren(uint32_t max) { UpdateValueIfNeeded(); if (m_synthetic_children_count < UINT32_MAX) - return m_synthetic_children_count; - return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren()); + return m_synthetic_children_count <= max ? m_synthetic_children_count : max; + + if (max < UINT32_MAX) + return m_synth_filter_ap->CalculateNumChildren(max); + else + return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max)); } lldb::ValueObjectSP Index: source/Core/ValueObjectVariable.cpp =================================================================== --- source/Core/ValueObjectVariable.cpp +++ source/Core/ValueObjectVariable.cpp @@ -91,7 +91,7 @@ } size_t -ValueObjectVariable::CalculateNumChildren() +ValueObjectVariable::CalculateNumChildren(uint32_t max) { CompilerType type(GetCompilerType()); @@ -99,7 +99,8 @@ return 0; const bool omit_empty_base_classes = true; - return type.GetNumChildren(omit_empty_base_classes); + auto child_count = type.GetNumChildren(omit_empty_base_classes); + return child_count <= max ? child_count : max; } uint64_t Index: source/DataFormatters/TypeSynthetic.cpp =================================================================== --- source/DataFormatters/TypeSynthetic.cpp +++ source/DataFormatters/TypeSynthetic.cpp @@ -200,7 +200,15 @@ { if (!m_wrapper_sp || m_interpreter == NULL) return 0; - return m_interpreter->CalculateNumChildren(m_wrapper_sp); + return m_interpreter->CalculateNumChildren(m_wrapper_sp, UINT32_MAX); +} + +size_t +ScriptedSyntheticChildren::FrontEnd::CalculateNumChildren (uint32_t max) +{ + if (!m_wrapper_sp || m_interpreter == NULL) + return 0; + return m_interpreter->CalculateNumChildren(m_wrapper_sp, max); } bool Index: source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h =================================================================== --- source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h +++ source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h @@ -73,7 +73,7 @@ const char *session_dictionary_name, const lldb::ProcessSP& process_sp); - typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor); + typedef size_t (*SWIGPythonCalculateNumChildren) (void *implementor, uint32_t max); typedef void* (*SWIGPythonGetChildAtIndex) (void *implementor, uint32_t idx); typedef int (*SWIGPythonGetIndexOfChildWithName) (void *implementor, const char* child_name); typedef void* (*SWIGPythonCastPyObjectToSBValue) (void* data); @@ -200,7 +200,7 @@ StructuredData::DictionarySP GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name, lldb_private::Error &error) override; - size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor) override; + size_t CalculateNumChildren(const StructuredData::ObjectSP &implementor, uint32_t max) override; lldb::ValueObjectSP GetChildAtIndex(const StructuredData::ObjectSP &implementor, uint32_t idx) override; Index: source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp =================================================================== --- source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -2199,7 +2199,7 @@ } size_t -ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp) +ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp, uint32_t max) { if (!implementor_sp) return 0; @@ -2217,7 +2217,7 @@ { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = g_swig_calc_children (implementor); + ret_val = g_swig_calc_children (implementor, max); } return ret_val; Index: test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py =================================================================== --- test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py +++ test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py @@ -66,6 +66,7 @@ # now set up the synth self.runCmd("script from myIntSynthProvider import *") self.runCmd("type synth add -l myIntSynthProvider myInt") + self.runCmd("type synth add -l myArraySynthProvider myArray") if self.TraceOn(): print "x_val = %s; y_val = %s; z_val = %s" % (x_val(),y_val(),z_val()) @@ -85,6 +86,12 @@ hi = self.frame().FindVariable("hi") self.assertEqual(hi.GetSummary(), "42") + ma = self.frame().FindVariable("ma") + self.assertTrue(ma.IsValid()) + self.assertEqual(ma.GetNumChildren(15), 15) + self.assertEqual(ma.GetNumChildren(16), 16) + self.assertEqual(ma.GetNumChildren(17), 16) + if __name__ == '__main__': import atexit lldb.SBDebugger.Initialize() Index: test/functionalities/data-formatter/data-formatter-synthval/main.cpp =================================================================== --- test/functionalities/data-formatter/data-formatter-synthval/main.cpp +++ test/functionalities/data-formatter/data-formatter-synthval/main.cpp @@ -5,6 +5,11 @@ int val() { return theValue; } }; +class myArray { +public: + int array[16]; +}; + class hasAnInt { public: myInt theInt; @@ -18,5 +23,7 @@ myInt y{4}; myInt z {x+y}; hasAnInt hi; + myArray ma; + return z.val(); // break here } Index: test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py =================================================================== --- test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py +++ test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py @@ -15,3 +15,22 @@ def get_value(self): return self.val + +class myArraySynthProvider(object): + def __init__(self, valobj, dict): + self.valobj = valobj + self.array = self.valobj.GetChildMemberWithName("array") + + def num_children(self, max_count): + if 16 < max_count: + return 16 + return max_count + + def get_child_at_index(self, index): + return None # Keep it simple when this is not tested here. + + def get_child_index(self, name): + return None # Keep it simple when this is not tested here. + + def has_children(self): + return True