summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/ValueObject.h10
-rw-r--r--lldb/include/lldb/Core/ValueObjectSyntheticFilter.h13
-rw-r--r--lldb/include/lldb/DataFormatters/TypeSynthetic.h14
-rw-r--r--lldb/include/lldb/DataFormatters/ValueObjectPrinter.h2
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h9
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreterPython.h4
-rw-r--r--lldb/scripts/Python/python-wrapper.swig28
-rw-r--r--lldb/source/API/SBCommandInterpreter.cpp4
-rw-r--r--lldb/source/Core/ValueObject.cpp16
-rw-r--r--lldb/source/Core/ValueObjectCast.cpp2
-rw-r--r--lldb/source/Core/ValueObjectDynamicValue.cpp2
-rw-r--r--lldb/source/Core/ValueObjectMemory.cpp2
-rw-r--r--lldb/source/Core/ValueObjectSyntheticFilter.cpp36
-rw-r--r--lldb/source/Core/ValueObjectVariable.cpp2
-rw-r--r--lldb/source/DataFormatters/TypeFormat.cpp8
-rw-r--r--lldb/source/DataFormatters/ValueObjectPrinter.cpp36
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp2
-rw-r--r--lldb/source/Interpreter/ScriptInterpreterPython.cpp39
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py2
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-synthval/Makefile5
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py95
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-synthval/main.cpp15
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py17
23 files changed, 331 insertions, 32 deletions
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 18844318c08..d9d6b78d301 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -88,6 +88,7 @@ public:
{
eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse
eExpressionPathScanEndReasonNoSuchChild, // child element not found
+ eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child element not found
eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for arrays
eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be used
eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be used
@@ -379,6 +380,9 @@ public:
// this vends a TypeImpl that is useful at the SB API layer
virtual TypeImpl
GetTypeImpl ();
+
+ virtual bool
+ CanProvideValue ();
//------------------------------------------------------------------
// Subclasses must implement the functions below.
@@ -756,6 +760,12 @@ public:
return false;
}
+ virtual bool
+ DoesProvideSyntheticValue ()
+ {
+ return false;
+ }
+
virtual SymbolContextScope *
GetSymbolContextScope();
diff --git a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
index e12698f49bb..9846ae6e247 100644
--- a/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -132,11 +132,12 @@ public:
GetNonSyntheticValue ();
virtual bool
- ResolveValue (Scalar &scalar)
+ CanProvideValue ();
+
+ virtual bool
+ DoesProvideSyntheticValue ()
{
- if (m_parent)
- return m_parent->ResolveValue(scalar);
- return false;
+ return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes);
}
protected:
@@ -167,12 +168,14 @@ protected:
LazyBool m_might_have_children;
+ LazyBool m_provides_value;
+
private:
friend class ValueObject;
ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter);
void
- CopyParentData ();
+ CopyValueData (ValueObject *source);
//------------------------------------------------------------------
// For ValueObject only
diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
index a25f11d6439..9c4f77cdecb 100644
--- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h
@@ -81,6 +81,11 @@ namespace lldb_private {
virtual bool
MightHaveChildren () = 0;
+ // if this function returns a non-null ValueObject, then the returned ValueObject will stand
+ // for this ValueObject whenever a "value" request is made to this ValueObject
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue () { return nullptr; }
+
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
typedef std::unique_ptr<SyntheticChildrenFrontEnd> AutoPointer;
@@ -593,6 +598,15 @@ namespace lldb_private {
return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString());
}
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue ()
+ {
+ if (!m_wrapper_sp || m_interpreter == NULL)
+ return nullptr;
+
+ return m_interpreter->GetSyntheticValue(m_wrapper_sp);
+ }
+
typedef std::shared_ptr<SyntheticChildrenFrontEnd> SharedPointer;
private:
diff --git a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
index 327ebd137db..cc8b198f038 100644
--- a/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/lldb/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -295,7 +295,7 @@ protected:
uint32_t curr_depth);
bool
- GetDynamicValueIfNeeded ();
+ GetMostSpecializedValue ();
const char*
GetDescriptionForDisplay ();
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 2fbc57a7a32..e7a456df029 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -121,7 +121,7 @@ public:
typedef lldb::ValueObjectSP (*SWIGPythonGetValueObjectSPFromSBValue) (void* data);
typedef bool (*SWIGPythonUpdateSynthProviderInstance) (void* data);
typedef bool (*SWIGPythonMightHaveChildrenSynthProviderInstance) (void* data);
-
+ typedef void* (*SWIGPythonGetValueSynthProviderInstance) (void *implementor);
typedef bool (*SWIGPythonCallCommand) (const char *python_function_name,
const char *session_dictionary_name,
@@ -498,6 +498,12 @@ public:
return true;
}
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor)
+ {
+ return nullptr;
+ }
+
virtual bool
RunScriptBasedCommand (const char* impl_function,
const char* args,
@@ -607,6 +613,7 @@ public:
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
index 92fc0328959..2cdb839196b 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h
@@ -141,6 +141,9 @@ public:
virtual bool
MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor);
+ virtual lldb::ValueObjectSP
+ GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor);
+
virtual bool
RunScriptBasedCommand(const char* impl_function,
const char* args,
@@ -285,6 +288,7 @@ public:
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig
index bf22198f4e4..9f9ebaded9d 100644
--- a/lldb/scripts/Python/python-wrapper.swig
+++ b/lldb/scripts/Python/python-wrapper.swig
@@ -723,6 +723,34 @@ LLDBSwigPython_MightHaveChildrenSynthProviderInstance
return ret_val;
}
+SWIGEXPORT PyObject*
+LLDBSwigPython_GetValueSynthProviderInstance
+(
+ PyObject *implementor
+)
+{
+ PyObject* ret_val = nullptr;
+
+ static char callee_name[] = "get_value";
+
+ PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_None);
+
+ if (py_return == Py_None || py_return == nullptr)
+ ret_val = nullptr;
+
+ lldb::SBValue* sbvalue_ptr = NULL;
+
+ if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1)
+ ret_val = nullptr;
+ else if (sbvalue_ptr == NULL)
+ ret_val = nullptr;
+ else
+ ret_val = py_return;
+
+ Py_XDECREF(py_return);
+ return ret_val;
+}
+
SWIGEXPORT void*
LLDBSWIGPython_CastPyObjectToSBValue
(
diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp
index aa1ff55bc73..9f6f4e8d428 100644
--- a/lldb/source/API/SBCommandInterpreter.cpp
+++ b/lldb/source/API/SBCommandInterpreter.cpp
@@ -474,6 +474,9 @@ LLDBSwigPython_UpdateSynthProviderInstance (void* implementor);
extern "C" bool
LLDBSwigPython_MightHaveChildrenSynthProviderInstance (void* implementor);
+extern "C" void *
+LLDBSwigPython_GetValueSynthProviderInstance (void* implementor);
+
extern "C" bool
LLDBSwigPythonCallCommand (const char *python_function_name,
const char *session_dictionary_name,
@@ -544,6 +547,7 @@ SBCommandInterpreter::InitializeSWIG ()
LLDBSWIGPython_GetValueObjectSPFromSBValue,
LLDBSwigPython_UpdateSynthProviderInstance,
LLDBSwigPython_MightHaveChildrenSynthProviderInstance,
+ LLDBSwigPython_GetValueSynthProviderInstance,
LLDBSwigPythonCallCommand,
LLDBSwigPythonCallModuleInit,
LLDBSWIGPythonCreateOSPlugin,
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 3b37de79234..f38b7c01565 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -1450,7 +1450,7 @@ ValueObject::GetValueAsCString ()
}
else
{
- my_format = GetClangType().GetFormat();
+ my_format = GetValue().GetClangType().GetFormat();
}
}
}
@@ -1482,7 +1482,7 @@ uint64_t
ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success)
{
// If our byte size is zero this is an aggregate type that has children
- if (!GetClangType().IsAggregateType())
+ if (CanProvideValue())
{
Scalar scalar;
if (ResolveValue (scalar))
@@ -1503,7 +1503,7 @@ int64_t
ValueObject::GetValueAsSigned (int64_t fail_value, bool *success)
{
// If our byte size is zero this is an aggregate type that has children
- if (!GetClangType().IsAggregateType())
+ if (CanProvideValue())
{
Scalar scalar;
if (ResolveValue (scalar))
@@ -1751,7 +1751,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s,
cstr = GetSummaryAsCString();
else if (val_obj_display == eValueObjectRepresentationStyleSummary)
{
- if (GetClangType().IsAggregateType())
+ if (!CanProvideValue())
{
strm.Printf("%s @ %s", GetTypeName().AsCString(), GetLocationAsCString());
cstr = strm.GetString().c_str();
@@ -2805,7 +2805,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
if (root->IsSynthetic())
{
*first_unparsed = expression_cstr;
- *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
+ *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchSyntheticChild;
*final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
return ValueObjectSP();
}
@@ -4080,3 +4080,9 @@ ValueObject::GetFormat () const
}
return m_format;
}
+
+bool
+ValueObject::CanProvideValue ()
+{
+ return (false == GetClangType().IsAggregateType());
+}
diff --git a/lldb/source/Core/ValueObjectCast.cpp b/lldb/source/Core/ValueObjectCast.cpp
index 4f4f8cc681d..b20371b128d 100644
--- a/lldb/source/Core/ValueObjectCast.cpp
+++ b/lldb/source/Core/ValueObjectCast.cpp
@@ -102,7 +102,7 @@ ValueObjectCast::UpdateValue ()
//m_value.SetContext (Value::eContextTypeClangType, clang_type);
m_value.SetClangType (clang_type);
SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren());
- if (clang_type.IsAggregateType ())
+ if (!CanProvideValue())
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
diff --git a/lldb/source/Core/ValueObjectDynamicValue.cpp b/lldb/source/Core/ValueObjectDynamicValue.cpp
index 3481bdedf38..30a42f09461 100644
--- a/lldb/source/Core/ValueObjectDynamicValue.cpp
+++ b/lldb/source/Core/ValueObjectDynamicValue.cpp
@@ -329,7 +329,7 @@ ValueObjectDynamicValue::UpdateValue ()
m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
if (m_error.Success())
{
- if (GetClangType().IsAggregateType ())
+ if (!CanProvideValue())
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
diff --git a/lldb/source/Core/ValueObjectMemory.cpp b/lldb/source/Core/ValueObjectMemory.cpp
index d2cbbfdda24..5fbe87b6652 100644
--- a/lldb/source/Core/ValueObjectMemory.cpp
+++ b/lldb/source/Core/ValueObjectMemory.cpp
@@ -233,7 +233,7 @@ ValueObjectMemory::UpdateValue ()
}
}
- if (GetClangType().IsAggregateType())
+ if (!CanProvideValue())
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
diff --git a/lldb/source/Core/ValueObjectSyntheticFilter.cpp b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
index 18d36164989..9bdf68963db 100644
--- a/lldb/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/lldb/source/Core/ValueObjectSyntheticFilter.cpp
@@ -66,16 +66,17 @@ ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::Synthetic
m_name_toindex(),
m_synthetic_children_count(UINT32_MAX),
m_parent_type_name(parent.GetTypeName()),
- m_might_have_children(eLazyBoolCalculate)
+ m_might_have_children(eLazyBoolCalculate),
+ m_provides_value(eLazyBoolCalculate)
{
-#ifdef LLDB_CONFIGURATION_DEBUG
+#ifdef FOOBAR
std::string new_name(parent.GetName().AsCString());
new_name += "$$__synth__";
SetName (ConstString(new_name.c_str()));
#else
SetName(parent.GetName());
#endif
- CopyParentData();
+ CopyValueData(m_parent);
CreateSynthFilter();
}
@@ -191,7 +192,20 @@ ValueObjectSynthetic::UpdateValue ()
m_might_have_children = eLazyBoolCalculate;
}
- CopyParentData();
+ m_provides_value = eLazyBoolCalculate;
+
+ lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());
+
+ if (synth_val && synth_val->CanProvideValue())
+ {
+ m_provides_value = eLazyBoolYes;
+ CopyValueData(synth_val.get());
+ }
+ else
+ {
+ m_provides_value = eLazyBoolNo;
+ CopyValueData(m_parent);
+ }
SetValueIsValid(true);
return true;
@@ -268,9 +282,19 @@ ValueObjectSynthetic::GetNonSyntheticValue ()
}
void
-ValueObjectSynthetic::CopyParentData ()
+ValueObjectSynthetic::CopyValueData (ValueObject *source)
{
- m_value = m_parent->GetValue();
+ m_value = (source->UpdateValueIfNeeded(), source->GetValue());
ExecutionContext exe_ctx (GetExecutionContextRef());
m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
}
+
+bool
+ValueObjectSynthetic::CanProvideValue ()
+{
+ if (!UpdateValueIfNeeded())
+ return false;
+ if (m_provides_value == eLazyBoolYes)
+ return true;
+ return m_parent->CanProvideValue();
+}
diff --git a/lldb/source/Core/ValueObjectVariable.cpp b/lldb/source/Core/ValueObjectVariable.cpp
index 225dc02c8ad..aa8ade1aed1 100644
--- a/lldb/source/Core/ValueObjectVariable.cpp
+++ b/lldb/source/Core/ValueObjectVariable.cpp
@@ -234,7 +234,7 @@ ValueObjectVariable::UpdateValue ()
}
}
- if (GetClangType().IsAggregateType())
+ if (!CanProvideValue())
{
// this value object represents an aggregate type whose
// children have values, but this object does not. So we
diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index 0c62daf87bb..64d37501a92 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -59,9 +59,9 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
{
if (!valobj)
return false;
- if (valobj->GetClangType().IsAggregateType () == false)
+ if (valobj->CanProvideValue())
{
- const Value& value(valobj->GetValue());
+ Value& value(valobj->GetValue());
const Value::ContextType context_type = value.GetContextType();
ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
DataExtractor data;
@@ -92,7 +92,7 @@ TypeFormatImpl_Format::FormatObject (ValueObject *valobj,
}
else
{
- ClangASTType clang_type = valobj->GetClangType ();
+ ClangASTType clang_type = value.GetClangType ();
if (clang_type)
{
// put custom bytes to display in the DataExtractor to override the default value logic
@@ -180,7 +180,7 @@ TypeFormatImpl_EnumType::FormatObject (ValueObject *valobj,
dest.clear();
if (!valobj)
return false;
- if (valobj->GetClangType().IsAggregateType ())
+ if (!valobj->CanProvideValue())
return false;
ProcessSP process_sp;
TargetSP target_sp;
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 3ce5051cc4e..126ff78c389 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -66,7 +66,7 @@ ValueObjectPrinter::Init (ValueObject* valobj,
bool
ValueObjectPrinter::PrintValueObject ()
{
- if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ if (!GetMostSpecializedValue () || m_valobj == nullptr)
return false;
if (ShouldPrintValueObject())
@@ -97,7 +97,7 @@ ValueObjectPrinter::PrintValueObject ()
}
bool
-ValueObjectPrinter::GetDynamicValueIfNeeded ()
+ValueObjectPrinter::GetMostSpecializedValue ()
{
if (m_valobj)
return true;
@@ -134,6 +134,25 @@ ValueObjectPrinter::GetDynamicValueIfNeeded ()
else
m_valobj = m_orig_valobj;
}
+
+ if (m_valobj->IsSynthetic())
+ {
+ if (options.m_use_synthetic == false)
+ {
+ ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
+ if (non_synthetic)
+ m_valobj = non_synthetic;
+ }
+ }
+ else
+ {
+ if (options.m_use_synthetic == true)
+ {
+ ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
+ if (synthetic)
+ m_valobj = synthetic;
+ }
+ }
}
m_clang_type = m_valobj->GetClangType();
m_type_flags = m_clang_type.GetTypeInfo ();
@@ -442,8 +461,7 @@ ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
ValueObject*
ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
{
- ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);
- return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);
+ return m_valobj;
}
void
@@ -540,7 +558,13 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
{
// Aggregate, no children...
if (ShouldPrintValueObject())
- m_stream->PutCString(" {}\n");
+ {
+ // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
+ if (m_valobj->DoesProvideSyntheticValue())
+ m_stream->PutCString( "\n");
+ else
+ m_stream->PutCString(" {}\n");
+ }
}
else
{
@@ -552,7 +576,7 @@ ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
bool
ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
{
- if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
+ if (!GetMostSpecializedValue () || m_valobj == nullptr)
return false;
ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 721eedb59d7..87bfc955be0 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -124,6 +124,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
@@ -148,6 +149,7 @@ ScriptInterpreter::InitializeInterpreter (SWIGInitCallback python_swig_init_call
swig_get_valobj_sp_from_sbvalue,
swig_update_provider,
swig_mighthavechildren_provider,
+ swig_getvalue_provider,
swig_call_command,
swig_call_module_init,
swig_create_os_plugin,
diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
index 03b39d19de0..987a168079a 100644
--- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp
@@ -55,6 +55,7 @@ static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue
static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr;
static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr;
static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr;
+static ScriptInterpreter::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr;
static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = nullptr;
static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;
static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;
@@ -2140,6 +2141,42 @@ ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::Scr
return ret_val;
}
+lldb::ValueObjectSP
+ScriptInterpreterPython::GetSyntheticValue (const lldb::ScriptInterpreterObjectSP& implementor_sp)
+{
+ lldb::ValueObjectSP ret_val(nullptr);
+
+ if (!implementor_sp)
+ return ret_val;
+
+ void* implementor = implementor_sp->GetObject();
+
+ if (!implementor)
+ return ret_val;
+
+ if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue)
+ return ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ void* child_ptr = g_swig_getvalue_provider (implementor);
+ if (child_ptr != nullptr && child_ptr != Py_None)
+ {
+ lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
+ if (sb_value_ptr == nullptr)
+ Py_XDECREF(child_ptr);
+ else
+ ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
+ }
+ else
+ {
+ Py_XDECREF(child_ptr);
+ }
+ }
+
+ return ret_val;
+}
+
static std::string
ReadPythonBacktrace (PyObject* py_backtrace)
{
@@ -2616,6 +2653,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
+ SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
@@ -2639,6 +2677,7 @@ ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callb
g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
g_swig_update_provider = swig_update_provider;
g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
+ g_swig_getvalue_provider = swig_getvalue_provider;
g_swig_call_command = swig_call_command;
g_swig_call_module_init = swig_call_module_init;
g_swig_create_os_plugin = swig_create_os_plugin;
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py b/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
index 9c3bed1828a..36ff60babdb 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
+++ b/lldb/test/functionalities/data-formatter/data-formatter-synth/TestDataFormatterSynth.py
@@ -14,12 +14,14 @@ class SynthDataFormatterTestCase(TestBase):
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dsym_test
+ @unittest2.expectedFailure("rdar://15630776 - Summary cannot reference non-synthetic children if synthetic children exist")
def test_with_dsym_and_run_command(self):
"""Test data formatter commands."""
self.buildDsym()
self.data_formatter_commands()
@dwarf_test
+ @unittest2.expectedFailure("rdar://15630776 - Summary cannot reference non-synthetic children if synthetic children exist")
def test_with_dwarf_and_run_command(self):
"""Test data formatter commands."""
self.buildDwarf()
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synthval/Makefile b/lldb/test/functionalities/data-formatter/data-formatter-synthval/Makefile
new file mode 100644
index 00000000000..314f1cb2f07
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-synthval/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py
new file mode 100644
index 00000000000..c5ff06b04b4
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py
@@ -0,0 +1,95 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import lldbutil
+
+class DataFormatterSynthValueTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_with_dsym_and_run_command(self):
+ """Test using Python synthetic children provider to provide a value."""
+ self.buildDsym()
+ self.data_formatter_commands()
+
+ @skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser
+ @dwarf_test
+ def test_with_dwarf_and_run_command(self):
+ """Test using Python synthetic children provider to provide a value."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.cpp', 'break here')
+
+ def data_formatter_commands(self):
+ """Test using Python synthetic children provider to provide a value."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs = ['stopped',
+ 'stop reason = breakpoint'])
+
+ # This is the function to remove the custom formats in order to have a
+ # clean slate for the next test case.
+ def cleanup():
+ self.runCmd('type format clear', check=False)
+ self.runCmd('type summary clear', check=False)
+ self.runCmd('type filter clear', check=False)
+ self.runCmd('type synth clear', check=False)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ x = self.frame().FindVariable("x")
+ x.SetPreferSyntheticValue(True)
+ y = self.frame().FindVariable("y")
+ y.SetPreferSyntheticValue(True)
+ z = self.frame().FindVariable("z")
+ z.SetPreferSyntheticValue(True)
+
+ x_val = x.GetValueAsUnsigned
+ y_val = y.GetValueAsUnsigned
+ z_val = z.GetValueAsUnsigned
+
+ if self.TraceOn():
+ print "x_val = %s; y_val = %s; z_val = %s" % (x_val(),y_val(),z_val())
+
+ self.assertFalse(x_val() == 3, "x == 3 before synthetics")
+ self.assertFalse(y_val() == 4, "y == 4 before synthetics")
+ self.assertFalse(z_val() == 7, "z == 7 before synthetics")
+
+ # now set up the synth
+ self.runCmd("script from myIntSynthProvider import *")
+ self.runCmd("type synth add -l myIntSynthProvider myInt")
+
+ if self.TraceOn():
+ print "x_val = %s; y_val = %s; z_val = %s" % (x_val(),y_val(),z_val())
+
+ self.assertTrue(x_val() == 3, "x != 3 after synthetics")
+ self.assertTrue(y_val() == 4, "y != 4 after synthetics")
+ self.assertTrue(z_val() == 7, "z != 7 after synthetics")
+
+ self.expect("frame variable x", substrs=['3'])
+ self.expect("frame variable x", substrs=['theValue = 3'], matching=False)
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synthval/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-synthval/main.cpp
new file mode 100644
index 00000000000..fef128c1eb1
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-synthval/main.cpp
@@ -0,0 +1,15 @@
+class myInt {
+ private: int theValue;
+ public: myInt() : theValue(0) {}
+ public: myInt(int _x) : theValue(_x) {}
+ int val() { return theValue; }
+};
+
+myInt operator + (myInt x, myInt y) { return myInt(x.val() + y.val()); }
+
+int main() {
+ myInt x{3};
+ myInt y{4};
+ myInt z {x+y};
+ return z.val(); // break here
+}
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py b/lldb/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py
new file mode 100644
index 00000000000..d37cb0ecc5f
--- /dev/null
+++ b/lldb/test/functionalities/data-formatter/data-formatter-synthval/myIntSynthProvider.py
@@ -0,0 +1,17 @@
+class myIntSynthProvider(object):
+ def __init__(self, valobj, dict):
+ self.valobj = valobj;
+ self.val = self.valobj.GetChildMemberWithName("theValue")
+ def num_children(self):
+ return 0;
+ def get_child_at_index(self, index):
+ return None
+ def get_child_index(self, name):
+ return None
+ def update(self):
+ return False
+ def might_have_children(self):
+ return False
+ def get_value(self):
+ return self.val
+
OpenPOWER on IntegriCloud