<div dir="ltr">Also seeing this on Windows.</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Oct 8, 2014 at 1:31 PM, Eric Christopher <span dir="ltr"><<a href="mailto:echristo@gmail.com" target="_blank">echristo@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Seeing a link error after this:<br>
<br>
/usr/local/google/home/echristo/sources/llvm/tools/lldb/source/API/SBCommandInterpreter.cpp:534:<br>
error: undefined reference to<br>
'LLDBSwigPython_GetValueSynthProviderInstance'<br>
<br>
Thoughts?<br>
<span class="HOEnZb"><font color="#888888"><br>
-eric<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Wed, Oct 8, 2014 at 11:27 AM, Enrico Granata <<a href="mailto:egranata@apple.com">egranata@apple.com</a>> wrote:<br>
> Author: enrico<br>
> Date: Wed Oct 8 13:27:36 2014<br>
> New Revision: 219330<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=219330&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=219330&view=rev</a><br>
> Log:<br>
> Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)<br>
><br>
> The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.<br>
> If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value<br>
><br>
> The rationale for doing things this way is twofold:<br>
><br>
> - there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial<br>
> - we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix<br>
> On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature<br>
><br>
> Comes with a test case<br>
><br>
><br>
> Added:<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py<br>
> Modified:<br>
> lldb/trunk/include/lldb/Core/ValueObject.h<br>
> lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h<br>
> lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h<br>
> lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h<br>
> lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h<br>
> lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h<br>
> lldb/trunk/scripts/Python/python-wrapper.swig<br>
> lldb/trunk/source/API/SBCommandInterpreter.cpp<br>
> lldb/trunk/source/Core/ValueObject.cpp<br>
> lldb/trunk/source/Core/ValueObjectCast.cpp<br>
> lldb/trunk/source/Core/ValueObjectDynamicValue.cpp<br>
> lldb/trunk/source/Core/ValueObjectMemory.cpp<br>
> lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp<br>
> lldb/trunk/source/Core/ValueObjectVariable.cpp<br>
> lldb/trunk/source/DataFormatters/TypeFormat.cpp<br>
> lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp<br>
> lldb/trunk/source/Interpreter/ScriptInterpreter.cpp<br>
> lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp<br>
> lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py<br>
><br>
> Modified: lldb/trunk/include/lldb/Core/ValueObject.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObject.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/Core/ValueObject.h (original)<br>
> +++ lldb/trunk/include/lldb/Core/ValueObject.h Wed Oct 8 13:27:36 2014<br>
> @@ -88,6 +88,7 @@ public:<br>
> {<br>
> eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse<br>
> eExpressionPathScanEndReasonNoSuchChild, // child element not found<br>
> + eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child element not found<br>
> eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for arrays<br>
> eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be used<br>
> eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be used<br>
> @@ -379,6 +380,9 @@ public:<br>
> // this vends a TypeImpl that is useful at the SB API layer<br>
> virtual TypeImpl<br>
> GetTypeImpl ();<br>
> +<br>
> + virtual bool<br>
> + CanProvideValue ();<br>
><br>
> //------------------------------------------------------------------<br>
> // Subclasses must implement the functions below.<br>
> @@ -755,6 +759,12 @@ public:<br>
> {<br>
> return false;<br>
> }<br>
> +<br>
> + virtual bool<br>
> + DoesProvideSyntheticValue ()<br>
> + {<br>
> + return false;<br>
> + }<br>
><br>
> virtual SymbolContextScope *<br>
> GetSymbolContextScope();<br>
><br>
> Modified: lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h (original)<br>
> +++ lldb/trunk/include/lldb/Core/ValueObjectSyntheticFilter.h Wed Oct 8 13:27:36 2014<br>
> @@ -132,11 +132,12 @@ public:<br>
> GetNonSyntheticValue ();<br>
><br>
> virtual bool<br>
> - ResolveValue (Scalar &scalar)<br>
> + CanProvideValue ();<br>
> +<br>
> + virtual bool<br>
> + DoesProvideSyntheticValue ()<br>
> {<br>
> - if (m_parent)<br>
> - return m_parent->ResolveValue(scalar);<br>
> - return false;<br>
> + return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes);<br>
> }<br>
><br>
> protected:<br>
> @@ -167,12 +168,14 @@ protected:<br>
><br>
> LazyBool m_might_have_children;<br>
><br>
> + LazyBool m_provides_value;<br>
> +<br>
> private:<br>
> friend class ValueObject;<br>
> ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter);<br>
><br>
> void<br>
> - CopyParentData ();<br>
> + CopyValueData (ValueObject *source);<br>
><br>
> //------------------------------------------------------------------<br>
> // For ValueObject only<br>
><br>
> Modified: lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h (original)<br>
> +++ lldb/trunk/include/lldb/DataFormatters/TypeSynthetic.h Wed Oct 8 13:27:36 2014<br>
> @@ -81,6 +81,11 @@ namespace lldb_private {<br>
> virtual bool<br>
> MightHaveChildren () = 0;<br>
><br>
> + // if this function returns a non-null ValueObject, then the returned ValueObject will stand<br>
> + // for this ValueObject whenever a "value" request is made to this ValueObject<br>
> + virtual lldb::ValueObjectSP<br>
> + GetSyntheticValue () { return nullptr; }<br>
> +<br>
> typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;<br>
> typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;<br>
><br>
> @@ -593,6 +598,15 @@ namespace lldb_private {<br>
> return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString());<br>
> }<br>
><br>
> + virtual lldb::ValueObjectSP<br>
> + GetSyntheticValue ()<br>
> + {<br>
> + if (!m_wrapper_sp || m_interpreter == NULL)<br>
> + return nullptr;<br>
> +<br>
> + return m_interpreter->GetSyntheticValue(m_wrapper_sp);<br>
> + }<br>
> +<br>
> typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;<br>
><br>
> private:<br>
><br>
> Modified: lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h (original)<br>
> +++ lldb/trunk/include/lldb/DataFormatters/ValueObjectPrinter.h Wed Oct 8 13:27:36 2014<br>
> @@ -295,7 +295,7 @@ protected:<br>
> uint32_t curr_depth);<br>
><br>
> bool<br>
> - GetDynamicValueIfNeeded ();<br>
> + GetMostSpecializedValue ();<br>
><br>
> const char*<br>
> GetDescriptionForDisplay ();<br>
><br>
> Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h (original)<br>
> +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreter.h Wed Oct 8 13:27:36 2014<br>
> @@ -121,7 +121,7 @@ public:<br>
> typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);<br>
> typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);<br>
> typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);<br>
> -<br>
> + typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor);<br>
><br>
> typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,<br>
> const char *session_dictionary_name,<br>
> @@ -498,6 +498,12 @@ public:<br>
> return true;<br>
> }<br>
><br>
> + virtual lldb::ValueObjectSP<br>
> + GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor)<br>
> + {<br>
> + return nullptr;<br>
> + }<br>
> +<br>
> virtual bool<br>
> RunScriptBasedCommand (const char* impl_function,<br>
> const char* args,<br>
> @@ -607,6 +613,7 @@ public:<br>
> SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,<br>
> SWIGPythonUpdateSynthProviderInstance swig_update_provider,<br>
> SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,<br>
> + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,<br>
> SWIGPythonCallCommand swig_call_command,<br>
> SWIGPythonCallModuleInit swig_call_module_init,<br>
> SWIGPythonCreateOSPlugin swig_create_os_plugin,<br>
><br>
> Modified: lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h (original)<br>
> +++ lldb/trunk/include/lldb/Interpreter/ScriptInterpreterPython.h Wed Oct 8 13:27:36 2014<br>
> @@ -141,6 +141,9 @@ public:<br>
> virtual bool<br>
> MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor);<br>
><br>
> + virtual lldb::ValueObjectSP<br>
> + GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor);<br>
> +<br>
> virtual bool<br>
> RunScriptBasedCommand(const char* impl_function,<br>
> const char* args,<br>
> @@ -285,6 +288,7 @@ public:<br>
> SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,<br>
> SWIGPythonUpdateSynthProviderInstance swig_update_provider,<br>
> SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,<br>
> + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,<br>
> SWIGPythonCallCommand swig_call_command,<br>
> SWIGPythonCallModuleInit swig_call_module_init,<br>
> SWIGPythonCreateOSPlugin swig_create_os_plugin,<br>
><br>
> Modified: lldb/trunk/scripts/Python/python-wrapper.swig<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/python-wrapper.swig?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/scripts/Python/python-wrapper.swig (original)<br>
> +++ lldb/trunk/scripts/Python/python-wrapper.swig Wed Oct 8 13:27:36 2014<br>
> @@ -723,6 +723,34 @@ LLDBSwigPython_MightHaveChildrenSynthPro<br>
> return ret_val;<br>
> }<br>
><br>
> +SWIGEXPORT PyObject*<br>
> +LLDBSwigPython_GetValueSynthProviderInstance<br>
> +(<br>
> + PyObject *implementor<br>
> +)<br>
> +{<br>
> + PyObject* ret_val = nullptr;<br>
> +<br>
> + static char callee_name[] = "get_value";<br>
> +<br>
> + PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None);<br>
> +<br>
> + if (py_return == Py_None || py_return == nullptr)<br>
> + ret_val = nullptr;<br>
> +<br>
> + lldb::SBValue* sbvalue_ptr = NULL;<br>
> +<br>
> + if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)<br>
> + ret_val = nullptr;<br>
> + else if (sbvalue_ptr == NULL)<br>
> + ret_val = nullptr;<br>
> + else<br>
> + ret_val = py_return;<br>
> +<br>
> + Py_XDECREF(py_return);<br>
> + return ret_val;<br>
> +}<br>
> +<br>
> SWIGEXPORT void*<br>
> LLDBSWIGPython_CastPyObjectToSBValue<br>
> (<br>
><br>
> Modified: lldb/trunk/source/API/SBCommandInterpreter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBCommandInterpreter.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/API/SBCommandInterpreter.cpp (original)<br>
> +++ lldb/trunk/source/API/SBCommandInterpreter.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -474,6 +474,9 @@ LLDBSwigPython_UpdateSynthProviderInstan<br>
> extern "C" bool<br>
> LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);<br>
><br>
> +extern "C" void *<br>
> +LLDBSwigPython_GetValueSynthProviderInstance (void* implementor);<br>
> +<br>
> extern "C" bool<br>
> LLDBSwigPythonCallCommand (const char *python_function_name,<br>
> const char *session_dictionary_name,<br>
> @@ -544,6 +547,7 @@ SBCommandInterpreter::InitializeSWIG ()<br>
> LLDBSWIGPython_GetValueObjectSPFromSBValue,<br>
> LLDBSwigPython_UpdateSynthProviderInstance,<br>
> LLDBSwigPython_MightHaveChildrenSynthProviderInstance,<br>
> + LLDBSwigPython_GetValueSynthProviderInstance,<br>
> LLDBSwigPythonCallCommand,<br>
> LLDBSwigPythonCallModuleInit,<br>
> LLDBSWIGPythonCreateOSPlugin,<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObject.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObject.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObject.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObject.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -1450,7 +1450,7 @@ ValueObject::GetValueAsCString ()<br>
> }<br>
> else<br>
> {<br>
> - my_format = GetClangType().GetFormat();<br>
> + my_format = GetValue().GetClangType().GetFormat();<br>
> }<br>
> }<br>
> }<br>
> @@ -1482,7 +1482,7 @@ uint64_t<br>
> ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success)<br>
> {<br>
> // If our byte size is zero this is an aggregate type that has children<br>
> - if (!GetClangType().IsAggregateType())<br>
> + if (CanProvideValue())<br>
> {<br>
> Scalar scalar;<br>
> if (ResolveValue (scalar))<br>
> @@ -1503,7 +1503,7 @@ int64_t<br>
> ValueObject::GetValueAsSigned (int64_t fail_value, bool *success)<br>
> {<br>
> // If our byte size is zero this is an aggregate type that has children<br>
> - if (!GetClangType().IsAggregateType())<br>
> + if (CanProvideValue())<br>
> {<br>
> Scalar scalar;<br>
> if (ResolveValue (scalar))<br>
> @@ -1751,7 +1751,7 @@ ValueObject::DumpPrintableRepresentation<br>
> cstr = GetSummaryAsCString();<br>
> else if (val_obj_display == eValueObjectRepresentationStyleSummary)<br>
> {<br>
> - if (GetClangType().IsAggregateType())<br>
> + if (!CanProvideValue())<br>
> {<br>
> strm.Printf("%s @ %s", GetTypeName().AsCString(), GetLocationAsCString());<br>
> cstr = strm.GetString().c_str();<br>
> @@ -2805,7 +2805,7 @@ ValueObject::GetValueForExpressionPath_I<br>
> if (root->IsSynthetic())<br>
> {<br>
> *first_unparsed = expression_cstr;<br>
> - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;<br>
> + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchSyntheticChild;<br>
> *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;<br>
> return ValueObjectSP();<br>
> }<br>
> @@ -4080,3 +4080,9 @@ ValueObject::GetFormat () const<br>
> }<br>
> return m_format;<br>
> }<br>
> +<br>
> +bool<br>
> +ValueObject::CanProvideValue ()<br>
> +{<br>
> + return (false == GetClangType().IsAggregateType());<br>
> +}<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObjectCast.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectCast.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectCast.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObjectCast.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObjectCast.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -102,7 +102,7 @@ ValueObjectCast::UpdateValue ()<br>
> //m_value.SetContext (Value::eContextTypeClangType, clang_type);<br>
> m_value.SetClangType (clang_type);<br>
> SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren());<br>
> - if (clang_type.IsAggregateType ())<br>
> + if (!CanProvideValue())<br>
> {<br>
> // this value object represents an aggregate type whose<br>
> // children have values, but this object does not. So we<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObjectDynamicValue.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectDynamicValue.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObjectDynamicValue.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObjectDynamicValue.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -329,7 +329,7 @@ ValueObjectDynamicValue::UpdateValue ()<br>
> m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());<br>
> if (m_error.Success())<br>
> {<br>
> - if (GetClangType().IsAggregateType ())<br>
> + if (!CanProvideValue())<br>
> {<br>
> // this value object represents an aggregate type whose<br>
> // children have values, but this object does not. So we<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObjectMemory.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectMemory.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectMemory.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObjectMemory.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObjectMemory.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -233,7 +233,7 @@ ValueObjectMemory::UpdateValue ()<br>
> }<br>
> }<br>
><br>
> - if (GetClangType().IsAggregateType())<br>
> + if (!CanProvideValue())<br>
> {<br>
> // this value object represents an aggregate type whose<br>
> // children have values, but this object does not. So we<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObjectSyntheticFilter.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -66,16 +66,17 @@ ValueObjectSynthetic::ValueObjectSynthet<br>
> m_name_toindex(),<br>
> m_synthetic_children_count(UINT32_MAX),<br>
> m_parent_type_name(parent.GetTypeName()),<br>
> - m_might_have_children(eLazyBoolCalculate)<br>
> + m_might_have_children(eLazyBoolCalculate),<br>
> + m_provides_value(eLazyBoolCalculate)<br>
> {<br>
> -#ifdef LLDB_CONFIGURATION_DEBUG<br>
> +#ifdef FOOBAR<br>
> std::string new_name(parent.GetName().AsCString());<br>
> new_name += "$$__synth__";<br>
> SetName (ConstString(new_name.c_str()));<br>
> #else<br>
> SetName(parent.GetName());<br>
> #endif<br>
> - CopyParentData();<br>
> + CopyValueData(m_parent);<br>
> CreateSynthFilter();<br>
> }<br>
><br>
> @@ -191,7 +192,20 @@ ValueObjectSynthetic::UpdateValue ()<br>
> m_might_have_children = eLazyBoolCalculate;<br>
> }<br>
><br>
> - CopyParentData();<br>
> + m_provides_value = eLazyBoolCalculate;<br>
> +<br>
> + lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());<br>
> +<br>
> + if (synth_val && synth_val->CanProvideValue())<br>
> + {<br>
> + m_provides_value = eLazyBoolYes;<br>
> + CopyValueData(synth_val.get());<br>
> + }<br>
> + else<br>
> + {<br>
> + m_provides_value = eLazyBoolNo;<br>
> + CopyValueData(m_parent);<br>
> + }<br>
><br>
> SetValueIsValid(true);<br>
> return true;<br>
> @@ -268,9 +282,19 @@ ValueObjectSynthetic::GetNonSyntheticVal<br>
> }<br>
><br>
> void<br>
> -ValueObjectSynthetic::CopyParentData ()<br>
> +ValueObjectSynthetic::CopyValueData (ValueObject *source)<br>
> {<br>
> - m_value = m_parent->GetValue();<br>
> + m_value = (source->UpdateValueIfNeeded(), source->GetValue());<br>
> ExecutionContext exe_ctx (GetExecutionContextRef());<br>
> m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());<br>
> }<br>
> +<br>
> +bool<br>
> +ValueObjectSynthetic::CanProvideValue ()<br>
> +{<br>
> + if (!UpdateValueIfNeeded())<br>
> + return false;<br>
> + if (m_provides_value == eLazyBoolYes)<br>
> + return true;<br>
> + return m_parent->CanProvideValue();<br>
> +}<br>
><br>
> Modified: lldb/trunk/source/Core/ValueObjectVariable.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectVariable.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ValueObjectVariable.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Core/ValueObjectVariable.cpp (original)<br>
> +++ lldb/trunk/source/Core/ValueObjectVariable.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -234,7 +234,7 @@ ValueObjectVariable::UpdateValue ()<br>
> }<br>
> }<br>
><br>
> - if (GetClangType().IsAggregateType())<br>
> + if (!CanProvideValue())<br>
> {<br>
> // this value object represents an aggregate type whose<br>
> // children have values, but this object does not. So we<br>
><br>
> Modified: lldb/trunk/source/DataFormatters/TypeFormat.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/TypeFormat.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/TypeFormat.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/DataFormatters/TypeFormat.cpp (original)<br>
> +++ lldb/trunk/source/DataFormatters/TypeFormat.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -59,9 +59,9 @@ TypeFormatImpl_Format::FormatObject (Val<br>
> {<br>
> if (!valobj)<br>
> return false;<br>
> - if (valobj->GetClangType().IsAggregateType () == false)<br>
> + if (valobj->CanProvideValue())<br>
> {<br>
> - const Value& value(valobj->GetValue());<br>
> + Value& value(valobj->GetValue());<br>
> const Value::ContextType context_type = value.GetContextType();<br>
> ExecutionContext exe_ctx (valobj->GetExecutionContextRef());<br>
> DataExtractor data;<br>
> @@ -92,7 +92,7 @@ TypeFormatImpl_Format::FormatObject (Val<br>
> }<br>
> else<br>
> {<br>
> - ClangASTType clang_type = valobj->GetClangType ();<br>
> + ClangASTType clang_type = value.GetClangType ();<br>
> if (clang_type)<br>
> {<br>
> // put custom bytes to display in the DataExtractor to override the default value logic<br>
> @@ -180,7 +180,7 @@ TypeFormatImpl_EnumType::FormatObject (V<br>
> dest.clear();<br>
> if (!valobj)<br>
> return false;<br>
> - if (valobj->GetClangType().IsAggregateType ())<br>
> + if (!valobj->CanProvideValue())<br>
> return false;<br>
> ProcessSP process_sp;<br>
> TargetSP target_sp;<br>
><br>
> Modified: lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp (original)<br>
> +++ lldb/trunk/source/DataFormatters/ValueObjectPrinter.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -66,7 +66,7 @@ ValueObjectPrinter::Init (ValueObject* v<br>
> bool<br>
> ValueObjectPrinter::PrintValueObject ()<br>
> {<br>
> - if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)<br>
> + if (!GetMostSpecializedValue () || m_valobj == nullptr)<br>
> return false;<br>
><br>
> if (ShouldPrintValueObject())<br>
> @@ -97,7 +97,7 @@ ValueObjectPrinter::PrintValueObject ()<br>
> }<br>
><br>
> bool<br>
> -ValueObjectPrinter::GetDynamicValueIfNeeded ()<br>
> +ValueObjectPrinter::GetMostSpecializedValue ()<br>
> {<br>
> if (m_valobj)<br>
> return true;<br>
> @@ -134,6 +134,25 @@ ValueObjectPrinter::GetDynamicValueIfNee<br>
> else<br>
> m_valobj = m_orig_valobj;<br>
> }<br>
> +<br>
> + if (m_valobj->IsSynthetic())<br>
> + {<br>
> + if (options.m_use_synthetic == false)<br>
> + {<br>
> + ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();<br>
> + if (non_synthetic)<br>
> + m_valobj = non_synthetic;<br>
> + }<br>
> + }<br>
> + else<br>
> + {<br>
> + if (options.m_use_synthetic == true)<br>
> + {<br>
> + ValueObject *synthetic = m_valobj->GetSyntheticValue().get();<br>
> + if (synthetic)<br>
> + m_valobj = synthetic;<br>
> + }<br>
> + }<br>
> }<br>
> m_clang_type = m_valobj->GetClangType();<br>
> m_type_flags = m_clang_type.GetTypeInfo ();<br>
> @@ -442,8 +461,7 @@ ValueObjectPrinter::ShouldPrintChildren<br>
> ValueObject*<br>
> ValueObjectPrinter::GetValueObjectForChildrenGeneration ()<br>
> {<br>
> - ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);<br>
> - return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);<br>
> + return m_valobj;<br>
> }<br>
><br>
> void<br>
> @@ -540,7 +558,13 @@ ValueObjectPrinter::PrintChildren (uint3<br>
> {<br>
> // Aggregate, no children...<br>
> if (ShouldPrintValueObject())<br>
> - m_stream->PutCString(" {}\n");<br>
> + {<br>
> + // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value<br>
> + if (m_valobj->DoesProvideSyntheticValue())<br>
> + m_stream->PutCString( "\n");<br>
> + else<br>
> + m_stream->PutCString(" {}\n");<br>
> + }<br>
> }<br>
> else<br>
> {<br>
> @@ -552,7 +576,7 @@ ValueObjectPrinter::PrintChildren (uint3<br>
> bool<br>
> ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)<br>
> {<br>
> - if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)<br>
> + if (!GetMostSpecializedValue () || m_valobj == nullptr)<br>
> return false;<br>
><br>
> ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();<br>
><br>
> Modified: lldb/trunk/source/Interpreter/ScriptInterpreter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreter.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Interpreter/ScriptInterpreter.cpp (original)<br>
> +++ lldb/trunk/source/Interpreter/ScriptInterpreter.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -124,6 +124,7 @@ ScriptInterpreter::InitializeInterpreter<br>
> SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,<br>
> SWIGPythonUpdateSynthProviderInstance swig_update_provider,<br>
> SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,<br>
> + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,<br>
> SWIGPythonCallCommand swig_call_command,<br>
> SWIGPythonCallModuleInit swig_call_module_init,<br>
> SWIGPythonCreateOSPlugin swig_create_os_plugin,<br>
> @@ -148,6 +149,7 @@ ScriptInterpreter::InitializeInterpreter<br>
> swig_get_valobj_sp_from_sbvalue,<br>
> swig_update_provider,<br>
> swig_mighthavechildren_provider,<br>
> + swig_getvalue_provider,<br>
> swig_call_command,<br>
> swig_call_module_init,<br>
> swig_create_os_plugin,<br>
><br>
> Modified: lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp (original)<br>
> +++ lldb/trunk/source/Interpreter/ScriptInterpreterPython.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -55,6 +55,7 @@ static ScriptInterpreter::SWIGPythonCast<br>
> static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr;<br>
> static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr;<br>
> static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr;<br>
> +static ScriptInterpreter::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr;<br>
> static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr;<br>
> static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;<br>
> static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;<br>
> @@ -2140,6 +2141,42 @@ ScriptInterpreterPython::MightHaveChildr<br>
> return ret_val;<br>
> }<br>
><br>
> +lldb::ValueObjectSP<br>
> +ScriptInterpreterPython::GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor_sp)<br>
> +{<br>
> + lldb::ValueObjectSP ret_val(nullptr);<br>
> +<br>
> + if (!implementor_sp)<br>
> + return ret_val;<br>
> +<br>
> + void* implementor = implementor_sp->GetObject();<br>
> +<br>
> + if (!implementor)<br>
> + return ret_val;<br>
> +<br>
> + if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue)<br>
> + return ret_val;<br>
> +<br>
> + {<br>
> + Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);<br>
> + void* child_ptr = g_swig_getvalue_provider (implementor);<br>
> + if (child_ptr != nullptr && child_ptr != Py_None)<br>
> + {<br>
> + lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);<br>
> + if (sb_value_ptr == nullptr)<br>
> + Py_XDECREF(child_ptr);<br>
> + else<br>
> + ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);<br>
> + }<br>
> + else<br>
> + {<br>
> + Py_XDECREF(child_ptr);<br>
> + }<br>
> + }<br>
> +<br>
> + return ret_val;<br>
> +}<br>
> +<br>
> static std::string<br>
> ReadPythonBacktrace (PyObject* py_backtrace)<br>
> {<br>
> @@ -2616,6 +2653,7 @@ ScriptInterpreterPython::InitializeInter<br>
> SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,<br>
> SWIGPythonUpdateSynthProviderInstance swig_update_provider,<br>
> SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,<br>
> + SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,<br>
> SWIGPythonCallCommand swig_call_command,<br>
> SWIGPythonCallModuleInit swig_call_module_init,<br>
> SWIGPythonCreateOSPlugin swig_create_os_plugin,<br>
> @@ -2639,6 +2677,7 @@ ScriptInterpreterPython::InitializeInter<br>
> g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;<br>
> g_swig_update_provider = swig_update_provider;<br>
> g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;<br>
> + g_swig_getvalue_provider = swig_getvalue_provider;<br>
> g_swig_call_command = swig_call_command;<br>
> g_swig_call_module_init = swig_call_module_init;<br>
> g_swig_create_os_plugin = swig_create_os_plugin;<br>
><br>
> Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py?rev=219330&r1=219329&r2=219330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py?rev=219330&r1=219329&r2=219330&view=diff</a><br>
> ==============================================================================<br>
> --- lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py (original)<br>
> +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py Wed Oct 8 13:27:36 2014<br>
> @@ -14,12 +14,14 @@ class SynthDataFormatterTestCase(TestBas<br>
><br>
> @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")<br>
> @dsym_test<br>
> + @unittest2.expectedFailure("rdar://15630776 - Summary cannot reference non-synthetic children if synthetic children exist")<br>
> def test_with_dsym_and_run_command(self):<br>
> """Test data formatter commands."""<br>
> self.buildDsym()<br>
> self.data_formatter_commands()<br>
><br>
> @dwarf_test<br>
> + @unittest2.expectedFailure("rdar://15630776 - Summary cannot reference non-synthetic children if synthetic children exist")<br>
> def test_with_dwarf_and_run_command(self):<br>
> """Test data formatter commands."""<br>
> self.buildDwarf()<br>
><br>
> Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile?rev=219330&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile?rev=219330&view=auto</a><br>
> ==============================================================================<br>
> --- lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile (added)<br>
> +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/Makefile Wed Oct 8 13:27:36 2014<br>
> @@ -0,0 +1,5 @@<br>
> +LEVEL = ../../../make<br>
> +<br>
> +CXX_SOURCES := main.cpp<br>
> +<br>
> +include $(LEVEL)/Makefile.rules<br>
><br>
> Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py?rev=219330&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py?rev=219330&view=auto</a><br>
> ==============================================================================<br>
> --- lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py (added)<br>
> +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py Wed Oct 8 13:27:36 2014<br>
> @@ -0,0 +1,95 @@<br>
> +"""<br>
> +Test lldb data formatter subsystem.<br>
> +"""<br>
> +<br>
> +import os, time<br>
> +import unittest2<br>
> +import lldb<br>
> +from lldbtest import *<br>
> +import lldbutil<br>
> +<br>
> +class DataFormatterSynthValueTestCase(TestBase):<br>
> +<br>
> + mydir = TestBase.compute_mydir(__file__)<br>
> +<br>
> + @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")<br>
> + @dsym_test<br>
> + def test_with_dsym_and_run_command(self):<br>
> + """Test using Python synthetic children provider to provide a value."""<br>
> + self.buildDsym()<br>
> + self.data_formatter_commands()<br>
> +<br>
> + @skipIfFreeBSD # <a href="http://llvm.org/pr20545" target="_blank">llvm.org/pr20545</a> bogus output confuses buildbot parser<br>
> + @dwarf_test<br>
> + def test_with_dwarf_and_run_command(self):<br>
> + """Test using Python synthetic children provider to provide a value."""<br>
> + self.buildDwarf()<br>
> + self.data_formatter_commands()<br>
> +<br>
> + def setUp(self):<br>
> + # Call super's setUp().<br>
> + TestBase.setUp(self)<br>
> + # Find the line number to break at.<br>
> + self.line = line_number('main.cpp', 'break here')<br>
> +<br>
> + def data_formatter_commands(self):<br>
> + """Test using Python synthetic children provider to provide a value."""<br>
> + self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)<br>
> +<br>
> + lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)<br>
> +<br>
> + self.runCmd("run", RUN_SUCCEEDED)<br>
> +<br>
> + # The stop reason of the thread should be breakpoint.<br>
> + self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,<br>
> + substrs = ['stopped',<br>
> + 'stop reason = breakpoint'])<br>
> +<br>
> + # This is the function to remove the custom formats in order to have a<br>
> + # clean slate for the next test case.<br>
> + def cleanup():<br>
> + self.runCmd('type format clear', check=False)<br>
> + self.runCmd('type summary clear', check=False)<br>
> + self.runCmd('type filter clear', check=False)<br>
> + self.runCmd('type synth clear', check=False)<br>
> +<br>
> + # Execute the cleanup function during test case tear down.<br>
> + self.addTearDownHook(cleanup)<br>
> +<br>
> + x = self.frame().FindVariable("x")<br>
> + x.SetPreferSyntheticValue(True)<br>
> + y = self.frame().FindVariable("y")<br>
> + y.SetPreferSyntheticValue(True)<br>
> + z = self.frame().FindVariable("z")<br>
> + z.SetPreferSyntheticValue(True)<br>
> +<br>
> + x_val = x.GetValueAsUnsigned<br>
> + y_val = y.GetValueAsUnsigned<br>
> + z_val = z.GetValueAsUnsigned<br>
> +<br>
> + if self.TraceOn():<br>
> + print "x_val = %s; y_val = %s; z_val = %s" % (x_val(),y_val(),z_val())<br>
> +<br>
> + self.assertFalse(x_val() == 3, "x == 3 before synthetics")<br>
> + self.assertFalse(y_val() == 4, "y == 4 before synthetics")<br>
> + self.assertFalse(z_val() == 7, "z == 7 before synthetics")<br>
> +<br>
> + # now set up the synth<br>
> + self.runCmd("script from myIntSynthProvider import *")<br>
> + self.runCmd("type synth add -l myIntSynthProvider myInt")<br>
> +<br>
> + if self.TraceOn():<br>
> + print "x_val = %s; y_val = %s; z_val = %s" % (x_val(),y_val(),z_val())<br>
> +<br>
> + self.assertTrue(x_val() == 3, "x != 3 after synthetics")<br>
> + self.assertTrue(y_val() == 4, "y != 4 after synthetics")<br>
> + self.assertTrue(z_val() == 7, "z != 7 after synthetics")<br>
> +<br>
> + self.expect("frame variable x", substrs=['3'])<br>
> + self.expect("frame variable x", substrs=['theValue = 3'], matching=False)<br>
> +<br>
> +if __name__ == '__main__':<br>
> + import atexit<br>
> + lldb.SBDebugger.Initialize()<br>
> + atexit.register(lambda: lldb.SBDebugger.Terminate())<br>
> + unittest2.main()<br>
><br>
> Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp?rev=219330&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp?rev=219330&view=auto</a><br>
> ==============================================================================<br>
> --- lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp (added)<br>
> +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/main.cpp Wed Oct 8 13:27:36 2014<br>
> @@ -0,0 +1,15 @@<br>
> +class myInt {<br>
> + private: int theValue;<br>
> + public: myInt() : theValue(0) {}<br>
> + public: myInt(int _x) : theValue(_x) {}<br>
> + int val() { return theValue; }<br>
> +};<br>
> +<br>
> +myInt operator + (myInt x, myInt y) { return myInt(x.val() + y.val()); }<br>
> +<br>
> +int main() {<br>
> + myInt x{3};<br>
> + myInt y{4};<br>
> + myInt z {x+y};<br>
> + return z.val(); // break here<br>
> +}<br>
><br>
> Added: lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py?rev=219330&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py?rev=219330&view=auto</a><br>
> ==============================================================================<br>
> --- lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py (added)<br>
> +++ lldb/trunk/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py Wed Oct 8 13:27:36 2014<br>
> @@ -0,0 +1,17 @@<br>
> +class myIntSynthProvider(object):<br>
> + def __init__(self, valobj, dict):<br>
> + self.valobj = valobj;<br>
> + self.val = self.valobj.GetChildMemberWithName("theValue")<br>
> + def num_children(self):<br>
> + return 0;<br>
> + def get_child_at_index(self, index):<br>
> + return None<br>
> + def get_child_index(self, name):<br>
> + return None<br>
> + def update(self):<br>
> + return False<br>
> + def might_have_children(self):<br>
> + return False<br>
> + def get_value(self):<br>
> + return self.val<br>
> +<br>
><br>
><br>
> _______________________________________________<br>
> lldb-commits mailing list<br>
> <a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@cs.uiuc.edu">lldb-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits</a><br>
</div></div></blockquote></div><br></div>