//===-- ValueObject.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/lldb-python.h"

#include "lldb/Core/ValueObject.h"

// C Includes
#include <stdlib.h>

// C++ Includes
// Other libraries and framework includes
#include "llvm/Support/raw_ostream.h"
#include "clang/AST/Type.h"

// Project includes
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObjectCast.h"
#include "lldb/Core/ValueObjectChild.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectDynamicValue.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectSyntheticFilter.h"

#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"

#include "lldb/Host/Endian.h"

#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"

#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Type.h"

#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_utility;

static user_id_t g_value_obj_uid = 0;

//----------------------------------------------------------------------
// ValueObject constructor
//----------------------------------------------------------------------
ValueObject::ValueObject (ValueObject &parent) :
    UserID (++g_value_obj_uid), // Unique identifier for every value object
    m_parent (&parent),
    m_root (NULL),
    m_update_point (parent.GetUpdatePoint ()),
    m_name (),
    m_data (),
    m_value (),
    m_error (),
    m_value_str (),
    m_old_value_str (),
    m_location_str (),
    m_summary_str (),
    m_object_desc_str (),
    m_manager(parent.GetManager()),
    m_children (),
    m_synthetic_children (),
    m_dynamic_value (NULL),
    m_synthetic_value(NULL),
    m_deref_valobj(NULL),
    m_format (eFormatDefault),
    m_last_format (eFormatDefault),
    m_last_format_mgr_revision(0),
    m_type_summary_sp(),
    m_type_format_sp(),
    m_synthetic_children_sp(),
    m_user_id_of_forced_summary(),
    m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid),
    m_value_is_valid (false),
    m_value_did_change (false),
    m_children_count_valid (false),
    m_old_value_valid (false),
    m_is_deref_of_parent (false),
    m_is_array_item_for_pointer(false),
    m_is_bitfield_for_scalar(false),
    m_is_child_at_offset(false),
    m_is_getting_summary(false),
    m_did_calculate_complete_objc_class_type(false)
{
    m_manager->ManageObject(this);
}

//----------------------------------------------------------------------
// ValueObject constructor
//----------------------------------------------------------------------
ValueObject::ValueObject (ExecutionContextScope *exe_scope,
                          AddressType child_ptr_or_ref_addr_type) :
    UserID (++g_value_obj_uid), // Unique identifier for every value object
    m_parent (NULL),
    m_root (NULL),
    m_update_point (exe_scope),
    m_name (),
    m_data (),
    m_value (),
    m_error (),
    m_value_str (),
    m_old_value_str (),
    m_location_str (),
    m_summary_str (),
    m_object_desc_str (),
    m_manager(),
    m_children (),
    m_synthetic_children (),
    m_dynamic_value (NULL),
    m_synthetic_value(NULL),
    m_deref_valobj(NULL),
    m_format (eFormatDefault),
    m_last_format (eFormatDefault),
    m_last_format_mgr_revision(0),
    m_type_summary_sp(),
    m_type_format_sp(),
    m_synthetic_children_sp(),
    m_user_id_of_forced_summary(),
    m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
    m_value_is_valid (false),
    m_value_did_change (false),
    m_children_count_valid (false),
    m_old_value_valid (false),
    m_is_deref_of_parent (false),
    m_is_array_item_for_pointer(false),
    m_is_bitfield_for_scalar(false),
    m_is_child_at_offset(false),
    m_is_getting_summary(false),
    m_did_calculate_complete_objc_class_type(false)
{
    m_manager = new ValueObjectManager();
    m_manager->ManageObject (this);
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
ValueObject::~ValueObject ()
{
}

bool
ValueObject::UpdateValueIfNeeded (bool update_format)
{
    
    bool did_change_formats = false;
    
    if (update_format)
        did_change_formats = UpdateFormatsIfNeeded();
    
    // If this is a constant value, then our success is predicated on whether
    // we have an error or not
    if (GetIsConstant())
    {
        // if you are constant, things might still have changed behind your back
        // (e.g. you are a frozen object and things have changed deeper than you cared to freeze-dry yourself)
        // in this case, your value has not changed, but "computed" entries might have, so you might now have
        // a different summary, or a different object description. clear these so we will recompute them
        if (update_format && !did_change_formats)
            ClearUserVisibleData(eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsDescription);
        return m_error.Success();
    }

    bool first_update = m_update_point.IsFirstEvaluation();
    
    if (m_update_point.NeedsUpdating())
    {
        m_update_point.SetUpdated();
        
        // Save the old value using swap to avoid a string copy which
        // also will clear our m_value_str
        if (m_value_str.empty())
        {
            m_old_value_valid = false;
        }
        else
        {
            m_old_value_valid = true;
            m_old_value_str.swap (m_value_str);
            ClearUserVisibleData(eClearUserVisibleDataItemsValue);
        }

        ClearUserVisibleData();
        
        if (IsInScope())
        {
            const bool value_was_valid = GetValueIsValid();
            SetValueDidChange (false);
            
            m_error.Clear();

            // Call the pure virtual function to update the value
            bool success = UpdateValue ();
            
            SetValueIsValid (success);
            
            if (first_update)
                SetValueDidChange (false);
            else if (!m_value_did_change && success == false)
            {
                // The value wasn't gotten successfully, so we mark this
                // as changed if the value used to be valid and now isn't
                SetValueDidChange (value_was_valid);
            }
        }
        else
        {
            m_error.SetErrorString("out of scope");
        }
    }
    return m_error.Success();
}

bool
ValueObject::UpdateFormatsIfNeeded()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
    if (log)
        log->Printf("[%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d",
                    GetName().GetCString(), static_cast<void*>(this),
                    m_last_format_mgr_revision,
                    DataVisualization::GetCurrentRevision());

    bool any_change = false;

    if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision()))
    {
        m_last_format_mgr_revision = DataVisualization::GetCurrentRevision();
        any_change = true;
        
        SetValueFormat(DataVisualization::GetFormat (*this, eNoDynamicValues));
        SetSummaryFormat(DataVisualization::GetSummaryFormat (*this, GetDynamicValueType()));
#ifndef LLDB_DISABLE_PYTHON
        SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType()));
#endif
    }

    return any_change;
}

void
ValueObject::SetNeedsUpdate ()
{
    m_update_point.SetNeedsUpdate();
    // We have to clear the value string here so ConstResult children will notice if their values are
    // changed by hand (i.e. with SetValueAsCString).
    ClearUserVisibleData(eClearUserVisibleDataItemsValue);
}

void
ValueObject::ClearDynamicTypeInformation ()
{
    m_children_count_valid = false;
    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
ValueObject::MaybeCalculateCompleteType ()
{
    ClangASTType clang_type(GetClangTypeImpl());
        
    if (m_did_calculate_complete_objc_class_type)
    {
        if (m_override_type.IsValid())
            return m_override_type;
        else
            return clang_type;
    }
    
    ClangASTType class_type;
    bool is_pointer_type = false;
    
    if (clang_type.IsObjCObjectPointerType(&class_type))
    {
        is_pointer_type = true;
    }
    else if (clang_type.IsObjCObjectOrInterfaceType())
    {
        class_type = clang_type;
    }
    else
    {
        return clang_type;
    }
    
    m_did_calculate_complete_objc_class_type = true;
    
    if (class_type)
    {
        ConstString class_name (class_type.GetConstTypeName());
        
        if (class_name)
        {
            ProcessSP process_sp(GetUpdatePoint().GetExecutionContextRef().GetProcessSP());
            
            if (process_sp)
            {
                ObjCLanguageRuntime *objc_language_runtime(process_sp->GetObjCLanguageRuntime());
                
                if (objc_language_runtime)
                {
                    TypeSP complete_objc_class_type_sp = objc_language_runtime->LookupInCompleteClassCache(class_name);
                    
                    if (complete_objc_class_type_sp)
                    {
                        ClangASTType complete_class(complete_objc_class_type_sp->GetClangFullType());
                        
                        if (complete_class.GetCompleteType())
                        {
                            if (is_pointer_type)
                            {
                                m_override_type = complete_class.GetPointerType();
                            }
                            else
                            {
                                m_override_type = complete_class;
                            }
                            
                            if (m_override_type.IsValid())
                                return m_override_type;
                        }
                    }
                }
            }
        }
    }
    return clang_type;
}

ClangASTType
ValueObject::GetClangType ()
{
    return MaybeCalculateCompleteType();
}

TypeImpl
ValueObject::GetTypeImpl ()
{
    return TypeImpl(GetClangType());
}

DataExtractor &
ValueObject::GetDataExtractor ()
{
    UpdateValueIfNeeded(false);
    return m_data;
}

const Error &
ValueObject::GetError()
{
    UpdateValueIfNeeded(false);
    return m_error;
}

const ConstString &
ValueObject::GetName() const
{
    return m_name;
}

const char *
ValueObject::GetLocationAsCString ()
{
    return GetLocationAsCStringImpl(m_value,
                                    m_data);
}

const char *
ValueObject::GetLocationAsCStringImpl (const Value& value,
                                       const DataExtractor& data)
{
    if (UpdateValueIfNeeded(false))
    {
        if (m_location_str.empty())
        {
            StreamString sstr;
            
            Value::ValueType value_type = value.GetValueType();
            
            switch (value_type)
            {
            case Value::eValueTypeScalar:
            case Value::eValueTypeVector:
                if (value.GetContextType() == Value::eContextTypeRegisterInfo)
                {
                    RegisterInfo *reg_info = value.GetRegisterInfo();
                    if (reg_info)
                    {
                        if (reg_info->name)
                            m_location_str = reg_info->name;
                        else if (reg_info->alt_name)
                            m_location_str = reg_info->alt_name;
                        if (m_location_str.empty())
                            m_location_str = (reg_info->encoding == lldb::eEncodingVector) ? "vector" : "scalar";
                    }
                }
                if (m_location_str.empty())
                    m_location_str = (value_type == Value::eValueTypeVector) ? "vector" : "scalar";
                break;

            case Value::eValueTypeLoadAddress:
            case Value::eValueTypeFileAddress:
            case Value::eValueTypeHostAddress:
                {
                    uint32_t addr_nibble_size = data.GetAddressByteSize() * 2;
                    sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS));
                    m_location_str.swap(sstr.GetString());
                }
                break;
            }
        }
    }
    return m_location_str.c_str();
}

Value &
ValueObject::GetValue()
{
    return m_value;
}

const Value &
ValueObject::GetValue() const
{
    return m_value;
}

bool
ValueObject::ResolveValue (Scalar &scalar)
{
    if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        Value tmp_value(m_value);
        scalar = tmp_value.ResolveValue(&exe_ctx);
        if (scalar.IsValid())
        {
            const uint32_t bitfield_bit_size = GetBitfieldBitSize();
            if (bitfield_bit_size)
                return scalar.ExtractBitfield (bitfield_bit_size, GetBitfieldBitOffset());
            return true;
        }
    }
    return false;
}

bool
ValueObject::GetValueIsValid () const
{
    return m_value_is_valid;
}


void
ValueObject::SetValueIsValid (bool b)
{
    m_value_is_valid = b;
}

bool
ValueObject::GetValueDidChange ()
{
    GetValueAsCString ();
    return m_value_did_change;
}

void
ValueObject::SetValueDidChange (bool value_changed)
{
    m_value_did_change = value_changed;
}

