2012-10-27 10:05:48 +08:00
|
|
|
//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
|
|
|
|
#include "lldb/Core/ValueObjectCast.h"
|
|
|
|
|
|
|
|
// C Includes
|
|
|
|
// C++ Includes
|
|
|
|
// Other libraries and framework includes
|
|
|
|
// Project includes
|
|
|
|
#include "lldb/Core/Log.h"
|
|
|
|
#include "lldb/Core/Module.h"
|
|
|
|
#include "lldb/Core/ValueObjectList.h"
|
|
|
|
#include "lldb/Core/Value.h"
|
|
|
|
#include "lldb/Core/ValueObject.h"
|
|
|
|
|
|
|
|
#include "lldb/Symbol/ClangASTType.h"
|
|
|
|
#include "lldb/Symbol/ObjectFile.h"
|
|
|
|
#include "lldb/Symbol/SymbolContext.h"
|
|
|
|
#include "lldb/Symbol/Type.h"
|
|
|
|
#include "lldb/Symbol/Variable.h"
|
|
|
|
|
|
|
|
#include "lldb/Target/ExecutionContext.h"
|
|
|
|
#include "lldb/Target/LanguageRuntime.h"
|
|
|
|
#include "lldb/Target/Process.h"
|
|
|
|
#include "lldb/Target/RegisterContext.h"
|
|
|
|
#include "lldb/Target/Target.h"
|
|
|
|
#include "lldb/Target/Thread.h"
|
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
|
|
lldb::ValueObjectSP
|
|
|
|
ValueObjectCast::Create (ValueObject &parent,
|
|
|
|
const ConstString &name,
|
|
|
|
const ClangASTType &cast_type)
|
|
|
|
{
|
|
|
|
ValueObjectCast *cast_valobj_ptr = new ValueObjectCast (parent, name, cast_type);
|
|
|
|
return cast_valobj_ptr->GetSP();
|
|
|
|
}
|
|
|
|
|
|
|
|
ValueObjectCast::ValueObjectCast
|
|
|
|
(
|
|
|
|
ValueObject &parent,
|
|
|
|
const ConstString &name,
|
|
|
|
const ClangASTType &cast_type
|
|
|
|
) :
|
|
|
|
ValueObject(parent),
|
|
|
|
m_cast_type (cast_type)
|
|
|
|
{
|
|
|
|
SetName (name);
|
2013-07-12 06:46:58 +08:00
|
|
|
//m_value.SetContext (Value::eContextTypeClangType, cast_type.GetOpaqueQualType());
|
|
|
|
m_value.SetClangType (cast_type);
|
2012-10-27 10:05:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ValueObjectCast::~ValueObjectCast()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-07-12 06:46:58 +08:00
|
|
|
ClangASTType
|
2012-10-27 10:05:48 +08:00
|
|
|
ValueObjectCast::GetClangTypeImpl ()
|
|
|
|
{
|
2013-07-12 06:46:58 +08:00
|
|
|
return m_cast_type;
|
2012-10-27 10:05:48 +08:00
|
|
|
}
|
|
|
|
|
2013-01-26 02:06:21 +08:00
|
|
|
size_t
|
2012-10-27 10:05:48 +08:00
|
|
|
ValueObjectCast::CalculateNumChildren()
|
|
|
|
{
|
2013-07-12 06:46:58 +08:00
|
|
|
return GetClangType().GetNumChildren (true);
|
2012-10-27 10:05:48 +08:00
|
|
|
}
|
|
|
|
|
2013-03-15 02:31:44 +08:00
|
|
|
uint64_t
|
2012-10-27 10:05:48 +08:00
|
|
|
ValueObjectCast::GetByteSize()
|
|
|
|
{
|
2013-07-12 06:46:58 +08:00
|
|
|
return m_value.GetValueByteSize(NULL);
|
2012-10-27 10:05:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
lldb::ValueType
|
|
|
|
ValueObjectCast::GetValueType() const
|
|
|
|
{
|
|
|
|
// Let our parent answer global, local, argument, etc...
|
|
|
|
return m_parent->GetValueType();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ValueObjectCast::UpdateValue ()
|
|
|
|
{
|
|
|
|
SetValueIsValid (false);
|
|
|
|
m_error.Clear();
|
|
|
|
|
|
|
|
if (m_parent->UpdateValueIfNeeded(false))
|
|
|
|
{
|
|
|
|
Value old_value(m_value);
|
|
|
|
m_update_point.SetUpdated();
|
|
|
|
m_value = m_parent->GetValue();
|
2013-07-12 06:46:58 +08:00
|
|
|
ClangASTType clang_type (GetClangType());
|
|
|
|
//m_value.SetContext (Value::eContextTypeClangType, clang_type);
|
|
|
|
m_value.SetClangType (clang_type);
|
2012-10-27 10:05:48 +08:00
|
|
|
SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren());
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
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
The rationale for doing things this way is twofold:
- 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
- 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
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
Comes with a test case
llvm-svn: 219330
2014-10-09 02:27:36 +08:00
|
|
|
if (!CanProvideValue())
|
2012-10-27 10:05:48 +08:00
|
|
|
{
|
|
|
|
// this value object represents an aggregate type whose
|
|
|
|
// children have values, but this object does not. So we
|
|
|
|
// say we are changed if our location has changed.
|
|
|
|
SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar());
|
|
|
|
}
|
|
|
|
ExecutionContext exe_ctx (GetExecutionContextRef());
|
2013-07-12 06:46:58 +08:00
|
|
|
m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
|
2012-10-27 10:05:48 +08:00
|
|
|
SetValueDidChange (m_parent->GetValueDidChange());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The dynamic value failed to get an error, pass the error along
|
|
|
|
if (m_error.Success() && m_parent->GetError().Fail())
|
|
|
|
m_error = m_parent->GetError();
|
|
|
|
SetValueIsValid (false);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ValueObjectCast::IsInScope ()
|
|
|
|
{
|
|
|
|
return m_parent->IsInScope();
|
|
|
|
}
|