Given our implementation of ValueObjects we could have a scenario where a ValueObject has a dynamic type of Foo* at one point, and then its dynamic type changes to Bar*
If Bar* has synthetic children enabled, by the time we figure that out, our public API is already vending SBValues wrapping a DynamicVO, instead of a SyntheticVO and there was
no trivial way for us to change the SP inside an SBValue on the fly
This checkin reimplements SBValue in terms of a wrapper, ValueImpl, that allows this substitutions on-the-fly by overriding GetSP() to do The Right Thing (TM)
As an additional bonus, GetNonSyntheticValue() now works, and we can get rid of the ForceDisableSyntheticChildren idiom in ScriptInterpreterPython
Lastly, this checkin makes sure the synthetic VOs get the correct m_value and m_data from their parents (prevented summaries from working in some cases)
llvm-svn: 166426
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBType.h"
+namespace {
+ class ValueImpl;
+}
namespace lldb {
lldb::SBValue
GetNonSyntheticValue ();
+ lldb::DynamicValueType
+ GetPreferDynamicValue ();
+
+ void
+ SetPreferDynamicValue (lldb::DynamicValueType use_dynamic);
+
+ bool
+ GetPreferSyntheticValue ();
+
+ void
+ SetPreferSyntheticValue (bool use_synthetic);
+
bool
- IsDynamic();
+ IsDynamic ();
+
+ bool
+ IsSynthetic ();
const char *
GetLocation ();
// currently rely on being able to extract the SharedPointer out of an SBValue. if the implementation
// is deferred to the .cpp file instead of being inlined here, the platform will fail to link
// correctly. however, this is temporary till a better general solution is found. FIXME
- lldb::ValueObjectSP&
+ lldb::ValueObjectSP
get_sp()
{
- return m_opaque_sp;
+ return GetSP();
}
protected:
- friend class SBValueList;
+ friend class SBBlock;
friend class SBFrame;
friend class SBThread;
+ friend class SBValueList;
lldb::ValueObjectSP
GetSP () const;
- // anyone who needs to set the value of the SP on this SBValue should rely on SetSP() exclusively
- // since this function contains logic to "do the right thing" with regard to providing to the user
- // a synthetic value when possible - in the future the same should automatically occur with
- // dynamic values
+ // these calls do the right thing WRT adjusting their settings according to the target's preferences
void
SetSP (const lldb::ValueObjectSP &sp);
+
+ void
+ SetSP (const lldb::ValueObjectSP &sp, bool use_synthetic);
+
+ void
+ SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic);
+
+ void
+ SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic, bool use_synthetic);
private:
- lldb::ValueObjectSP m_opaque_sp;
+ typedef STD_SHARED_PTR(ValueImpl) ValueImplSP;
+ ValueImplSP m_opaque_sp;
+
+ void
+ SetSP (ValueImplSP impl_sp);
};
} // namespace lldb
GetDataExtractor ();
void
- ResetCompleteTypeInfo ();
+ ClearDynamicTypeInformation ();
//------------------------------------------------------------------
// Sublasses must implement the functions below.
friend class ValueObject;
ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter);
+ void
+ CopyParentData ();
+
//------------------------------------------------------------------
// For ValueObject only
//------------------------------------------------------------------
lldb::SBValue
GetNonSyntheticValue ();
+
+ lldb::DynamicValueType
+ GetPreferDynamicValue ();
+
+ void
+ SetPreferDynamicValue (lldb::DynamicValueType use_dynamic);
+
+ bool
+ GetPreferSyntheticValue ();
+
+ void
+ SetPreferSyntheticValue (bool use_synthetic);
bool
IsDynamic();
+
+ bool
+ IsSynthetic ();
const char *
GetLocation ();
// I do not want the SBValue to be deallocated when going out of scope because python
// has ownership of it and will manage memory for this object by itself
lldb::SBValue *valobj_sb = new lldb::SBValue(valobj_sp);
+ valobj_sb->SetPreferSyntheticValue(false);
PyObject *ValObj_PyObj = SWIG_NewPointerObj((void *)valobj_sb, SWIGTYPE_p_lldb__SBValue, 0);
if (add_variable)
{
if (frame_sp)
- value_list.Append (frame_sp->GetValueObjectForFrameVariable (variable_sp, use_dynamic));
+ {
+ lldb::ValueObjectSP valobj_sp(frame_sp->GetValueObjectForFrameVariable (variable_sp,eNoDynamicValues));
+ SBValue value_sb;
+ value_sb.SetSP(valobj_sp, use_dynamic);
+ value_list.Append (value_sb);
+ }
}
}
}
{
VariableSP var_sp;
Error error;
- ValueObjectSP value_sp (frame->GetValueForVariableExpressionPath (var_path,
- use_dynamic,
+ ValueObjectSP value_sp (frame->GetValueForVariableExpressionPath (var_path,
+ eNoDynamicValues,
StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
var_sp,
error));
- sb_value.SetSP(value_sp);
+ sb_value.SetSP(value_sp, use_dynamic);
}
else
{
if (var_sp)
{
- value_sp = frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
- sb_value.SetSP(value_sp);
+ value_sp = frame->GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
+ sb_value.SetSP(value_sp, use_dynamic);
}
}
else
variable_sp->GetScope() == value_type &&
variable_sp->GetName() == const_name)
{
- value_sp = frame->GetValueObjectForFrameVariable (variable_sp, use_dynamic);
- sb_value.SetSP (value_sp);
+ value_sp = frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues);
+ sb_value.SetSP (value_sp, use_dynamic);
break;
}
}
if (expr_var_sp)
{
value_sp = expr_var_sp->GetValueObject();
- sb_value.SetSP (value_sp);
+ sb_value.SetSP (value_sp, use_dynamic);
}
}
break;
if (in_scope_only && !variable_sp->IsInScope(frame))
continue;
- value_list.Append(frame->GetValueObjectForFrameVariable (variable_sp, use_dynamic));
+ ValueObjectSP valobj_sp(frame->GetValueObjectForFrameVariable (variable_sp, eNoDynamicValues));
+ SBValue value_sb;
+ value_sb.SetSP(valobj_sp,use_dynamic);
+ value_list.Append(value_sb);
}
}
}
frame,
expr_value_sp,
options.ref());
- expr_result.SetSP(expr_value_sp);
+ expr_result.SetSP(expr_value_sp,options.GetFetchDynamicValue());
#ifdef LLDB_CONFIGURATION_DEBUG
Host::SetCrashDescription (NULL);
#endif
using namespace lldb;
using namespace lldb_private;
+namespace {
+ class ValueImpl
+ {
+ public:
+ ValueImpl ()
+ {
+ }
+
+ ValueImpl (lldb::ValueObjectSP opaque_sp,
+ lldb::DynamicValueType use_dynamic,
+ bool use_synthetic) :
+ m_opaque_sp(opaque_sp),
+ m_use_dynamic(use_dynamic),
+ m_use_synthetic(use_synthetic)
+ {
+ }
+
+ ValueImpl (const ValueImpl& rhs) :
+ m_opaque_sp(rhs.m_opaque_sp),
+ m_use_dynamic(rhs.m_use_dynamic),
+ m_use_synthetic(rhs.m_use_synthetic)
+ {
+ }
+
+ ValueImpl &
+ operator = (const ValueImpl &rhs)
+ {
+ if (this != &rhs)
+ {
+ m_opaque_sp = rhs.m_opaque_sp;
+ m_use_dynamic = rhs.m_use_dynamic;
+ m_use_synthetic = rhs.m_use_synthetic;
+ }
+ return *this;
+ }
+
+ bool
+ IsValid ()
+ {
+ return m_opaque_sp.get() != NULL;
+ }
+
+ lldb::ValueObjectSP
+ GetRootSP ()
+ {
+ return m_opaque_sp;
+ }
+
+ lldb::ValueObjectSP
+ GetSP ()
+ {
+ if (!m_opaque_sp)
+ return m_opaque_sp;
+ lldb::ValueObjectSP value_sp = m_opaque_sp;
+ if (value_sp->GetDynamicValue(m_use_dynamic))
+ value_sp = value_sp->GetDynamicValue(m_use_dynamic);
+ if (value_sp->GetSyntheticValue(m_use_synthetic))
+ value_sp = value_sp->GetSyntheticValue(m_use_synthetic);
+ return value_sp;
+ }
+
+ void
+ SetUseDynamic (lldb::DynamicValueType use_dynamic)
+ {
+ m_use_dynamic = use_dynamic;
+ }
+
+ void
+ SetUseSynthetic (bool use_synthetic)
+ {
+ m_use_synthetic = use_synthetic;
+ }
+
+ lldb::DynamicValueType
+ GetUseDynamic ()
+ {
+ return m_use_dynamic;
+ }
+
+ bool
+ GetUseSynthetic ()
+ {
+ return m_use_synthetic;
+ }
+
+ private:
+ lldb::ValueObjectSP m_opaque_sp;
+ lldb::DynamicValueType m_use_dynamic;
+ bool m_use_synthetic;
+ };
+}
+
SBValue::SBValue () :
m_opaque_sp ()
{
SBValue::SBValue (const lldb::ValueObjectSP &value_sp)
{
- SetSP(value_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
+ SetSP(value_sp);
}
SBValue::SBValue(const SBValue &rhs)
{
- SetSP(rhs.m_opaque_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
+ SetSP(rhs.m_opaque_sp);
}
SBValue &
{
if (this != &rhs)
{
- SetSP(rhs.m_opaque_sp); // whenever setting the SP call SetSP() since it knows how to deal with synthetic values properly
+ SetSP(rhs.m_opaque_sp);
}
return *this;
}
// If this function ever changes to anything that does more than just
// check if the opaque shared pointer is non NULL, then we need to update
// all "if (m_opaque_sp)" code in this file.
- return m_opaque_sp.get() != NULL;
+ return m_opaque_sp.get() != NULL && m_opaque_sp->GetRootSP().get() != NULL;
}
void
TypeImplSP type_sp (type.GetSP());
if (type.IsValid())
{
- sb_value = SBValue(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(), true));
+ sb_value.SetSP(value_sp->GetSyntheticChildAtOffset(offset, type_sp->GetClangASTType(), true),GetPreferDynamicValue(),GetPreferSyntheticValue());
new_value_sp = sb_value.GetSP();
if (new_value_sp)
new_value_sp->SetName(ConstString(name));
lldb::ValueObjectSP value_sp(GetSP());
TypeImplSP type_sp (type.GetSP());
if (value_sp && type_sp)
- sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType()));
+ sb_value.SetSP(value_sp->Cast(type_sp->GetClangASTType()),GetPreferDynamicValue(),GetPreferSyntheticValue());
return sb_value;
}
}
}
- if (child_sp)
- {
- if (use_dynamic != lldb::eNoDynamicValues)
- {
- lldb::ValueObjectSP dynamic_sp(child_sp->GetDynamicValue (use_dynamic));
- if (dynamic_sp)
- child_sp = dynamic_sp;
- }
- }
}
}
}
- SBValue sb_value (child_sp);
+ SBValue sb_value;
+ sb_value.SetSP (child_sp, use_dynamic, GetPreferSyntheticValue());
if (log)
log->Printf ("SBValue(%p)::GetChildAtIndex (%u) => SBValue(%p)", value_sp.get(), idx, value_sp.get());
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
child_sp = value_sp->GetChildMemberWithName (str_name, true);
- if (use_dynamic_value != lldb::eNoDynamicValues)
- {
- if (child_sp)
- {
- lldb::ValueObjectSP dynamic_sp = child_sp->GetDynamicValue (use_dynamic_value);
- if (dynamic_sp)
- child_sp = dynamic_sp;
- }
- }
}
}
}
- SBValue sb_value (child_sp);
+ SBValue sb_value;
+ sb_value.SetSP(child_sp, use_dynamic_value, GetPreferSyntheticValue());
if (log)
log->Printf ("SBValue(%p)::GetChildMemberWithName (name=\"%s\") => SBValue(%p)", value_sp.get(), name, value_sp.get());
lldb::SBValue
SBValue::GetDynamicValue (lldb::DynamicValueType use_dynamic)
{
- lldb::ValueObjectSP value_sp(GetSP());
- if (value_sp)
+ SBValue value_sb;
+ if (IsValid())
{
- ProcessSP process_sp(value_sp->GetProcessSP());
- Process::StopLocker stop_locker;
- if (process_sp && !stop_locker.TryLock(&process_sp->GetRunLock()))
- {
- LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
- if (log)
- log->Printf ("SBValue(%p)::GetDynamicValue() => error: process is running", value_sp.get());
- }
- else
- {
- TargetSP target_sp(value_sp->GetTargetSP());
- if (target_sp)
- {
- Mutex::Locker api_locker (target_sp->GetAPIMutex());
- return SBValue (value_sp->GetDynamicValue(use_dynamic));
- }
- }
+ ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(),use_dynamic,m_opaque_sp->GetUseSynthetic()));
+ value_sb.SetSP(proxy_sp);
}
-
- return SBValue();
+ return value_sb;
}
lldb::SBValue
SBValue::GetStaticValue ()
{
- lldb::ValueObjectSP value_sp(GetSP());
- if (value_sp)
+ SBValue value_sb;
+ if (IsValid())
{
- TargetSP target_sp(value_sp->GetTargetSP());
- if (target_sp)
- {
- Mutex::Locker api_locker (target_sp->GetAPIMutex());
- return SBValue(value_sp->GetStaticValue());
- }
+ ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(),eNoDynamicValues,m_opaque_sp->GetUseSynthetic()));
+ value_sb.SetSP(proxy_sp);
}
-
- return SBValue();
+ return value_sb;
}
lldb::SBValue
SBValue::GetNonSyntheticValue ()
{
- SBValue sb_value;
+ SBValue value_sb;
+ if (IsValid())
+ {
+ ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(),m_opaque_sp->GetUseDynamic(),false));
+ value_sb.SetSP(proxy_sp);
+ }
+ return value_sb;
+}
+
+lldb::DynamicValueType
+SBValue::GetPreferDynamicValue ()
+{
+ if (!IsValid())
+ return eNoDynamicValues;
+ return m_opaque_sp->GetUseDynamic();
+}
+
+void
+SBValue::SetPreferDynamicValue (lldb::DynamicValueType use_dynamic)
+{
+ if (IsValid())
+ return m_opaque_sp->SetUseDynamic (use_dynamic);
+}
+
+bool
+SBValue::GetPreferSyntheticValue ()
+{
+ if (!IsValid())
+ return false;
+ return m_opaque_sp->GetUseSynthetic();
+}
+
+void
+SBValue::SetPreferSyntheticValue (bool use_synthetic)
+{
+ if (IsValid())
+ return m_opaque_sp->SetUseSynthetic (use_synthetic);
+}
+
+bool
+SBValue::IsDynamic()
+{
lldb::ValueObjectSP value_sp(GetSP());
if (value_sp)
{
- if (value_sp->IsSynthetic())
+ TargetSP target_sp(value_sp->GetTargetSP());
+ if (target_sp)
{
- TargetSP target_sp(value_sp->GetTargetSP());
- if (target_sp)
- {
- Mutex::Locker api_locker (target_sp->GetAPIMutex());
- // deliberately breaking the rules here to optimize the case where we DO NOT want
- // the synthetic value to be returned to the user - if we did not do this, we would have to tell
- // the target to suppress the synthetic value, and then return the flag to its original value
- if (value_sp->GetNonSyntheticValue())
- sb_value.m_opaque_sp = value_sp->GetNonSyntheticValue();
- }
+ Mutex::Locker api_locker (target_sp->GetAPIMutex());
+ return value_sp->IsDynamic();
}
}
- return sb_value;
+ return false;
}
bool
-SBValue::IsDynamic()
+SBValue::IsSynthetic ()
{
lldb::ValueObjectSP value_sp(GetSP());
if (value_sp)
if (target_sp)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
- return value_sp->IsDynamic();
+ return value_sp->IsSynthetic();
}
}
return false;
}
}
- SBValue sb_value (child_sp);
+ SBValue sb_value;
+ sb_value.SetSP(child_sp,GetPreferDynamicValue(),GetPreferSyntheticValue());
if (log)
log->Printf ("SBValue(%p)::GetValueForExpressionPath (expr_path=\"%s\") => SBValue(%p)", value_sp.get(), expr_path, value_sp.get());
lldb::ValueObjectSP
SBValue::GetSP () const
{
- return m_opaque_sp;
+ if (!m_opaque_sp || !m_opaque_sp->IsValid())
+ return ValueObjectSP();
+ return m_opaque_sp->GetSP();
+}
+
+void
+SBValue::SetSP (ValueImplSP impl_sp)
+{
+ m_opaque_sp = impl_sp;
}
void
SBValue::SetSP (const lldb::ValueObjectSP &sp)
{
- m_opaque_sp = sp;
- if (IsValid() && m_opaque_sp->HasSyntheticValue())
- m_opaque_sp = m_opaque_sp->GetSyntheticValue();
+ if (sp)
+ {
+ lldb::TargetSP target_sp(sp->GetTargetSP());
+ if (target_sp)
+ {
+ lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue();
+ bool use_synthetic = target_sp->TargetProperties::GetEnableSyntheticValue();
+ m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic));
+ }
+ else
+ m_opaque_sp = ValueImplSP(new ValueImpl(sp,eNoDynamicValues,true));
+ }
+ else
+ m_opaque_sp = ValueImplSP(new ValueImpl(sp,eNoDynamicValues,false));
}
+void
+SBValue::SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic)
+{
+ if (sp)
+ {
+ lldb::TargetSP target_sp(sp->GetTargetSP());
+ if (target_sp)
+ {
+ bool use_synthetic = target_sp->TargetProperties::GetEnableSyntheticValue();
+ SetSP (sp, use_dynamic, use_synthetic);
+ }
+ else
+ SetSP (sp, use_dynamic, true);
+ }
+ else
+ SetSP (sp, use_dynamic, false);
+}
+
+void
+SBValue::SetSP (const lldb::ValueObjectSP &sp, bool use_synthetic)
+{
+ if (sp)
+ {
+ lldb::TargetSP target_sp(sp->GetTargetSP());
+ if (target_sp)
+ {
+ lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue();
+ SetSP (sp, use_dynamic, use_synthetic);
+ }
+ else
+ SetSP (sp, eNoDynamicValues, use_synthetic);
+ }
+ else
+ SetSP (sp, eNoDynamicValues, use_synthetic);
+}
+
+void
+SBValue::SetSP (const lldb::ValueObjectSP &sp, lldb::DynamicValueType use_dynamic, bool use_synthetic)
+{
+ m_opaque_sp = ValueImplSP(new ValueImpl(sp,use_dynamic,use_synthetic));
+}
bool
SBValue::GetExpressionPath (SBStream &description)
{
Mutex::Locker api_locker (target_sp->GetAPIMutex());
Error error;
- sb_value = value_sp->AddressOf (error);
+ sb_value.SetSP(value_sp->AddressOf (error),GetPreferDynamicValue(), GetPreferSyntheticValue());
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
sb_watchpoint = Dereference().Watch (resolve_location, read, write, error);
return sb_watchpoint;
}
-
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
- lldb::TypeCategoryImplSP category = *begin;
+ lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeSummaryImplSP current_format;
- if (!category->Get(valobj, current_format, use_dynamic, &reason_why))
+ if (log)
+ log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s\n", category_sp->GetName());
+ if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
continue;
return current_format;
}
+ if (log)
+ log->Printf("[CategoryMap::GetSummaryFormat] nothing found - returning empty SP\n");
return lldb::TypeSummaryImplSP();
}
ActiveCategoriesIterator begin, end = m_active_categories.end();
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+
for (begin = m_active_categories.begin(); begin != end; begin++)
{
- lldb::TypeCategoryImplSP category = *begin;
+ lldb::TypeCategoryImplSP category_sp = *begin;
lldb::SyntheticChildrenSP current_format;
- if (!category->Get(valobj, current_format, use_dynamic, &reason_why))
+ if (log)
+ log->Printf("[CategoryMap::GetSyntheticChildren] Trying to use category %s\n", category_sp->GetName());
+ if (!category_sp->Get(valobj, current_format, use_dynamic, &reason_why))
continue;
return current_format;
}
+ if (log)
+ log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning empty SP\n");
return lldb::SyntheticChildrenSP();
}
#endif
}
void
-ValueObject::ResetCompleteTypeInfo ()
+ValueObject::ClearDynamicTypeInformation ()
{
m_did_calculate_complete_objc_class_type = false;
+ m_last_format_mgr_revision = 0;
m_override_type = ClangASTType();
+ SetValueFormat(lldb::TypeFormatImplSP());
+ SetSummaryFormat(lldb::TypeSummaryImplSP());
+ SetSyntheticChildren(lldb::SyntheticChildrenSP());
}
ClangASTType
return;
}
+ lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
+
if (!UpdateFormatsIfNeeded(m_last_format_mgr_dynamic) && m_synthetic_value)
return;
if (m_synthetic_children_sp.get() == NULL)
return;
+ if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value)
+ return;
+
m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp);
}
ExecutionContext exe_ctx (GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
if (process && process->IsPossibleDynamicValue(*this))
+ {
+ ClearDynamicTypeInformation ();
m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic);
+ }
}
}
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
+ bool has_changed_type = false;
+
if (!m_type_sp)
{
m_type_sp = dynamic_type_sp;
- ResetCompleteTypeInfo ();
- if (log)
- log->Printf("[%s %p] now has a dynamic type %s",
- GetName().GetCString(),
- this,
- GetTypeName().AsCString(""));
+ has_changed_type = true;
}
else if (dynamic_type_sp != m_type_sp)
{
// We are another type, we need to tear down our children...
m_type_sp = dynamic_type_sp;
SetValueDidChange (true);
- ResetCompleteTypeInfo ();
- if (log)
- log->Printf("[%s %p] has a new dynamic type %s",
- GetName().GetCString(),
- this,
- GetTypeName().AsCString(""));
+ has_changed_type = true;
}
+ if (has_changed_type)
+ ClearDynamicTypeInformation ();
+
if (!m_address.IsValid() || m_address != dynamic_address)
{
if (m_address.IsValid())
// because we aren't pointing to the LOCATION that stores the pointer to us, we're pointing to us...
m_value.SetValueType(Value::eValueTypeScalar);
+ if (has_changed_type && log)
+ log->Printf("[%s %p] has a new dynamic type %s",
+ GetName().GetCString(),
+ this,
+ GetTypeName().GetCString());
+
if (m_address.IsValid() && m_type_sp)
{
// The variable value is in the Scalar value inside the m_value.
#else
SetName(parent.GetName());
#endif
+ CopyParentData();
CreateSynthFilter();
}
m_synthetic_children_count = UINT32_MAX;
}
+ CopyParentData();
+
SetValueIsValid(true);
return true;
}
{
return m_parent->GetSP();
}
+
+void
+ValueObjectSynthetic::CopyParentData ()
+{
+ m_value = m_parent->GetValue();
+ ExecutionContext exe_ctx (GetExecutionContextRef());
+ m_error = m_value.GetValueAsData (&exe_ctx, GetClangAST(), m_data, 0, GetModule().get());
+}
DoFreeLock();
}
-class ForceDisableSyntheticChildren
-{
-public:
- ForceDisableSyntheticChildren (Target* target) :
- m_target(target)
- {
- m_old_value = target->GetSuppressSyntheticValue();
- target->SetSuppressSyntheticValue(true);
- }
- ~ForceDisableSyntheticChildren ()
- {
- m_target->SetSuppressSyntheticValue(m_old_value);
- }
-private:
- Target* m_target;
- bool m_old_value;
-};
-
ScriptInterpreterPython::PythonInputReaderManager::PythonInputReaderManager (ScriptInterpreterPython *interpreter) :
m_interpreter(interpreter),
m_debugger_sp(),
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(target);
- ret_val = g_swig_synthetic_script (class_name,
- python_interpreter->m_dictionary_name.c_str(),
- valobj);
+ ret_val = g_swig_synthetic_script (class_name,
+ python_interpreter->m_dictionary_name.c_str(),
+ valobj);
}
return MakeScriptObject(ret_val);
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_calc_children (implementor);
+ ret_val = g_swig_calc_children (implementor);
}
return ret_val;
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- child_ptr = g_swig_get_child_index (implementor,idx);
+ child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != NULL && child_ptr != Py_None)
{
value_sb = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_get_index_child (implementor, child_name);
+ ret_val = g_swig_get_index_child (implementor, child_name);
}
return ret_val;
{
Locker py_lock(this);
- ForceDisableSyntheticChildren no_synthetics(GetCommandInterpreter().GetDebugger().GetSelectedTarget().get());
- ret_val = g_swig_update_provider (implementor);
+ ret_val = g_swig_update_provider (implementor);
}
return ret_val;
--- /dev/null
+LEVEL = ../../../make
+
+OBJC_SOURCES := main.m
+
+CFLAGS_EXTRAS += -w
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation
--- /dev/null
+"""
+Test lldb data formatter subsystem.
+"""
+
+import os, time
+import unittest2
+import lldb
+from lldbtest import *
+import datetime
+import lldbutil
+
+class DataFormatterRdar12437442TestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "data-formatter", "rdar-12437442")
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_rdar12437442_with_dsym_and_run_command(self):
+ """Test that we update SBValues correctly as dynamic types change."""
+ self.buildDsym()
+ self.rdar12437442_tester()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dwarf_test
+ def test_rdar12437442_with_dwarf_and_run_command(self):
+ """Test that we update SBValues correctly as dynamic types change."""
+ self.buildDwarf()
+ self.rdar12437442_tester()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break at.
+ self.line = line_number('main.m', '// Set break point at this line.')
+
+ def rdar12437442_tester(self):
+ """Test that we update SBValues correctly as dynamic types change."""
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+ lldbutil.run_break_set_by_file_and_line (self, "main.m", 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 synth clear', check=False)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ self.runCmd("log enable lldb types -f types.log")
+
+ # Now run the bulk of the test
+ id_x = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable("x")
+ id_x.SetPreferDynamicValue(lldb.eDynamicCanRunTarget)
+ id_x.SetPreferSyntheticValue(True)
+
+ if self.TraceOn():
+ self.runCmd("frame variable x -d run-target --ptr-depth 1")
+
+ self.assertTrue(id_x.GetSummary() == '@"5 objects"', "array does not get correct summary")
+
+ self.runCmd("next")
+
+ id_x = self.dbg.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().FindVariable("x")
+ id_x.SetPreferDynamicValue(lldb.eDynamicCanRunTarget)
+ id_x.SetPreferSyntheticValue(True)
+
+ if self.TraceOn():
+ self.runCmd("frame variable x -d run-target --ptr-depth 1")
+
+ self.assertTrue(id_x.GetNumChildren() == 7, "dictionary does not have 7 children")
+ id_x.SetPreferSyntheticValue(False)
+ self.assertFalse(id_x.GetNumChildren() == 7, "dictionary still looks synthetic")
+ id_x.SetPreferSyntheticValue(True)
+ self.assertTrue(id_x.GetSummary() == "7 key/value pairs", "dictionary does not get correct summary")
+
+
+if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+ atexit.register(lambda: lldb.SBDebugger.Terminate())
+ unittest2.main()
--- /dev/null
+//===-- main.m ------------------------------------------------*- ObjC -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#import <Foundation/Foundation.h>
+
+int main (int argc, const char * argv[])
+{
+
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray* foo = [NSArray arrayWithObjects:@1,@2,@3,@4,@5, nil];
+ NSDictionary *bar = @{@1 : @"one",@2 : @"two", @3 : @"three", @4 : @"four", @5 : @"five", @6 : @"six", @7 : @"seven"};
+ id x = foo;
+ x = bar; // Set break point at this line.
+
+ [pool drain];
+ return 0;
+}
+