ValueObjectSP
ValueObject::GetChildAtIndex (size_t idx, bool can_create)
{
    ValueObjectSP child_sp;
    // We may need to update our value if we are dynamic
    if (IsPossibleDynamicType ())
        UpdateValueIfNeeded(false);
    if (idx < GetNumChildren())
    {
        // Check if we have already made the child value object?
        if (can_create && !m_children.HasChildAtIndex(idx))
        {
            // No we haven't created the child at this index, so lets have our
            // subclass do it and cache the result for quick future access.
            m_children.SetChildAtIndex(idx,CreateChildAtIndex (idx, false, 0));
        }
        
        ValueObject* child = m_children.GetChildAtIndex(idx);
        if (child != NULL)
            return child->GetSP();
    }
    return child_sp;
}

ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::initializer_list<size_t>& idxs,
                                  size_t* index_of_error)
{
    if (idxs.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (size_t idx : idxs)
    {
        root = root->GetChildAtIndex(idx, true);
        if (!root)
        {
            if (index_of_error)
                *index_of_error = idx;
            return root;
        }
    }
    return root;
}

ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> >& idxs,
                                  size_t* index_of_error)
{
    if (idxs.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (std::pair<size_t, bool> idx : idxs)
    {
        root = root->GetChildAtIndex(idx.first, idx.second);
        if (!root)
        {
            if (index_of_error)
                *index_of_error = idx.first;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::vector<size_t> &idxs,
                                  size_t* index_of_error)
{
    if (idxs.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (size_t idx : idxs)
    {
        root = root->GetChildAtIndex(idx, true);
        if (!root)
        {
            if (index_of_error)
                *index_of_error = idx;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs,
                                  size_t* index_of_error)
{
    if (idxs.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (std::pair<size_t, bool> idx : idxs)
    {
        root = root->GetChildAtIndex(idx.first, idx.second);
        if (!root)
        {
            if (index_of_error)
                *index_of_error = idx.first;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names,
                                 ConstString* name_of_error)
{
    if (names.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (ConstString name : names)
    {
        root = root->GetChildMemberWithName(name, true);
        if (!root)
        {
            if (name_of_error)
                *name_of_error = name;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names,
                                 ConstString* name_of_error)
{
    if (names.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (ConstString name : names)
    {
        root = root->GetChildMemberWithName(name, true);
        if (!root)
        {
            if (name_of_error)
                *name_of_error = name;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
                                 ConstString* name_of_error)
{
    if (names.size() == 0)
        return GetSP();
    ValueObjectSP root(GetSP());
    for (std::pair<ConstString, bool> name : names)
    {
        root = root->GetChildMemberWithName(name.first, name.second);
        if (!root)
        {
            if (name_of_error)
                *name_of_error = name.first;
            return root;
        }
    }
    return root;
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names,
                                 ConstString* name_of_error)
{
    if (names.size() == 0)
        return GetSP();
        ValueObjectSP root(GetSP());
        for (std::pair<ConstString, bool> name : names)
        {
            root = root->GetChildMemberWithName(name.first, name.second);
            if (!root)
            {
                if (name_of_error)
                    *name_of_error = name.first;
                    return root;
            }
        }
    return root;
}

size_t
ValueObject::GetIndexOfChildWithName (const ConstString &name)
{
    bool omit_empty_base_classes = true;
    return GetClangType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes);
}

ValueObjectSP
ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create)
{
    // when getting a child by name, it could be buried inside some base
    // classes (which really aren't part of the expression path), so we
    // need a vector of indexes that can get us down to the correct child
    ValueObjectSP child_sp;

    // We may need to update our value if we are dynamic
    if (IsPossibleDynamicType ())
        UpdateValueIfNeeded(false);

    std::vector<uint32_t> child_indexes;
    bool omit_empty_base_classes = true;
    const size_t num_child_indexes =  GetClangType().GetIndexOfChildMemberWithName (name.GetCString(),
                                                                                    omit_empty_base_classes,
                                                                                    child_indexes);
    if (num_child_indexes > 0)
    {
        std::vector<uint32_t>::const_iterator pos = child_indexes.begin ();
        std::vector<uint32_t>::const_iterator end = child_indexes.end ();

        child_sp = GetChildAtIndex(*pos, can_create);
        for (++pos; pos != end; ++pos)
        {
            if (child_sp)
            {
                ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create));
                child_sp = new_child_sp;
            }
            else
            {
                child_sp.reset();
            }

        }
    }
    return child_sp;
}


size_t
ValueObject::GetNumChildren ()
{
    UpdateValueIfNeeded();
    if (!m_children_count_valid)
    {
        SetNumChildren (CalculateNumChildren());
    }
    return m_children.GetChildrenCount();
}

bool
ValueObject::MightHaveChildren()
{
    bool has_children = false;
    const uint32_t type_info = GetTypeInfo();
    if (type_info)
    {
        if (type_info & (ClangASTType::eTypeHasChildren |
                         ClangASTType::eTypeIsPointer |
                         ClangASTType::eTypeIsReference))
            has_children = true;
    }
    else
    {
        has_children = GetNumChildren () > 0;
    }
    return has_children;
}

// Should only be called by ValueObject::GetNumChildren()
void
ValueObject::SetNumChildren (size_t num_children)
{
    m_children_count_valid = true;
    m_children.SetChildrenCount(num_children);
}

void
ValueObject::SetName (const ConstString &name)
{
    m_name = name;
}

ValueObject *
ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index)
{
    ValueObject *valobj = NULL;
    
    bool omit_empty_base_classes = true;
    bool ignore_array_bounds = synthetic_array_member;
    std::string child_name_str;
    uint32_t child_byte_size = 0;
    int32_t child_byte_offset = 0;
    uint32_t child_bitfield_bit_size = 0;
    uint32_t child_bitfield_bit_offset = 0;
    bool child_is_base_class = false;
    bool child_is_deref_of_parent = false;

    const bool transparent_pointers = synthetic_array_member == false;
    ClangASTType child_clang_type;
    
    ExecutionContext exe_ctx (GetExecutionContextRef());
    
    child_clang_type = GetClangType().GetChildClangTypeAtIndex (&exe_ctx,
                                                                GetName().GetCString(),
                                                                idx,
                                                                transparent_pointers,
                                                                omit_empty_base_classes,
                                                                ignore_array_bounds,
                                                                child_name_str,
                                                                child_byte_size,
                                                                child_byte_offset,
                                                                child_bitfield_bit_size,
                                                                child_bitfield_bit_offset,
                                                                child_is_base_class,
                                                                child_is_deref_of_parent);
    if (child_clang_type)
    {
        if (synthetic_index)
            child_byte_offset += child_byte_size * synthetic_index;

        ConstString child_name;
        if (!child_name_str.empty())
            child_name.SetCString (child_name_str.c_str());

        valobj = new ValueObjectChild (*this,
                                       child_clang_type,
                                       child_name,
                                       child_byte_size,
                                       child_byte_offset,
                                       child_bitfield_bit_size,
                                       child_bitfield_bit_offset,
                                       child_is_base_class,
                                       child_is_deref_of_parent,
                                       eAddressTypeInvalid);
        //if (valobj)
        //    valobj->SetAddressTypeOfChildren(eAddressTypeInvalid);
   }
    
    return valobj;
}

bool
ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
                                  std::string& destination)
{
    destination.clear();

    // ideally we would like to bail out if passing NULL, but if we do so
    // we end up not providing the summary for function pointers anymore
    if (/*summary_ptr == NULL ||*/ m_is_getting_summary)
        return false;
    
    m_is_getting_summary = true;
    
    // this is a hot path in code and we prefer to avoid setting this string all too often also clearing out other
    // information that we might care to see in a crash log. might be useful in very specific situations though.
    /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. Summary provider's description is %s",
                                        GetTypeName().GetCString(),
                                        GetName().GetCString(),
                                        summary_ptr->GetDescription().c_str());*/
    
    if (UpdateValueIfNeeded (false))
    {
        if (summary_ptr)
        {
            if (HasSyntheticValue())
                m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#})
            summary_ptr->FormatObject(this, destination);
        }
        else
        {
            ClangASTType clang_type = GetClangType();
            
            // Do some default printout for function pointers
            if (clang_type)
            {
                if (clang_type.IsFunctionPointerType ())
                {
                    StreamString sstr;
                    AddressType func_ptr_address_type = eAddressTypeInvalid;
                    addr_t func_ptr_address = GetPointerValue (&func_ptr_address_type);
                    if (func_ptr_address != 0 && func_ptr_address != LLDB_INVALID_ADDRESS)
                    {
                        switch (func_ptr_address_type)
                        {
                            case eAddressTypeInvalid:
                            case eAddressTypeFile:
                                break;
                                
                            case eAddressTypeLoad:
                            {
                                ExecutionContext exe_ctx (GetExecutionContextRef());
                                
                                Address so_addr;
                                Target *target = exe_ctx.GetTargetPtr();
                                if (target && target->GetSectionLoadList().IsEmpty() == false)
                                {
                                    if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address, so_addr))
                                    {
                                        so_addr.Dump (&sstr, 
                                                      exe_ctx.GetBestExecutionContextScope(), 
                                                      Address::DumpStyleResolvedDescription, 
                                                      Address::DumpStyleSectionNameOffset);
                                    }
                                }
                            }
                                break;
                                
                            case eAddressTypeHost:
                                break;
                        }
                    }
                    if (sstr.GetSize() > 0)
                    {
                        destination.assign (1, '(');
                        destination.append (sstr.GetData(), sstr.GetSize());
                        destination.append (1, ')');
                    }
                }
            }
        }
    }
    m_is_getting_summary = false;
    return !destination.empty();
}

const char *
ValueObject::GetSummaryAsCString ()
{
    if (UpdateValueIfNeeded(true) && m_summary_str.empty())
    {
        GetSummaryAsCString(GetSummaryFormat().get(),
                            m_summary_str);
    }
    if (m_summary_str.empty())
        return NULL;
    return m_summary_str.c_str();
}

bool
ValueObject::IsCStringContainer(bool check_pointer)
{
    ClangASTType pointee_or_element_clang_type;
    const Flags type_flags (GetTypeInfo (&pointee_or_element_clang_type));
    bool is_char_arr_ptr (type_flags.AnySet (ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) &&
                          pointee_or_element_clang_type.IsCharType ());
    if (!is_char_arr_ptr)
        return false;
    if (!check_pointer)
        return true;
    if (type_flags.Test(ClangASTType::eTypeIsArray))
        return true;
    addr_t cstr_address = LLDB_INVALID_ADDRESS;
    AddressType cstr_address_type = eAddressTypeInvalid;
    cstr_address = GetAddressOf (true, &cstr_address_type);
    return (cstr_address != LLDB_INVALID_ADDRESS);
}

size_t
ValueObject::GetPointeeData (DataExtractor& data,
                             uint32_t item_idx,
                             uint32_t item_count)
{
    ClangASTType pointee_or_element_clang_type;
    const uint32_t type_info = GetTypeInfo (&pointee_or_element_clang_type);
    const bool is_pointer_type = type_info & ClangASTType::eTypeIsPointer;
    const bool is_array_type = type_info & ClangASTType::eTypeIsArray;
    if (!(is_pointer_type || is_array_type))
        return 0;
    
    if (item_count == 0)
        return 0;
    
    const uint64_t item_type_size = pointee_or_element_clang_type.GetByteSize();
    const uint64_t bytes = item_count * item_type_size;
    const uint64_t offset = item_idx * item_type_size;
    
    if (item_idx == 0 && item_count == 1) // simply a deref
    {
        if (is_pointer_type)
        {
            Error error;
            ValueObjectSP pointee_sp = Dereference(error);
            if (error.Fail() || pointee_sp.get() == NULL)
                return 0;
            return pointee_sp->GetData(data, error);
        }
        else
        {
            ValueObjectSP child_sp = GetChildAtIndex(0, true);
            if (child_sp.get() == NULL)
                return 0;
            Error error;
            return child_sp->GetData(data, error);
        }
        return true;
    }
    else /* (items > 1) */
    {
        Error error;
        lldb_private::DataBufferHeap* heap_buf_ptr = NULL;
        lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap());
        
        AddressType addr_type;
        lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type);
        
        switch (addr_type)
        {
            case eAddressTypeFile:
                {
                    ModuleSP module_sp (GetModule());
                    if (module_sp)
                    {
                        addr = addr + offset;
                        Address so_addr;
                        module_sp->ResolveFileAddress(addr, so_addr);
                        ExecutionContext exe_ctx (GetExecutionContextRef());
                        Target* target = exe_ctx.GetTargetPtr();
                        if (target)
                        {
                            heap_buf_ptr->SetByteSize(bytes);
                            size_t bytes_read = target->ReadMemory(so_addr, false, heap_buf_ptr->GetBytes(), bytes, error);
                            if (error.Success())
                            {
                                data.SetData(data_sp);
                                return bytes_read;
                            }
                        }
                    }
                }
                break;
            case eAddressTypeLoad:
                {
                    ExecutionContext exe_ctx (GetExecutionContextRef());
                    Process *process = exe_ctx.GetProcessPtr();
                    if (process)
                    {
                        heap_buf_ptr->SetByteSize(bytes);
                        size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error);
                        if (error.Success() || bytes_read > 0)
                        {
                            data.SetData(data_sp);
                            return bytes_read;
                        }
                    }
                }
                break;
            case eAddressTypeHost:
                {
                    const uint64_t max_bytes = GetClangType().GetByteSize();
                    if (max_bytes > offset)
                    {
                        size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
                        heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes_read);
                        data.SetData(data_sp);
                        return bytes_read;
                    }
                }
                break;
            case eAddressTypeInvalid:
                break;
        }
    }
    return 0;
}

uint64_t
ValueObject::GetData (DataExtractor& data, Error &error)
{
    UpdateValueIfNeeded(false);
    ExecutionContext exe_ctx (GetExecutionContextRef());
    error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get());
    if (error.Fail())
    {
        if (m_data.GetByteSize())
        {
            data = m_data;
            return data.GetByteSize();
        }
        else
        {
            return 0;
        }
    }
    data.SetAddressByteSize(m_data.GetAddressByteSize());
    data.SetByteOrder(m_data.GetByteOrder());
    return data.GetByteSize();
}

bool
ValueObject::SetData (DataExtractor &data, Error &error)
{
    error.Clear();
    // Make sure our value is up to date first so that our location and location
    // type is valid.
    if (!UpdateValueIfNeeded(false))
    {
        error.SetErrorString("unable to read value");
        return false;
    }
    
    uint64_t count = 0;
    const Encoding encoding = GetClangType().GetEncoding(count);
    
    const size_t byte_size = GetByteSize();
    
    Value::ValueType value_type = m_value.GetValueType();
    
    switch (value_type)
    {
    case Value::eValueTypeScalar:
        {
            Error set_error = m_value.GetScalar().SetValueFromData(data, encoding, byte_size);
            
            if (!set_error.Success())
            {
                error.SetErrorStringWithFormat("unable to set scalar value: %s", set_error.AsCString());
                return false;
            }
        }
        break;
    case Value::eValueTypeLoadAddress:
        {
            // If it is a load address, then the scalar value is the storage location
            // of the data, and we have to shove this value down to that load location.
            ExecutionContext exe_ctx (GetExecutionContextRef());
            Process *process = exe_ctx.GetProcessPtr();
            if (process)
            {
                addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                size_t bytes_written = process->WriteMemory(target_addr,
                                                            data.GetDataStart(),
                                                            byte_size,
                                                            error);
                if (!error.Success())
                    return false;
                if (bytes_written != byte_size)
                {
                    error.SetErrorString("unable to write value to memory");
                    return false;
                }
            }
        }
        break;
    case Value::eValueTypeHostAddress:
        {
            // If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data.            
            DataBufferSP buffer_sp (new DataBufferHeap(byte_size, 0));
            m_data.SetData(buffer_sp, 0);
            data.CopyByteOrderedData (0,
                                      byte_size,
                                      const_cast<uint8_t *>(m_data.GetDataStart()),
                                      byte_size,
                                      m_data.GetByteOrder());
            m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
        }
        break;
    case Value::eValueTypeFileAddress:
    case Value::eValueTypeVector:
        break;
    }
    
    // If we have reached this point, then we have successfully changed the value.
    SetNeedsUpdate();
    return true;
}

// will compute strlen(str), but without consuming more than
// maxlen bytes out of str (this serves the purpose of reading
// chunks of a string without having to worry about
// missing NULL terminators in the chunk)
// of course, if strlen(str) > maxlen, the function will return
// maxlen_value (which should be != maxlen, because that allows you
// to know whether strlen(str) == maxlen or strlen(str) > maxlen)
static uint32_t
strlen_or_inf (const char* str,
               uint32_t maxlen,
               uint32_t maxlen_value)
{
    uint32_t len = 0;
    if (str)
    {
        while(*str)
        {
            len++;str++;
            if (len >= maxlen)
                return maxlen_value;
        }
    }
    return len;
}

size_t
ValueObject::ReadPointedString (Stream& s,
                                Error& error,
                                uint32_t max_length,
                                bool honor_array,
                                Format item_format)
{
    ExecutionContext exe_ctx (GetExecutionContextRef());
    Target* target = exe_ctx.GetTargetPtr();

    if (!target)
    {
        s << "<no target to read from>";
        error.SetErrorString("no target to read from");
        return 0;
    }
    
    if (max_length == 0)
        max_length = target->GetMaximumSizeOfStringSummary();
    
    size_t bytes_read = 0;
    size_t total_bytes_read = 0;
    
    ClangASTType clang_type = GetClangType();
    ClangASTType elem_or_pointee_clang_type;
    const Flags type_flags (GetTypeInfo (&elem_or_pointee_clang_type));
    if (type_flags.AnySet (ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer) &&
        elem_or_pointee_clang_type.IsCharType ())
    {
        addr_t cstr_address = LLDB_INVALID_ADDRESS;
        AddressType cstr_address_type = eAddressTypeInvalid;
        
        size_t cstr_len = 0;
        bool capped_data = false;
        if (type_flags.Test (ClangASTType::eTypeIsArray))
        {
            // We have an array
            uint64_t array_size = 0;
            if (clang_type.IsArrayType(NULL, &array_size, NULL))
            {
                cstr_len = array_size;
                if (cstr_len > max_length)
                {
                    capped_data = true;
                    cstr_len = max_length;
                }
            }
            cstr_address = GetAddressOf (true, &cstr_address_type);
        }
        else
        {
            // We have a pointer
            cstr_address = GetPointerValue (&cstr_address_type);
        }
        
        if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS)
        {
            s << "<invalid address>";
            error.SetErrorString("invalid address");
            return 0;
        }

        Address cstr_so_addr (cstr_address);
        DataExtractor data;
        if (cstr_len > 0 && honor_array)
        {
            // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host
            // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this
            GetPointeeData(data, 0, cstr_len);

            if ((bytes_read = data.GetByteSize()) > 0)
            {
                total_bytes_read = bytes_read;
                s << '"';
                data.Dump (&s,
                           0,                 // Start offset in "data"
                           item_format,
                           1,                 // Size of item (1 byte for a char!)
                           bytes_read,        // How many bytes to print?
                           UINT32_MAX,        // num per line
                           LLDB_INVALID_ADDRESS,// base address
                           0,                 // bitfield bit size
                           0);                // bitfield bit offset
                if (capped_data)
                    s << "...";
                s << '"';
            }
        }
        else
        {
            cstr_len = max_length;
            const size_t k_max_buf_size = 64;
                                        
            size_t offset = 0;
            
            int cstr_len_displayed = -1;
            bool capped_cstr = false;
            // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host
            // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this
            while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0)
            {
                total_bytes_read += bytes_read;
                const char *cstr = data.PeekCStr(0);
                size_t len = strlen_or_inf (cstr, k_max_buf_size, k_max_buf_size+1);
                if (len > k_max_buf_size)
                    len = k_max_buf_size;
                if (cstr && cstr_len_displayed < 0)
                    s << '"';

                if (cstr_len_displayed < 0)
                    cstr_len_displayed = len;

                if (len == 0)
                    break;
                cstr_len_displayed += len;
                if (len > bytes_read)
                    len = bytes_read;
                if (len > cstr_len)
                    len = cstr_len;
                
                data.Dump (&s,
                           0,                 // Start offset in "data"
                           item_format,
                           1,                 // Size of item (1 byte for a char!)
                           len,               // How many bytes to print?
                           UINT32_MAX,        // num per line
                           LLDB_INVALID_ADDRESS,// base address
                           0,                 // bitfield bit size
                           0);                // bitfield bit offset
                
                if (len < k_max_buf_size)
                    break;
                
                if (len >= cstr_len)
                {
                    capped_cstr = true;
                    break;
                }

                cstr_len -= len;
                offset += len;
            }
            
            if (cstr_len_displayed >= 0)
            {
                s << '"';
                if (capped_cstr)
                    s << "...";
            }
        }
    }
    else
    {
        error.SetErrorString("not a string object");
        s << "<not a string object>";
    }
    return total_bytes_read;
}

