<rdar://problem/12437442>
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)
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@166426 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBBlock.cpp b/source/API/SBBlock.cpp
index 8f325f4..91324ed 100644
--- a/source/API/SBBlock.cpp
+++ b/source/API/SBBlock.cpp
@@ -299,7 +299,12 @@
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);
+ }
}
}
}
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index 3fdadde..3f66623 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -549,12 +549,12 @@
{
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
{
@@ -619,8 +619,8 @@
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
@@ -697,8 +697,8 @@
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;
}
}
@@ -757,7 +757,7 @@
if (expr_var_sp)
{
value_sp = expr_var_sp->GetValueObject();
- sb_value.SetSP (value_sp);
+ sb_value.SetSP (value_sp, use_dynamic);
}
}
break;
@@ -939,7 +939,10 @@
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);
}
}
}
@@ -1102,7 +1105,7 @@
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
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index 5b38bc5..318029f 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -50,6 +50,98 @@
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 ()
{
@@ -57,12 +149,12 @@
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 &
@@ -70,7 +162,7 @@
{
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;
}
@@ -85,7 +177,7 @@
// 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
@@ -683,7 +775,7 @@
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));
@@ -712,7 +804,7 @@
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;
}
@@ -904,20 +996,12 @@
}
}
- 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());
@@ -993,20 +1077,12 @@
{
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());
@@ -1017,70 +1093,67 @@
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;
- lldb::ValueObjectSP value_sp(GetSP());
- if (value_sp)
+ SBValue value_sb;
+ if (IsValid())
{
- if (value_sp->IsSynthetic())
- {
- 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();
- }
- }
+ ValueImplSP proxy_sp(new ValueImpl(m_opaque_sp->GetRootSP(),m_opaque_sp->GetUseDynamic(),false));
+ value_sb.SetSP(proxy_sp);
}
- return sb_value;
+ 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
@@ -1099,6 +1172,22 @@
return false;
}
+bool
+SBValue::IsSynthetic ()
+{
+ lldb::ValueObjectSP value_sp(GetSP());
+ if (value_sp)
+ {
+ TargetSP target_sp(value_sp->GetTargetSP());
+ if (target_sp)
+ {
+ Mutex::Locker api_locker (target_sp->GetAPIMutex());
+ return value_sp->IsSynthetic();
+ }
+ }
+ return false;
+}
+
lldb::SBValue
SBValue::GetValueForExpressionPath(const char* expr_path)
{
@@ -1126,7 +1215,8 @@
}
}
- 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());
@@ -1457,17 +1547,77 @@
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)
@@ -1549,7 +1699,7 @@
{
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));
@@ -1805,4 +1955,3 @@
sb_watchpoint = Dereference().Watch (resolve_location, read, write, error);
return sb_watchpoint;
}
-