const char *
ValueObject::GetObjectDescription ()
{
    
    if (!UpdateValueIfNeeded (true))
        return NULL;

    if (!m_object_desc_str.empty())
        return m_object_desc_str.c_str();

    ExecutionContext exe_ctx (GetExecutionContextRef());
    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
        return NULL;
        
    StreamString s;
    
    LanguageType language = GetObjectRuntimeLanguage();
    LanguageRuntime *runtime = process->GetLanguageRuntime(language);
    
    if (runtime == NULL)
    {
        // Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway...
        ClangASTType clang_type = GetClangType();
        if (clang_type)
        {
            bool is_signed;
            if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType ())
            {
                runtime = process->GetLanguageRuntime(eLanguageTypeObjC);
            }
        }
    }
    
    if (runtime && runtime->GetObjectDescription(s, *this))
    {
        m_object_desc_str.append (s.GetData());
    }
    
    if (m_object_desc_str.empty())
        return NULL;
    else
        return m_object_desc_str.c_str();
}

bool
ValueObject::GetValueAsCString (const lldb_private::TypeFormatImpl& format,
                                std::string& destination)
{
    if (UpdateValueIfNeeded(false))
        return format.FormatObject(this,destination);
    else
        return false;
}

bool
ValueObject::GetValueAsCString (lldb::Format format,
                                std::string& destination)
{
    return GetValueAsCString(TypeFormatImpl_Format(format),destination);
}

const char *
ValueObject::GetValueAsCString ()
{
    if (UpdateValueIfNeeded(true))
    {
        lldb::TypeFormatImplSP format_sp;
        lldb::Format my_format = GetFormat();
        if (my_format == lldb::eFormatDefault)
        {
            if (m_type_format_sp)
                format_sp = m_type_format_sp;
            else
            {
                if (m_is_bitfield_for_scalar)
                    my_format = eFormatUnsigned;
                else
                {
                    if (m_value.GetContextType() == Value::eContextTypeRegisterInfo)
                    {
                        const RegisterInfo *reg_info = m_value.GetRegisterInfo();
                        if (reg_info)
                            my_format = reg_info->format;
                    }
                    else
                    {
                        my_format = GetClangType().GetFormat();
                    }
                }
            }
        }
        if (my_format != m_last_format || m_value_str.empty())
        {
            m_last_format = my_format;
            if (!format_sp)
                format_sp.reset(new TypeFormatImpl_Format(my_format));
            if (GetValueAsCString(*format_sp.get(), m_value_str))
            {
                if (!m_value_did_change && m_old_value_valid)
                {
                    // The value was gotten successfully, so we consider the
                    // value as changed if the value string differs
                    SetValueDidChange (m_old_value_str != m_value_str);
                }
            }
        }
    }
    if (m_value_str.empty())
        return NULL;
    return m_value_str.c_str();
}

// if > 8bytes, 0 is returned. this method should mostly be used
// to read address values out of pointers
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())
    {
        Scalar scalar;
        if (ResolveValue (scalar))
        {
            if (success)
                *success = true;
            return scalar.ULongLong(fail_value);
        }
        // fallthrough, otherwise...
    }

    if (success)
        *success = false;
    return fail_value;
}

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())
    {
        Scalar scalar;
        if (ResolveValue (scalar))
        {
            if (success)
                *success = true;
                return scalar.SLongLong(fail_value);
        }
        // fallthrough, otherwise...
    }
    
    if (success)
        *success = false;
        return fail_value;
}

// if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep
// this call up to date by returning true for your new special cases. We will eventually move
// to checking this call result before trying to display special cases
bool
ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display,
                                               Format custom_format)
{
    Flags flags(GetTypeInfo());
    if (flags.AnySet(ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer)
        && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)
    {        
        if (IsCStringContainer(true) && 
            (custom_format == eFormatCString ||
             custom_format == eFormatCharArray ||
             custom_format == eFormatChar ||
             custom_format == eFormatVectorOfChar))
            return true;

        if (flags.Test(ClangASTType::eTypeIsArray))
        {
            if ((custom_format == eFormatBytes) ||
                (custom_format == eFormatBytesWithASCII))
                return true;
            
            if ((custom_format == eFormatVectorOfChar) ||
                (custom_format == eFormatVectorOfFloat32) ||
                (custom_format == eFormatVectorOfFloat64) ||
                (custom_format == eFormatVectorOfSInt16) ||
                (custom_format == eFormatVectorOfSInt32) ||
                (custom_format == eFormatVectorOfSInt64) ||
                (custom_format == eFormatVectorOfSInt8) ||
                (custom_format == eFormatVectorOfUInt128) ||
                (custom_format == eFormatVectorOfUInt16) ||
                (custom_format == eFormatVectorOfUInt32) ||
                (custom_format == eFormatVectorOfUInt64) ||
                (custom_format == eFormatVectorOfUInt8))
                return true;
        }
    }
    return false;
}

bool
ValueObject::DumpPrintableRepresentation(Stream& s,
                                         ValueObjectRepresentationStyle val_obj_display,
                                         Format custom_format,
                                         PrintableRepresentationSpecialCases special,
                                         bool do_dump_error)
{

    Flags flags(GetTypeInfo());
    
    bool allow_special = ((special & ePrintableRepresentationSpecialCasesAllow) == ePrintableRepresentationSpecialCasesAllow);
    bool only_special = ((special & ePrintableRepresentationSpecialCasesOnly) == ePrintableRepresentationSpecialCasesOnly);
    
    if (allow_special)
    {
        if (flags.AnySet(ClangASTType::eTypeIsArray | ClangASTType::eTypeIsPointer)
             && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue)
        {
            // when being asked to get a printable display an array or pointer type directly, 
            // try to "do the right thing"
            
            if (IsCStringContainer(true) && 
                (custom_format == eFormatCString ||
                 custom_format == eFormatCharArray ||
                 custom_format == eFormatChar ||
                 custom_format == eFormatVectorOfChar)) // print char[] & char* directly
            {
                Error error;
                ReadPointedString(s,
                                  error,
                                  0,
                                  (custom_format == eFormatVectorOfChar) ||
                                  (custom_format == eFormatCharArray));
                return !error.Fail();
            }
            
            if (custom_format == eFormatEnum)
                return false;
            
            // this only works for arrays, because I have no way to know when
            // the pointed memory ends, and no special \0 end of data marker
            if (flags.Test(ClangASTType::eTypeIsArray))
            {
                if ((custom_format == eFormatBytes) ||
                    (custom_format == eFormatBytesWithASCII))
                {
                    const size_t count = GetNumChildren();
                                    
                    s << '[';
                    for (size_t low = 0; low < count; low++)
                    {
                        
                        if (low)
                            s << ',';
                        
                        ValueObjectSP child = GetChildAtIndex(low,true);
                        if (!child.get())
                        {
                            s << "<invalid child>";
                            continue;
                        }
                        child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, custom_format);
                    }                
                    
                    s << ']';
                    
                    return true;
                }
                
                if ((custom_format == eFormatVectorOfChar) ||
                    (custom_format == eFormatVectorOfFloat32) ||
                    (custom_format == eFormatVectorOfFloat64) ||
                    (custom_format == eFormatVectorOfSInt16) ||
                    (custom_format == eFormatVectorOfSInt32) ||
                    (custom_format == eFormatVectorOfSInt64) ||
                    (custom_format == eFormatVectorOfSInt8) ||
                    (custom_format == eFormatVectorOfUInt128) ||
                    (custom_format == eFormatVectorOfUInt16) ||
                    (custom_format == eFormatVectorOfUInt32) ||
                    (custom_format == eFormatVectorOfUInt64) ||
                    (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly
                {
                    const size_t count = GetNumChildren();

                    Format format = FormatManager::GetSingleItemFormat(custom_format);
                    
                    s << '[';
                    for (size_t low = 0; low < count; low++)
                    {
                        
                        if (low)
                            s << ',';
                        
                        ValueObjectSP child = GetChildAtIndex(low,true);
                        if (!child.get())
                        {
                            s << "<invalid child>";
                            continue;
                        }
                        child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, format);
                    }                
                    
                    s << ']';
                    
                    return true;
                }
            }
            
            if ((custom_format == eFormatBoolean) ||
                (custom_format == eFormatBinary) ||
                (custom_format == eFormatChar) ||
                (custom_format == eFormatCharPrintable) ||
                (custom_format == eFormatComplexFloat) ||
                (custom_format == eFormatDecimal) ||
                (custom_format == eFormatHex) ||
                (custom_format == eFormatHexUppercase) ||
                (custom_format == eFormatFloat) ||
                (custom_format == eFormatOctal) ||
                (custom_format == eFormatOSType) ||
                (custom_format == eFormatUnicode16) ||
                (custom_format == eFormatUnicode32) ||
                (custom_format == eFormatUnsigned) ||
                (custom_format == eFormatPointer) ||
                (custom_format == eFormatComplexInteger) ||
                (custom_format == eFormatComplex) ||
                (custom_format == eFormatDefault)) // use the [] operator
                return false;
        }
    }
    
    if (only_special)
        return false;
    
    bool var_success = false;
    
    {
        const char *cstr = NULL;
        
         // this is a local stream that we are using to ensure that the data pointed to by cstr survives
        // long enough for us to copy it to its destination - it is necessary to have this temporary storage
        // area for cases where our desired output is not backed by some other longer-term storage
        StreamString strm;

        if (custom_format != eFormatInvalid)
            SetFormat(custom_format);
        
        switch(val_obj_display)
        {
            case eValueObjectRepresentationStyleValue:
                cstr = GetValueAsCString();
                break;
                
            case eValueObjectRepresentationStyleSummary:
                cstr = GetSummaryAsCString();
                break;
                
            case eValueObjectRepresentationStyleLanguageSpecific:
                cstr = GetObjectDescription();
                break;
                
            case eValueObjectRepresentationStyleLocation:
                cstr = GetLocationAsCString();
                break;
                
            case eValueObjectRepresentationStyleChildrenCount:
                strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren());
                cstr = strm.GetString().c_str();
                break;
                
            case eValueObjectRepresentationStyleType:
                cstr = GetTypeName().AsCString();
                break;
                
            case eValueObjectRepresentationStyleName:
                cstr = GetName().AsCString();
                break;
                
            case eValueObjectRepresentationStyleExpressionPath:
                GetExpressionPath(strm, false);
                cstr = strm.GetString().c_str();
                break;
        }
        
        if (!cstr)
        {
            if (val_obj_display == eValueObjectRepresentationStyleValue)
                cstr = GetSummaryAsCString();
            else if (val_obj_display == eValueObjectRepresentationStyleSummary)
            {
                if (GetClangType().IsAggregateType())
                {
                    strm.Printf("%s @ %s", GetTypeName().AsCString(), GetLocationAsCString());
                    cstr = strm.GetString().c_str();
                }
                else
                    cstr = GetValueAsCString();
            }
        }
        
        if (cstr)
            s.PutCString(cstr);
        else
        {
            if (m_error.Fail())
            {
                if (do_dump_error)
                    s.Printf("<%s>", m_error.AsCString());
                else
                    return false;
            }
            else if (val_obj_display == eValueObjectRepresentationStyleSummary)
                s.PutCString("<no summary available>");
            else if (val_obj_display == eValueObjectRepresentationStyleValue)
                s.PutCString("<no value available>");
            else if (val_obj_display == eValueObjectRepresentationStyleLanguageSpecific)
                s.PutCString("<not a valid Objective-C object>"); // edit this if we have other runtimes that support a description
            else
                s.PutCString("<no printable representation>");
        }
        
        // we should only return false here if we could not do *anything*
        // even if we have an error message as output, that's a success
        // from our callers' perspective, so return true
        var_success = true;
        
        if (custom_format != eFormatInvalid)
            SetFormat(eFormatDefault);
    }
    
    return var_success;
}

addr_t
ValueObject::GetAddressOf (bool scalar_is_load_address, AddressType *address_type)
{
    if (!UpdateValueIfNeeded(false))
        return LLDB_INVALID_ADDRESS;
        
    switch (m_value.GetValueType())
    {
    case Value::eValueTypeScalar:
    case Value::eValueTypeVector:
        if (scalar_is_load_address)
        {
            if(address_type)
                *address_type = eAddressTypeLoad;
            return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        }
        break;

    case Value::eValueTypeLoadAddress: 
    case Value::eValueTypeFileAddress:
    case Value::eValueTypeHostAddress:
        {
            if(address_type)
                *address_type = m_value.GetValueAddressType ();
            return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        }
        break;
    }
    if (address_type)
        *address_type = eAddressTypeInvalid;
    return LLDB_INVALID_ADDRESS;
}

addr_t
ValueObject::GetPointerValue (AddressType *address_type)
{
    addr_t address = LLDB_INVALID_ADDRESS;
    if(address_type)
        *address_type = eAddressTypeInvalid;
    
    if (!UpdateValueIfNeeded(false))
        return address;
        
    switch (m_value.GetValueType())
    {
    case Value::eValueTypeScalar:
    case Value::eValueTypeVector:
        address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        break;

    case Value::eValueTypeHostAddress:
    case Value::eValueTypeLoadAddress:
    case Value::eValueTypeFileAddress:
        {
            lldb::offset_t data_offset = 0;
            address = m_data.GetPointer(&data_offset);
        }
        break;
    }

    if (address_type)
        *address_type = GetAddressTypeOfChildren();

    return address;
}

bool
ValueObject::SetValueFromCString (const char *value_str, Error& error)
{
    error.Clear();
    // Make sure our value is up to date first so that our location and location
    // type is valid.
    if (!UpdateValueIfNeeded(false))
    {
        error.SetErrorString("unable to read value");
        return false;
    }

    uint64_t count = 0;
    const Encoding encoding = GetClangType().GetEncoding (count);

    const size_t byte_size = GetByteSize();

    Value::ValueType value_type = m_value.GetValueType();
    
    if (value_type == Value::eValueTypeScalar)
    {
        // If the value is already a scalar, then let the scalar change itself:
        m_value.GetScalar().SetValueFromCString (value_str, encoding, byte_size);
    }
    else if (byte_size <= Scalar::GetMaxByteSize())
    {
        // If the value fits in a scalar, then make a new scalar and again let the
        // scalar code do the conversion, then figure out where to put the new value.
        Scalar new_scalar;
        error = new_scalar.SetValueFromCString (value_str, encoding, byte_size);
        if (error.Success())
        {
            switch (value_type)
            {
            case Value::eValueTypeLoadAddress:
                {
                    // If it is a load address, then the scalar value is the storage location
                    // of the data, and we have to shove this value down to that load location.
                    ExecutionContext exe_ctx (GetExecutionContextRef());
                    Process *process = exe_ctx.GetProcessPtr();
                    if (process)
                    {
                        addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                        size_t bytes_written = process->WriteScalarToMemory (target_addr, 
                                                                             new_scalar, 
                                                                             byte_size, 
                                                                             error);
                        if (!error.Success())
                            return false;
                        if (bytes_written != byte_size)
                        {
                            error.SetErrorString("unable to write value to memory");
                            return false;
                        }
                    }
                }
                break;
            case Value::eValueTypeHostAddress:
                {
                    // If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data.
                    DataExtractor new_data;
                    new_data.SetByteOrder (m_data.GetByteOrder());
                    
                    DataBufferSP buffer_sp (new DataBufferHeap(byte_size, 0));
                    m_data.SetData(buffer_sp, 0);
                    bool success = new_scalar.GetData(new_data);
                    if (success)
                    {
                        new_data.CopyByteOrderedData (0, 
                                                      byte_size, 
                                                      const_cast<uint8_t *>(m_data.GetDataStart()), 
                                                      byte_size, 
                                                      m_data.GetByteOrder());
                    }
                    m_value.GetScalar() = (uintptr_t)m_data.GetDataStart();
                    
                }
                break;
            case Value::eValueTypeFileAddress:
            case Value::eValueTypeScalar:
            case Value::eValueTypeVector:
                break;
            }
        }
        else
        {
            return false;
        }
    }
    else
    {
        // We don't support setting things bigger than a scalar at present.
        error.SetErrorString("unable to write aggregate data type");
        return false;
    }
    
    // If we have reached this point, then we have successfully changed the value.
    SetNeedsUpdate();
    return true;
}

bool
ValueObject::GetDeclaration (Declaration &decl)
{
    decl.Clear();
    return false;
}

ConstString
ValueObject::GetTypeName()
{
    return GetClangType().GetConstTypeName();
}

ConstString
ValueObject::GetDisplayTypeName()
{
    return GetTypeName();
}

ConstString
ValueObject::GetQualifiedTypeName()
{
    return GetClangType().GetConstQualifiedTypeName();
}


LanguageType
ValueObject::GetObjectRuntimeLanguage ()
{
    return GetClangType().GetMinimumLanguage ();
}

void
ValueObject::AddSyntheticChild (const ConstString &key, ValueObject *valobj)
{
    m_synthetic_children[key] = valobj;
}

ValueObjectSP
ValueObject::GetSyntheticChild (const ConstString &key) const
{
    ValueObjectSP synthetic_child_sp;
    std::map<ConstString, ValueObject *>::const_iterator pos = m_synthetic_children.find (key);
    if (pos != m_synthetic_children.end())
        synthetic_child_sp = pos->second->GetSP();
    return synthetic_child_sp;
}

uint32_t
ValueObject::GetTypeInfo (ClangASTType *pointee_or_element_clang_type)
{
    return GetClangType().GetTypeInfo (pointee_or_element_clang_type);
}

bool
ValueObject::IsPointerType ()
{
    return GetClangType().IsPointerType();
}

bool
ValueObject::IsArrayType ()
{
    return GetClangType().IsArrayType (NULL, NULL, NULL);
}

bool
ValueObject::IsScalarType ()
{
    return GetClangType().IsScalarType ();
}

bool
ValueObject::IsIntegerType (bool &is_signed)
{
    return GetClangType().IsIntegerType (is_signed);
}

bool
ValueObject::IsPointerOrReferenceType ()
{
    return GetClangType().IsPointerOrReferenceType ();
}

bool
ValueObject::IsPossibleDynamicType ()
{
    ExecutionContext exe_ctx (GetExecutionContextRef());
    Process *process = exe_ctx.GetProcessPtr();
    if (process)
        return process->IsPossibleDynamicValue(*this);
    else
        return GetClangType().IsPossibleDynamicType (NULL, true, true);
}

bool
ValueObject::IsObjCNil ()
{
    const uint32_t mask = ClangASTType::eTypeIsObjC | ClangASTType::eTypeIsPointer;
    bool isObjCpointer = (((GetClangType().GetTypeInfo(NULL)) & mask) == mask);
    if (!isObjCpointer)
        return false;
    bool canReadValue = true;
    bool isZero = GetValueAsUnsigned(0,&canReadValue) == 0;
    return canReadValue && isZero;
}

ValueObjectSP
ValueObject::GetSyntheticArrayMember (size_t index, bool can_create)
{
    const uint32_t type_info = GetTypeInfo ();
    if (type_info & ClangASTType::eTypeIsArray)
        return GetSyntheticArrayMemberFromArray(index, can_create);

    if (type_info & ClangASTType::eTypeIsPointer)
        return GetSyntheticArrayMemberFromPointer(index, can_create);
    
    return ValueObjectSP();
    
}

ValueObjectSP
ValueObject::GetSyntheticArrayMemberFromPointer (size_t index, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    if (IsPointerType ())
    {
        char index_str[64];
        snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
        ConstString index_const_str(index_str);
        // Check if we have already created a synthetic array member in this
        // valid object. If we have we will re-use it.
        synthetic_child_sp = GetSyntheticChild (index_const_str);
        if (!synthetic_child_sp)
        {
            ValueObject *synthetic_child;
            // We haven't made a synthetic array member for INDEX yet, so
            // lets make one and cache it for any future reference.
            synthetic_child = CreateChildAtIndex(0, true, index);

            // Cache the value if we got one back...
            if (synthetic_child)
            {
                AddSyntheticChild(index_const_str, synthetic_child);
                synthetic_child_sp = synthetic_child->GetSP();
                synthetic_child_sp->SetName(ConstString(index_str));
                synthetic_child_sp->m_is_array_item_for_pointer = true;
            }
        }
    }
    return synthetic_child_sp;
}

// This allows you to create an array member using and index
// that doesn't not fall in the normal bounds of the array.
// Many times structure can be defined as:
// struct Collection
// {
//     uint32_t item_count;
//     Item item_array[0];
// };
// The size of the "item_array" is 1, but many times in practice
// there are more items in "item_array".

ValueObjectSP
ValueObject::GetSyntheticArrayMemberFromArray (size_t index, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    if (IsArrayType ())
    {
        char index_str[64];
        snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index);
        ConstString index_const_str(index_str);
        // Check if we have already created a synthetic array member in this
        // valid object. If we have we will re-use it.
        synthetic_child_sp = GetSyntheticChild (index_const_str);
        if (!synthetic_child_sp)
        {
            ValueObject *synthetic_child;
            // We haven't made a synthetic array member for INDEX yet, so
            // lets make one and cache it for any future reference.
            synthetic_child = CreateChildAtIndex(0, true, index);
            
            // Cache the value if we got one back...
            if (synthetic_child)
            {
                AddSyntheticChild(index_const_str, synthetic_child);
                synthetic_child_sp = synthetic_child->GetSP();
                synthetic_child_sp->SetName(ConstString(index_str));
                synthetic_child_sp->m_is_array_item_for_pointer = true;
            }
        }
    }
    return synthetic_child_sp;
}

ValueObjectSP
ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    if (IsScalarType ())
    {
        char index_str[64];
        snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to);
        ConstString index_const_str(index_str);
        // Check if we have already created a synthetic array member in this
        // valid object. If we have we will re-use it.
        synthetic_child_sp = GetSyntheticChild (index_const_str);
        if (!synthetic_child_sp)
        {
            // We haven't made a synthetic array member for INDEX yet, so
            // lets make one and cache it for any future reference.
            ValueObjectChild *synthetic_child = new ValueObjectChild (*this,
                                                                      GetClangType(),
                                                                      index_const_str,
                                                                      GetByteSize(),
                                                                      0,
                                                                      to-from+1,
                                                                      from,
                                                                      false,
                                                                      false,
                                                                      eAddressTypeInvalid);
            
            // Cache the value if we got one back...
            if (synthetic_child)
            {
                AddSyntheticChild(index_const_str, synthetic_child);
                synthetic_child_sp = synthetic_child->GetSP();
                synthetic_child_sp->SetName(ConstString(index_str));
                synthetic_child_sp->m_is_bitfield_for_scalar = true;
            }
        }
    }
    return synthetic_child_sp;
}

ValueObjectSP
ValueObject::GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create)
{
    
    ValueObjectSP synthetic_child_sp;
    
    char name_str[64];
    snprintf(name_str, sizeof(name_str), "@%i", offset);
    ConstString name_const_str(name_str);
    
    // Check if we have already created a synthetic array member in this
    // valid object. If we have we will re-use it.
    synthetic_child_sp = GetSyntheticChild (name_const_str);
    
    if (synthetic_child_sp.get())
        return synthetic_child_sp;
    
    if (!can_create)
        return ValueObjectSP();
    
    ValueObjectChild *synthetic_child = new ValueObjectChild(*this,
                                                             type,
                                                             name_const_str,
                                                             type.GetByteSize(),
                                                             offset,
                                                             0,
                                                             0,
                                                             false,
                                                             false,
                                                             eAddressTypeInvalid);
    if (synthetic_child)
    {
        AddSyntheticChild(name_const_str, synthetic_child);
        synthetic_child_sp = synthetic_child->GetSP();
        synthetic_child_sp->SetName(name_const_str);
        synthetic_child_sp->m_is_child_at_offset = true;
    }
    return synthetic_child_sp;
}

// your expression path needs to have a leading . or ->
// (unless it somehow "looks like" an array, in which case it has
// a leading [ symbol). while the [ is meaningful and should be shown
// to the user, . and -> are just parser design, but by no means
// added information for the user.. strip them off
static const char*
SkipLeadingExpressionPathSeparators(const char* expression)
{
    if (!expression || !expression[0])
        return expression;
    if (expression[0] == '.')
        return expression+1;
    if (expression[0] == '-' && expression[1] == '>')
        return expression+2;
    return expression;
}

ValueObjectSP
ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    ConstString name_const_string(expression);
    // Check if we have already created a synthetic array member in this
    // valid object. If we have we will re-use it.
    synthetic_child_sp = GetSyntheticChild (name_const_string);
    if (!synthetic_child_sp)
    {
        // We haven't made a synthetic array member for expression yet, so
        // lets make one and cache it for any future reference.
        synthetic_child_sp = GetValueForExpressionPath(expression,
                                                       NULL, NULL, NULL,
                                                       GetValueForExpressionPathOptions().DontAllowSyntheticChildren());
        
        // Cache the value if we got one back...
        if (synthetic_child_sp.get())
        {
            // FIXME: this causes a "real" child to end up with its name changed to the contents of expression
            AddSyntheticChild(name_const_string, synthetic_child_sp.get());
            synthetic_child_sp->SetName(ConstString(SkipLeadingExpressionPathSeparators(expression)));
        }
    }
    return synthetic_child_sp;
}

void
ValueObject::CalculateSyntheticValue (bool use_synthetic)
{
    if (use_synthetic == false)
        return;
    
    TargetSP target_sp(GetTargetSP());
    if (target_sp && target_sp->GetEnableSyntheticValue() == false)
    {
        m_synthetic_value = NULL;
        return;
    }
    
    lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp);
    
    if (!UpdateFormatsIfNeeded() && 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);
}

void
ValueObject::CalculateDynamicValue (DynamicValueType use_dynamic)
{
    if (use_dynamic == eNoDynamicValues)
        return;
        
    if (!m_dynamic_value && !IsDynamic())
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        Process *process = exe_ctx.GetProcessPtr();
        if (process && process->IsPossibleDynamicValue(*this))
        {
            ClearDynamicTypeInformation ();
            m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic);
        }
    }
}

ValueObjectSP
ValueObject::GetDynamicValue (DynamicValueType use_dynamic)
{
    if (use_dynamic == eNoDynamicValues)
        return ValueObjectSP();
        
    if (!IsDynamic() && m_dynamic_value == NULL)
    {
        CalculateDynamicValue(use_dynamic);
    }
    if (m_dynamic_value)
        return m_dynamic_value->GetSP();
    else
        return ValueObjectSP();
}

ValueObjectSP
ValueObject::GetStaticValue()
{
    return GetSP();
}

lldb::ValueObjectSP
ValueObject::GetNonSyntheticValue ()
{
    return GetSP();
}

ValueObjectSP
ValueObject::GetSyntheticValue (bool use_synthetic)
{
    if (use_synthetic == false)
        return ValueObjectSP();

    CalculateSyntheticValue(use_synthetic);
    
    if (m_synthetic_value)
        return m_synthetic_value->GetSP();
    else
        return ValueObjectSP();
}

bool
ValueObject::HasSyntheticValue()
{
    UpdateFormatsIfNeeded();
    
    if (m_synthetic_children_sp.get() == NULL)
        return false;
    
    CalculateSyntheticValue(true);
    
    if (m_synthetic_value)
        return true;
    else
        return false;
}

bool
ValueObject::GetBaseClassPath (Stream &s)
{
    if (IsBaseClass())
    {
        bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s);
        ClangASTType clang_type = GetClangType();
        std::string cxx_class_name;
        bool this_had_base_class = clang_type.GetCXXClassName (cxx_class_name);
        if (this_had_base_class)
        {
            if (parent_had_base_class)
                s.PutCString("::");
            s.PutCString(cxx_class_name.c_str());
        }
        return parent_had_base_class || this_had_base_class;
    }
    return false;
}


ValueObject *
ValueObject::GetNonBaseClassParent()
{
    if (GetParent())
    {
        if (GetParent()->IsBaseClass())
            return GetParent()->GetNonBaseClassParent();
        else
            return GetParent();
    }
    return NULL;
}

void
ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
{
    const bool is_deref_of_parent = IsDereferenceOfParent ();

    if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers)
    {
        // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely
        // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName.
        // the eHonorPointers mode is meant to produce strings in this latter format
        s.PutCString("*(");
    }
    
    ValueObject* parent = GetParent();
    
    if (parent)
        parent->GetExpressionPath (s, qualify_cxx_base_classes, epformat);
    
    // if we are a deref_of_parent just because we are synthetic array
    // members made up to allow ptr[%d] syntax to work in variable
    // printing, then add our name ([%d]) to the expression path
    if (m_is_array_item_for_pointer && epformat == eGetExpressionPathFormatHonorPointers)
        s.PutCString(m_name.AsCString());
            
    if (!IsBaseClass())
    {
        if (!is_deref_of_parent)
        {
            ValueObject *non_base_class_parent = GetNonBaseClassParent();
            if (non_base_class_parent)
            {
                ClangASTType non_base_class_parent_clang_type = non_base_class_parent->GetClangType();
                if (non_base_class_parent_clang_type)
                {
                    if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers)
                    {
                        s.PutCString("->");
                    }
                    else
                    {                    
                        const uint32_t non_base_class_parent_type_info = non_base_class_parent_clang_type.GetTypeInfo();
                        
                        if (non_base_class_parent_type_info & ClangASTType::eTypeIsPointer)
                        {
                            s.PutCString("->");
                        }
                        else if ((non_base_class_parent_type_info & ClangASTType::eTypeHasChildren) &&
                                 !(non_base_class_parent_type_info & ClangASTType::eTypeIsArray))
                        {
                            s.PutChar('.');
                        }
                    }
                }
            }

            const char *name = GetName().GetCString();
            if (name)
            {
                if (qualify_cxx_base_classes)
                {
                    if (GetBaseClassPath (s))
                        s.PutCString("::");
                }
                s.PutCString(name);
            }
        }
    }
    
    if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers)
    {
        s.PutChar(')');
    }
}

ValueObjectSP
ValueObject::GetValueForExpressionPath(const char* expression,
                                       const char** first_unparsed,
                                       ExpressionPathScanEndReason* reason_to_stop,
                                       ExpressionPathEndResultType* final_value_type,
                                       const GetValueForExpressionPathOptions& options,
                                       ExpressionPathAftermath* final_task_on_target)
{
    
    const char* dummy_first_unparsed;
    ExpressionPathScanEndReason dummy_reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnknown;
    ExpressionPathEndResultType dummy_final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
    ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
    
    ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression,
                                                           first_unparsed ? first_unparsed : &dummy_first_unparsed,
                                                           reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
                                                           final_value_type ? final_value_type : &dummy_final_value_type,
                                                           options,
                                                           final_task_on_target ? final_task_on_target : &dummy_final_task_on_target);
    
    if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
        return ret_val;

    if (ret_val.get() && ((final_value_type ? *final_value_type : dummy_final_value_type) == eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress of plain objects
    {
        if ( (final_task_on_target ? *final_task_on_target : dummy_final_task_on_target) == ValueObject::eExpressionPathAftermathDereference)
        {
            Error error;
            ValueObjectSP final_value = ret_val->Dereference(error);
            if (error.Fail() || !final_value.get())
            {
                if (reason_to_stop)
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                if (final_value_type)
                    *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
                return ValueObjectSP();
            }
            else
            {
                if (final_task_on_target)
                    *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
                return final_value;
            }
        }
        if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress)
        {
            Error error;
            ValueObjectSP final_value = ret_val->AddressOf(error);
            if (error.Fail() || !final_value.get())
            {
                if (reason_to_stop)
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
                if (final_value_type)
                    *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
                return ValueObjectSP();
            }
            else
            {
                if (final_task_on_target)
                    *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
                return final_value;
            }
        }
    }
    return ret_val; // final_task_on_target will still have its original value, so you know I did not do it
}

int
ValueObject::GetValuesForExpressionPath(const char* expression,
                                        ValueObjectListSP& list,
                                        const char** first_unparsed,
                                        ExpressionPathScanEndReason* reason_to_stop,
                                        ExpressionPathEndResultType* final_value_type,
                                        const GetValueForExpressionPathOptions& options,
                                        ExpressionPathAftermath* final_task_on_target)
{
    const char* dummy_first_unparsed;
    ExpressionPathScanEndReason dummy_reason_to_stop;
    ExpressionPathEndResultType dummy_final_value_type;
    ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
    
    ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression,
                                                           first_unparsed ? first_unparsed : &dummy_first_unparsed,
                                                           reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
                                                           final_value_type ? final_value_type : &dummy_final_value_type,
                                                           options,
                                                           final_task_on_target ? final_task_on_target : &dummy_final_task_on_target);
    
    if (!ret_val.get()) // if there are errors, I add nothing to the list
        return 0;
    
    if ( (reason_to_stop ? *reason_to_stop : dummy_reason_to_stop) != eExpressionPathScanEndReasonArrayRangeOperatorMet)
    {
        // I need not expand a range, just post-process the final value and return
        if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing)
        {
            list->Append(ret_val);
            return 1;
        }
        if (ret_val.get() && (final_value_type ? *final_value_type : dummy_final_value_type) == eExpressionPathEndResultTypePlain) // I can only deref and takeaddress of plain objects
        {
            if (*final_task_on_target == ValueObject::eExpressionPathAftermathDereference)
            {
                Error error;
                ValueObjectSP final_value = ret_val->Dereference(error);
                if (error.Fail() || !final_value.get())
                {
                    if (reason_to_stop)
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                    if (final_value_type)
                        *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return 0;
                }
                else
                {
                    *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
                    list->Append(final_value);
                    return 1;
                }
            }
            if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress)
            {
                Error error;
                ValueObjectSP final_value = ret_val->AddressOf(error);
                if (error.Fail() || !final_value.get())
                {
                    if (reason_to_stop)
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed;
                    if (final_value_type)
                        *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return 0;
                }
                else
                {
                    *final_task_on_target = ValueObject::eExpressionPathAftermathNothing;
                    list->Append(final_value);
                    return 1;
                }
            }
        }
    }
    else
    {
        return ExpandArraySliceExpression(first_unparsed ? *first_unparsed : dummy_first_unparsed,
                                          first_unparsed ? first_unparsed : &dummy_first_unparsed,
                                          ret_val,
                                          list,
                                          reason_to_stop ? reason_to_stop : &dummy_reason_to_stop,
                                          final_value_type ? final_value_type : &dummy_final_value_type,
                                          options,
                                          final_task_on_target ? final_task_on_target : &dummy_final_task_on_target);
    }
    // in any non-covered case, just do the obviously right thing
    list->Append(ret_val);
    return 1;
}

ValueObjectSP
ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr,
                                            const char** first_unparsed,
                                            ExpressionPathScanEndReason* reason_to_stop,
                                            ExpressionPathEndResultType* final_result,
                                            const GetValueForExpressionPathOptions& options,
                                            ExpressionPathAftermath* what_next)
{
    ValueObjectSP root = GetSP();
    
    if (!root.get())
        return ValueObjectSP();
    
    *first_unparsed = expression_cstr;
    
    while (true)
    {
        
        const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
        
        ClangASTType root_clang_type = root->GetClangType();
        ClangASTType pointee_clang_type;
        Flags pointee_clang_type_info;
        
        Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type));
        if (pointee_clang_type)
            pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo());
        
        if (!expression_cstr || *expression_cstr == '\0')
        {
            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
            return root;
        }
        
        switch (*expression_cstr)
        {
            case '-':
            {
                if (options.m_check_dot_vs_arrow_syntax &&
                    root_clang_type_info.Test(ClangASTType::eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return ValueObjectSP();
                }
                if (root_clang_type_info.Test(ClangASTType::eTypeIsObjC) &&  // if yo are trying to extract an ObjC IVar when this is forbidden
                    root_clang_type_info.Test(ClangASTType::eTypeIsPointer) &&
                    options.m_no_fragile_ivar)
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return ValueObjectSP();
                }
                if (expression_cstr[1] != '>')
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return ValueObjectSP();
                }
                expression_cstr++; // skip the -
            }
            case '.': // or fallthrough from ->
            {
                if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' &&
                    root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return ValueObjectSP();
                }
                expression_cstr++; // skip .
                const char *next_separator = strpbrk(expression_cstr+1,"-.[");
                ConstString child_name;
                if (!next_separator) // if no other separator just expand this last layer
                {
                    child_name.SetCString (expression_cstr);
                    ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true);
                    
                    if (child_valobj_sp.get()) // we know we are done, so just return
                    {
                        *first_unparsed = "";
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
                        *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                        return child_valobj_sp;
                    }
                    else if (options.m_no_synthetic_children == false) // let's try with synthetic children
                    {
                        if (root->IsSynthetic())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }

                        child_valobj_sp = root->GetSyntheticValue();
                        if (child_valobj_sp.get())
                            child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                    }
                    
                    // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP,
                    // so we hit the "else" branch, and return an error
                    if(child_valobj_sp.get()) // if it worked, just return
                    {
                        *first_unparsed = "";
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
                        *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                        return child_valobj_sp;
                    }
                    else
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                }
                else // other layers do expand
                {
                    child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr);
                    ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true);
                    if (child_valobj_sp.get()) // store the new root and move on
                    {
                        root = child_valobj_sp;
                        *first_unparsed = next_separator;
                        *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                        continue;
                    }
                    else if (options.m_no_synthetic_children == false) // let's try with synthetic children
                    {
                        if (root->IsSynthetic())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        
                        child_valobj_sp = root->GetSyntheticValue(true);
                        if (child_valobj_sp)
                            child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                    }
                    
                    // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP,
                    // so we hit the "else" branch, and return an error
                    if(child_valobj_sp.get()) // if it worked, move on
                    {
                        root = child_valobj_sp;
                        *first_unparsed = next_separator;
                        *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                        continue;
                    }
                    else
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                }
                break;
            }
            case '[':
            {
                if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray) && !root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && !root_clang_type_info.Test(ClangASTType::eTypeIsVector)) // if this is not a T[] nor a T*
                {
                    if (!root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // if this is not even a scalar...
                    {
                        if (options.m_no_synthetic_children) // ...only chance left is synthetic
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                    }
                    else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                }
                if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
                {
                    if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                    else // even if something follows, we cannot expand unbounded ranges, just let the caller do it
                    {
                        *first_unparsed = expression_cstr+2;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
                        *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange;
                        return root;
                    }
                }
                const char *separator_position = ::strchr(expression_cstr+1,'-');
                const char *close_bracket_position = ::strchr(expression_cstr+1,']');
                if (!close_bracket_position) // if there is no ], this is a syntax error
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return ValueObjectSP();
                }
                if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N]
                {
                    char *end = NULL;
                    unsigned long index = ::strtoul (expression_cstr+1, &end, 0);
                    if (!end || end != close_bracket_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                    if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
                    {
                        if (root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                        {
                            *first_unparsed = expression_cstr+2;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
                            *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange;
                            return root;
                        }
                        else
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                    }
                    // from here on we do have a valid index
                    if (root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                    {
                        ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
                        if (!child_valobj_sp)
                            child_valobj_sp = root->GetSyntheticArrayMemberFromArray(index, true);
                        if (!child_valobj_sp)
                            if (root->HasSyntheticValue() && root->GetSyntheticValue()->GetNumChildren() > index)
                                child_valobj_sp = root->GetSyntheticValue()->GetChildAtIndex(index, true);
                        if (child_valobj_sp)
                        {
                            root = child_valobj_sp;
                            *first_unparsed = end+1; // skip ]
                            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                            continue;
                        }
                        else
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer))
                    {
                        if (*what_next == ValueObject::eExpressionPathAftermathDereference &&  // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
                            pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar))
                        {
                            Error error;
                            root = root->Dereference(error);
                            if (error.Fail() || !root.get())
                            {
                                *first_unparsed = expression_cstr;
                                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                                return ValueObjectSP();
                            }
                            else
                            {
                                *what_next = eExpressionPathAftermathNothing;
                                continue;
                            }
                        }
                        else
                        {
                            if (root->GetClangType().GetMinimumLanguage() == eLanguageTypeObjC
                                && pointee_clang_type_info.AllClear(ClangASTType::eTypeIsPointer)
                                && root->HasSyntheticValue()
                                && options.m_no_synthetic_children == false)
                            {
                                root = root->GetSyntheticValue()->GetChildAtIndex(index, true);
                            }
                            else
                                root = root->GetSyntheticArrayMemberFromPointer(index, true);
                            if (!root.get())
                            {
                                *first_unparsed = expression_cstr;
                                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                                return ValueObjectSP();
                            }
                            else
                            {
                                *first_unparsed = end+1; // skip ]
                                *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                                continue;
                            }
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar))
                    {
                        root = root->GetSyntheticBitFieldChild(index, index, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
                        {
                            *first_unparsed = end+1; // skip ]
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
                            *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
                            return root;
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsVector))
                    {
                        root = root->GetChildAtIndex(index, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        else
                        {
                            *first_unparsed = end+1; // skip ]
                            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                            continue;
                        }
                    }
                    else if (options.m_no_synthetic_children == false)
                    {
                        if (root->HasSyntheticValue())
                            root = root->GetSyntheticValue();
                        else if (!root->IsSynthetic())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        // if we are here, then root itself is a synthetic VO.. should be good to go
                        
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        root = root->GetChildAtIndex(index, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        else
                        {
                            *first_unparsed = end+1; // skip ]
                            *final_result = ValueObject::eExpressionPathEndResultTypePlain;
                            continue;
                        }
                    }
                    else
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                }
                else // we have a low and a high index
                {
                    char *end = NULL;
                    unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0);
                    if (!end || end != separator_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                    unsigned long index_higher = ::strtoul (separator_position+1, &end, 0);
                    if (!end || end != close_bracket_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return ValueObjectSP();
                    }
                    if (index_lower > index_higher) // swap indices if required
                    {
                        unsigned long temp = index_lower;
                        index_lower = index_higher;
                        index_higher = temp;
                    }
                    if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // expansion only works for scalars
                    {
                        root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        else
                        {
                            *first_unparsed = end+1; // skip ]
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet;
                            *final_result = ValueObject::eExpressionPathEndResultTypeBitfield;
                            return root;
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
                             *what_next == ValueObject::eExpressionPathAftermathDereference &&
                             pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar))
                    {
                        Error error;
                        root = root->Dereference(error);
                        if (error.Fail() || !root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return ValueObjectSP();
                        }
                        else
                        {
                            *what_next = ValueObject::eExpressionPathAftermathNothing;
                            continue;
                        }
                    }
                    else
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet;
                        *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange;
                        return root;
                    }
                }
                break;
            }
            default: // some non-separator is in the way
            {
                *first_unparsed = expression_cstr;
                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                return ValueObjectSP();
                break;
            }
        }
    }
}

int
ValueObject::ExpandArraySliceExpression(const char* expression_cstr,
                                        const char** first_unparsed,
                                        ValueObjectSP root,
                                        ValueObjectListSP& list,
                                        ExpressionPathScanEndReason* reason_to_stop,
                                        ExpressionPathEndResultType* final_result,
                                        const GetValueForExpressionPathOptions& options,
                                        ExpressionPathAftermath* what_next)
{
    if (!root.get())
        return 0;
    
    *first_unparsed = expression_cstr;
    
    while (true)
    {
        
        const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr
        
        ClangASTType root_clang_type = root->GetClangType();
        ClangASTType pointee_clang_type;
        Flags pointee_clang_type_info;
        Flags root_clang_type_info(root_clang_type.GetTypeInfo(&pointee_clang_type));
        if (pointee_clang_type)
            pointee_clang_type_info.Reset(pointee_clang_type.GetTypeInfo());
        
        if (!expression_cstr || *expression_cstr == '\0')
        {
            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
            list->Append(root);
            return 1;
        }
        
        switch (*expression_cstr)
        {
            case '[':
            {
                if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray) && !root_clang_type_info.Test(ClangASTType::eTypeIsPointer)) // if this is not a T[] nor a T*
                {
                    if (!root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong!
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                    else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                }
                if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays
                {
                    if (!root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                    else // expand this into list
                    {
                        const size_t max_index = root->GetNumChildren() - 1;
                        for (size_t index = 0; index < max_index; index++)
                        {
                            ValueObjectSP child = 
                                root->GetChildAtIndex(index, true);
                            list->Append(child);
                        }
                        *first_unparsed = expression_cstr+2;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                        *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                        return max_index; // tell me number of items I added to the VOList
                    }
                }
                const char *separator_position = ::strchr(expression_cstr+1,'-');
                const char *close_bracket_position = ::strchr(expression_cstr+1,']');
                if (!close_bracket_position) // if there is no ], this is a syntax error
                {
                    *first_unparsed = expression_cstr;
                    *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                    *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                    return 0;
                }
                if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N]
                {
                    char *end = NULL;
                    unsigned long index = ::strtoul (expression_cstr+1, &end, 0);
                    if (!end || end != close_bracket_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                    if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays
                    {
                        if (root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                        {
                            const size_t max_index = root->GetNumChildren() - 1;
                            for (size_t index = 0; index < max_index; index++)
                            {
                                ValueObjectSP child = 
                                root->GetChildAtIndex(index, true);
                                list->Append(child);
                            }
                            *first_unparsed = expression_cstr+2;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                            *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                            return max_index; // tell me number of items I added to the VOList
                        }
                        else
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return 0;
                        }
                    }
                    // from here on we do have a valid index
                    if (root_clang_type_info.Test(ClangASTType::eTypeIsArray))
                    {
                        root = root->GetChildAtIndex(index, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return 0;
                        }
                        else
                        {
                            list->Append(root);
                            *first_unparsed = end+1; // skip ]
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                            *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                            return 1;
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer))
                    {
                        if (*what_next == ValueObject::eExpressionPathAftermathDereference &&  // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
                            pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar))
                        {
                            Error error;
                            root = root->Dereference(error);
                            if (error.Fail() || !root.get())
                            {
                                *first_unparsed = expression_cstr;
                                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                                return 0;
                            }
                            else
                            {
                                *what_next = eExpressionPathAftermathNothing;
                                continue;
                            }
                        }
                        else
                        {
                            root = root->GetSyntheticArrayMemberFromPointer(index, true);
                            if (!root.get())
                            {
                                *first_unparsed = expression_cstr;
                                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                                return 0;
                            }
                            else
                            {
                                list->Append(root);
                                *first_unparsed = end+1; // skip ]
                                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                                *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                                return 1;
                            }
                        }
                    }
                    else /*if (ClangASTContext::IsScalarType(root_clang_type))*/
                    {
                        root = root->GetSyntheticBitFieldChild(index, index, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return 0;
                        }
                        else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing
                        {
                            list->Append(root);
                            *first_unparsed = end+1; // skip ]
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                            *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                            return 1;
                        }
                    }
                }
                else // we have a low and a high index
                {
                    char *end = NULL;
                    unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0);
                    if (!end || end != separator_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                    unsigned long index_higher = ::strtoul (separator_position+1, &end, 0);
                    if (!end || end != close_bracket_position) // if something weird is in our way return an error
                    {
                        *first_unparsed = expression_cstr;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                        *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                        return 0;
                    }
                    if (index_lower > index_higher) // swap indices if required
                    {
                        unsigned long temp = index_lower;
                        index_lower = index_higher;
                        index_higher = temp;
                    }
                    if (root_clang_type_info.Test(ClangASTType::eTypeIsScalar)) // expansion only works for scalars
                    {
                        root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true);
                        if (!root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return 0;
                        }
                        else
                        {
                            list->Append(root);
                            *first_unparsed = end+1; // skip ]
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                            *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                            return 1;
                        }
                    }
                    else if (root_clang_type_info.Test(ClangASTType::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield
                             *what_next == ValueObject::eExpressionPathAftermathDereference &&
                             pointee_clang_type_info.Test(ClangASTType::eTypeIsScalar))
                    {
                        Error error;
                        root = root->Dereference(error);
                        if (error.Fail() || !root.get())
                        {
                            *first_unparsed = expression_cstr;
                            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed;
                            *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                            return 0;
                        }
                        else
                        {
                            *what_next = ValueObject::eExpressionPathAftermathNothing;
                            continue;
                        }
                    }
                    else
                    {
                        for (unsigned long index = index_lower;
                             index <= index_higher; index++)
                        {
                            ValueObjectSP child = 
                                root->GetChildAtIndex(index, true);
                            list->Append(child);
                        }
                        *first_unparsed = end+1;
                        *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded;
                        *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList;
                        return index_higher-index_lower+1; // tell me number of items I added to the VOList
                    }
                }
                break;
            }
            default: // some non-[ separator, or something entirely wrong, is in the way
            {
                *first_unparsed = expression_cstr;
                *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol;
                *final_result = ValueObject::eExpressionPathEndResultTypeInvalid;
                return 0;
                break;
            }
        }
    }
}

void
ValueObject::LogValueObject (Log *log)
{
    if (log)
        return LogValueObject (log, DumpValueObjectOptions::DefaultOptions());
}

void
ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options)
{
    if (log)
    {
        StreamString s;
        Dump (s, options);
        if (s.GetSize())
            log->PutCString(s.GetData());
    }
}

void
ValueObject::Dump (Stream &s)
{
    
    ValueObjectPrinter printer(this,&s,DumpValueObjectOptions::DefaultOptions());
    printer.PrintValueObject();
}

void
ValueObject::Dump (Stream &s,
                   const DumpValueObjectOptions& options)
{
    ValueObjectPrinter printer(this,&s,options);
    printer.PrintValueObject();
}

ValueObjectSP
ValueObject::CreateConstantValue (const ConstString &name)
{
    ValueObjectSP valobj_sp;
    
    if (UpdateValueIfNeeded(false) && m_error.Success())
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        
        DataExtractor data;
        data.SetByteOrder (m_data.GetByteOrder());
        data.SetAddressByteSize(m_data.GetAddressByteSize());
        
        if (IsBitfield())
        {
            Value v(Scalar(GetValueAsUnsigned(UINT64_MAX)));
            m_error = v.GetValueAsData (&exe_ctx, data, 0, GetModule().get());
        }
        else
            m_error = m_value.GetValueAsData (&exe_ctx, data, 0, GetModule().get());
        
        valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), 
                                                    GetClangType(),
                                                    name,
                                                    data,
                                                    GetAddressOf());
    }
    
    if (!valobj_sp)
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), m_error);
    }
    return valobj_sp;
}

ValueObjectSP
ValueObject::Dereference (Error &error)
{
    if (m_deref_valobj)
        return m_deref_valobj->GetSP();
        
    const bool is_pointer_type = IsPointerType();
    if (is_pointer_type)
    {
        bool omit_empty_base_classes = true;
        bool ignore_array_bounds = false;

        std::string child_name_str;
        uint32_t child_byte_size = 0;
        int32_t child_byte_offset = 0;
        uint32_t child_bitfield_bit_size = 0;
        uint32_t child_bitfield_bit_offset = 0;
        bool child_is_base_class = false;
        bool child_is_deref_of_parent = false;
        const bool transparent_pointers = false;
        ClangASTType clang_type = GetClangType();
        ClangASTType child_clang_type;

        ExecutionContext exe_ctx (GetExecutionContextRef());
        
        child_clang_type = clang_type.GetChildClangTypeAtIndex (&exe_ctx,
                                                                GetName().GetCString(),
                                                                0,
                                                                transparent_pointers,
                                                                omit_empty_base_classes,
                                                                ignore_array_bounds,
                                                                child_name_str,
                                                                child_byte_size,
                                                                child_byte_offset,
                                                                child_bitfield_bit_size,
                                                                child_bitfield_bit_offset,
                                                                child_is_base_class,
                                                                child_is_deref_of_parent);
        if (child_clang_type && child_byte_size)
        {
            ConstString child_name;
            if (!child_name_str.empty())
                child_name.SetCString (child_name_str.c_str());

            m_deref_valobj = new ValueObjectChild (*this,
                                                   child_clang_type,
                                                   child_name,
                                                   child_byte_size,
                                                   child_byte_offset,
                                                   child_bitfield_bit_size,
                                                   child_bitfield_bit_offset,
                                                   child_is_base_class,
                                                   child_is_deref_of_parent,
                                                   eAddressTypeInvalid);
        }
    }

    if (m_deref_valobj)
    {
        error.Clear();
        return m_deref_valobj->GetSP();
    }
    else
    {
        StreamString strm;
        GetExpressionPath(strm, true);

        if (is_pointer_type)
            error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
        else
            error.SetErrorStringWithFormat("not a pointer type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
        return ValueObjectSP();
    }
}

ValueObjectSP
ValueObject::AddressOf (Error &error)
{
    if (m_addr_of_valobj_sp)
        return m_addr_of_valobj_sp;
        
    AddressType address_type = eAddressTypeInvalid;
    const bool scalar_is_load_address = false;
    addr_t addr = GetAddressOf (scalar_is_load_address, &address_type);
    error.Clear();
    if (addr != LLDB_INVALID_ADDRESS)
    {
        switch (address_type)
        {
        case eAddressTypeInvalid:
            {
                StreamString expr_path_strm;
                GetExpressionPath(expr_path_strm, true);
                error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_strm.GetString().c_str());
            }
            break;

        case eAddressTypeFile:
        case eAddressTypeLoad:
        case eAddressTypeHost:
            {
                ClangASTType clang_type = GetClangType();
                if (clang_type)
                {
                    std::string name (1, '&');
                    name.append (m_name.AsCString(""));
                    ExecutionContext exe_ctx (GetExecutionContextRef());
                    m_addr_of_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                                          clang_type.GetPointerType(),
                                                                          ConstString (name.c_str()),
                                                                          addr, 
                                                                          eAddressTypeInvalid,
                                                                          m_data.GetAddressByteSize());
                }
            }
            break;
        }
    }
    else
    {
        StreamString expr_path_strm;
        GetExpressionPath(expr_path_strm, true);
        error.SetErrorStringWithFormat("'%s' doesn't have a valid address", expr_path_strm.GetString().c_str());
    }
    
    return m_addr_of_valobj_sp;
}

ValueObjectSP
ValueObject::Cast (const ClangASTType &clang_ast_type)
{
    return ValueObjectCast::Create (*this, GetName(), clang_ast_type);
}

ValueObjectSP
ValueObject::CastPointerType (const char *name, ClangASTType &clang_ast_type)
{
    ValueObjectSP valobj_sp;
    AddressType address_type;
    addr_t ptr_value = GetPointerValue (&address_type);
    
    if (ptr_value != LLDB_INVALID_ADDRESS)
    {
        Address ptr_addr (ptr_value);
        ExecutionContext exe_ctx (GetExecutionContextRef());
        valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
                                               name, 
                                               ptr_addr, 
                                               clang_ast_type);
    }
    return valobj_sp;    
}

ValueObjectSP
ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
{
    ValueObjectSP valobj_sp;
    AddressType address_type;
    addr_t ptr_value = GetPointerValue (&address_type);
    
    if (ptr_value != LLDB_INVALID_ADDRESS)
    {
        Address ptr_addr (ptr_value);
        ExecutionContext exe_ctx (GetExecutionContextRef());
        valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(),
                                               name, 
                                               ptr_addr, 
                                               type_sp);
    }
    return valobj_sp;
}

ValueObject::EvaluationPoint::EvaluationPoint () :
    m_mod_id(),
    m_exe_ctx_ref(),
    m_needs_update (true),
    m_first_update (true)
{
}

ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
    m_mod_id(),
    m_exe_ctx_ref(),
    m_needs_update (true),
    m_first_update (true)
{
    ExecutionContext exe_ctx(exe_scope);
    TargetSP target_sp (exe_ctx.GetTargetSP());
    if (target_sp)
    {
        m_exe_ctx_ref.SetTargetSP (target_sp);
        ProcessSP process_sp (exe_ctx.GetProcessSP());
        if (!process_sp)
            process_sp = target_sp->GetProcessSP();
        
        if (process_sp)
        {
            m_mod_id = process_sp->GetModID();
            m_exe_ctx_ref.SetProcessSP (process_sp);
            
            ThreadSP thread_sp (exe_ctx.GetThreadSP());
            
            if (!thread_sp)
            {
                if (use_selected)
                    thread_sp = process_sp->GetThreadList().GetSelectedThread();
            }
                
            if (thread_sp)
            {
                m_exe_ctx_ref.SetThreadSP(thread_sp);
                
                StackFrameSP frame_sp (exe_ctx.GetFrameSP());
                if (!frame_sp)
                {
                    if (use_selected)
                        frame_sp = thread_sp->GetSelectedFrame();
                }
                if (frame_sp)
                    m_exe_ctx_ref.SetFrameSP(frame_sp);
            }
        }
    }
}

ValueObject::EvaluationPoint::EvaluationPoint (const ValueObject::EvaluationPoint &rhs) :
    m_mod_id(),
    m_exe_ctx_ref(rhs.m_exe_ctx_ref),
    m_needs_update (true),
    m_first_update (true)
{
}

ValueObject::EvaluationPoint::~EvaluationPoint () 
{
}

// This function checks the EvaluationPoint against the current process state.  If the current
// state matches the evaluation point, or the evaluation point is already invalid, then we return
// false, meaning "no change".  If the current state is different, we update our state, and return
// true meaning "yes, change".  If we did see a change, we also set m_needs_update to true, so 
// future calls to NeedsUpdate will return true.
// exe_scope will be set to the current execution context scope.

bool
ValueObject::EvaluationPoint::SyncWithProcessState()
{

    // Start with the target, if it is NULL, then we're obviously not going to get any further:
    const bool thread_and_frame_only_if_stopped = true;
    ExecutionContext exe_ctx(m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped));
    
    if (exe_ctx.GetTargetPtr() == NULL)
        return false;
    
    // If we don't have a process nothing can change.
    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
        return false;
        
    // If our stop id is the current stop ID, nothing has changed:
    ProcessModID current_mod_id = process->GetModID();
    
    // If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
    // In either case, we aren't going to be able to sync with the process state.
    if (current_mod_id.GetStopID() == 0)
        return false;
    
    bool changed = false;
    const bool was_valid = m_mod_id.IsValid();
    if (was_valid)
    {
        if (m_mod_id == current_mod_id)
        {
            // Everything is already up to date in this object, no need to 
            // update the execution context scope.
            changed = false;
        }
        else
        {
            m_mod_id = current_mod_id;
            m_needs_update = true;
            changed = true;
        }       
    }
    
    // Now re-look up the thread and frame in case the underlying objects have gone away & been recreated.
    // That way we'll be sure to return a valid exe_scope.
    // If we used to have a thread or a frame but can't find it anymore, then mark ourselves as invalid.
    
    if (m_exe_ctx_ref.HasThreadRef())
    {
        ThreadSP thread_sp (m_exe_ctx_ref.GetThreadSP());
        if (thread_sp)
        {
            if (m_exe_ctx_ref.HasFrameRef())
            {
                StackFrameSP frame_sp (m_exe_ctx_ref.GetFrameSP());
                if (!frame_sp)
                {
                    // We used to have a frame, but now it is gone
                    SetInvalid();
                    changed = was_valid;
                }
            }
        }
        else
        {
            // We used to have a thread, but now it is gone
            SetInvalid();
            changed = was_valid;
        }

    }
    return changed;
}

void
ValueObject::EvaluationPoint::SetUpdated ()
{
    ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
    if (process_sp)
        m_mod_id = process_sp->GetModID();
    m_first_update = false;
    m_needs_update = false;
}
        


void
ValueObject::ClearUserVisibleData(uint32_t clear_mask)
{
    if ((clear_mask & eClearUserVisibleDataItemsValue) == eClearUserVisibleDataItemsValue)
        m_value_str.clear();
    
    if ((clear_mask & eClearUserVisibleDataItemsLocation) == eClearUserVisibleDataItemsLocation)
        m_location_str.clear();
    
    if ((clear_mask & eClearUserVisibleDataItemsSummary) == eClearUserVisibleDataItemsSummary)
    {
        m_summary_str.clear();
    }
    
    if ((clear_mask & eClearUserVisibleDataItemsDescription) == eClearUserVisibleDataItemsDescription)
        m_object_desc_str.clear();
    
    if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == eClearUserVisibleDataItemsSyntheticChildren)
    {
            if (m_synthetic_value)
                m_synthetic_value = NULL;
    }
}

SymbolContextScope *
ValueObject::GetSymbolContextScope()
{
    if (m_parent)
    {
        if (!m_parent->IsPointerOrReferenceType())
            return m_parent->GetSymbolContextScope();
    }
    return NULL;
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromExpression (const char* name,
                                              const char* expression,
                                              const ExecutionContext& exe_ctx)
{
    lldb::ValueObjectSP retval_sp;
    lldb::TargetSP target_sp(exe_ctx.GetTargetSP());
    if (!target_sp)
        return retval_sp;
    if (!expression || !*expression)
        return retval_sp;
    target_sp->EvaluateExpression (expression,
                                   exe_ctx.GetFrameSP().get(),
                                   retval_sp);
    if (retval_sp && name && *name)
        retval_sp->SetName(ConstString(name));
    return retval_sp;
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromAddress (const char* name,
                                           uint64_t address,
                                           const ExecutionContext& exe_ctx,
                                           ClangASTType type)
{
    if (type)
    {
        ClangASTType pointer_type(type.GetPointerType());
        if (pointer_type)
        {
            lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
            lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                                                     pointer_type,
                                                                                     ConstString(name),
                                                                                     buffer,
                                                                                     lldb::endian::InlHostByteOrder(),
                                                                                     exe_ctx.GetAddressByteSize()));
            if (ptr_result_valobj_sp)
            {
                ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress);
                Error err;
                ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
                if (ptr_result_valobj_sp && name && *name)
                    ptr_result_valobj_sp->SetName(ConstString(name));
            }
            return ptr_result_valobj_sp;
        }
    }
    return lldb::ValueObjectSP();
}

lldb::ValueObjectSP
ValueObject::CreateValueObjectFromData (const char* name,
                                        const DataExtractor& data,
                                        const ExecutionContext& exe_ctx,
                                        ClangASTType type)
{
    lldb::ValueObjectSP new_value_sp;
    new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                   type,
                                                   ConstString(name),
                                                   data,
                                                   LLDB_INVALID_ADDRESS);
    new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad);
    if (new_value_sp && name && *name)
        new_value_sp->SetName(ConstString(name));
    return new_value_sp;
}

ModuleSP
ValueObject::GetModule ()
{
    ValueObject* root(GetRoot());
    if (root != this)
        return root->GetModule();
    return lldb::ModuleSP();
}

ValueObject*
ValueObject::GetRoot ()
{
    if (m_root)
        return m_root;
    ValueObject* parent = m_parent;
    if (!parent)
        return (m_root = this);
    while (parent->m_parent)
    {
        if (parent->m_root)
            return (m_root = parent->m_root);
        parent = parent->m_parent;
    }
    return (m_root = parent);
}

AddressType
ValueObject::GetAddressTypeOfChildren()
{
    if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid)
    {
        ValueObject* root(GetRoot());
        if (root != this)
            return root->GetAddressTypeOfChildren();
    }
    return m_address_type_of_ptr_or_ref_children;
}

lldb::DynamicValueType
ValueObject::GetDynamicValueType ()
{
    ValueObject* with_dv_info = this;
    while (with_dv_info)
    {
        if (with_dv_info->HasDynamicValueTypeInfo())
            return with_dv_info->GetDynamicValueTypeImpl();
        with_dv_info = with_dv_info->m_parent;
    }
    return lldb::eNoDynamicValues;
}

lldb::Format
ValueObject::GetFormat () const
{
    const ValueObject* with_fmt_info = this;
    while (with_fmt_info)
    {
        if (with_fmt_info->m_format != lldb::eFormatDefault)
            return with_fmt_info->m_format;
        with_fmt_info = with_fmt_info->m_parent;
    }
    return m_format;
}
