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

// C Includes
#include <stdlib.h>

// C++ Includes
// Other libraries and framework includes
#include "llvm/Support/raw_ostream.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/StringPrinter.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"

#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"

#include "lldb/Host/Endian.h"

#include "lldb/Interpreter/CommandInterpreter.h"

#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Type.h"

#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Language.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_validation_result(),
    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_type_validator_sp(),
    m_user_id_of_forced_summary(),
    m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid),
    m_value_checksum(),
    m_preferred_display_language(lldb::eLanguageTypeUnknown),
    m_language_flags(0),
    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_is_synthetic_children_generated(parent.m_is_synthetic_children_generated)
{
    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_validation_result(),
    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_type_validator_sp(),
    m_user_id_of_forced_summary(),
    m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type),
    m_value_checksum(),
    m_preferred_display_language(lldb::eLanguageTypeUnknown),
    m_language_flags(0),
    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_is_synthetic_children_generated(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 = IsChecksumEmpty();
    
    if (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 need_compare_checksums = false;
            llvm::SmallVector<uint8_t, 16> old_checksum;
            
            if (!first_update && CanProvideValue())
            {
                need_compare_checksums = true;
                old_checksum.resize(m_value_checksum.size());
                std::copy(m_value_checksum.begin(), m_value_checksum.end(), old_checksum.begin());
            }
            
            bool success = UpdateValue ();
            
            SetValueIsValid (success);
            
            if (success)
            {
                const uint64_t max_checksum_size = 128;
                m_data.Checksum(m_value_checksum,
                                max_checksum_size);
            }
            else
            {
                need_compare_checksums = false;
                m_value_checksum.clear();
            }
            
            assert (!need_compare_checksums || (!old_checksum.empty() && !m_value_checksum.empty()));

            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 if (need_compare_checksums)
            {
                SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], m_value_checksum.size()));
            }
            
        }
        else
        {
            m_error.SetErrorString("out of scope");
        }
    }
    return m_error.Success();
}

bool
ValueObject::UpdateFormatsIfNeeded()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS));
    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
        SetValidator(DataVisualization::GetValidator(*this, GetDynamicValueType()));
    }

    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 = CompilerType();
    SetValueFormat(lldb::TypeFormatImplSP());
    SetSummaryFormat(lldb::TypeSummaryImplSP());
    SetSyntheticChildren(lldb::SyntheticChildrenSP());
}

CompilerType
ValueObject::MaybeCalculateCompleteType ()
{
    CompilerType compiler_type(GetCompilerTypeImpl());
        
    if (m_did_calculate_complete_objc_class_type)
    {
        if (m_override_type.IsValid())
            return m_override_type;
        else
            return compiler_type;
    }
    
    CompilerType class_type;
    bool is_pointer_type = false;
    
    if (ClangASTContext::IsObjCObjectPointerType(compiler_type, &class_type))
    {
        is_pointer_type = true;
    }
    else if (ClangASTContext::IsObjCObjectOrInterfaceType(compiler_type))
    {
        class_type = compiler_type;
    }
    else
    {
        return compiler_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)
                    {
                        CompilerType complete_class(complete_objc_class_type_sp->GetFullCompilerType ());
                        
                        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 compiler_type;
}

CompilerType
ValueObject::GetCompilerType ()
{
    return MaybeCalculateCompleteType();
}

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

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::IsLogicalTrue (Error& error)
{
    if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
    {
        LazyBool is_logical_true = language->IsLogicalTrue(*this, error);
        switch (is_logical_true)
        {
            case eLazyBoolYes:
            case eLazyBoolNo:
                return (is_logical_true == true);
            case eLazyBoolCalculate:
                break;
        }
    }
    
    Scalar scalar_value;
    
    if (!ResolveValue (scalar_value))
    {
        error.SetErrorString("failed to get a scalar result");
        return false;
    }
    
    bool ret;
    if (scalar_value.ULongLong(1) == 0)
        ret = false;
    else
        ret = true;
    error.Clear();
    return ret;
}

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


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

bool
ValueObject::GetValueDidChange ()
{
    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)
{
    return GetChildAtIndexPath( std::vector<size_t>(idxs),
                               index_of_error );
}

ValueObjectSP
ValueObject::GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> >& idxs,
                                  size_t* index_of_error)
{
    return GetChildAtIndexPath( std::vector<std::pair<size_t,bool>>(idxs),
                               index_of_error );
}

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)
{
    return GetChildAtNamePath( std::vector<ConstString>(names),
                              name_of_error );
}

lldb::ValueObjectSP
ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names,
                                 ConstString* name_of_error)
{
    return GetChildAtNamePath( std::vector<std::pair<ConstString,bool>>(names),
                              name_of_error );
}

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::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 GetCompilerType().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 =  GetCompilerType().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 (uint32_t max)
{
    UpdateValueIfNeeded();

    if (max < UINT32_MAX)
    {
        if (m_children_count_valid)
        {
            size_t children_count = m_children.GetChildrenCount();
            return children_count <= max ? children_count : max;
        }
        else
            return CalculateNumChildren(max);
    }

    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 & (eTypeHasChildren |
                         eTypeIsPointer |
                         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;
    uint64_t language_flags = 0;

    const bool transparent_pointers = synthetic_array_member == false;
    CompilerType child_compiler_type;
    
    ExecutionContext exe_ctx (GetExecutionContextRef());
    
    child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex (&exe_ctx,
                                                                      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,
                                                                      this,
                                                                      language_flags);
    if (child_compiler_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_compiler_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,
                                       language_flags);
        //if (valobj)
        //    valobj->SetAddressTypeOfChildren(eAddressTypeInvalid);
   }
    
    return valobj;
}

bool
ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
                                  std::string& destination,
                                  lldb::LanguageType lang)
{
    return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions().SetLanguage(lang));
}

bool
ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr,
                                  std::string& destination,
                                  const TypeSummaryOptions& options)
{
    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;
    
    TypeSummaryOptions actual_options(options);
    
    if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown)
        actual_options.SetLanguage(GetPreferredDisplayLanguage());
    
    // 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) && 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, actual_options);
    }
    m_is_getting_summary = false;
    return !destination.empty();
}

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

bool
ValueObject::GetSummaryAsCString (std::string& destination,
                                  const TypeSummaryOptions& options)
{
    return GetSummaryAsCString(GetSummaryFormat().get(),
                               destination,
                               options);
}

bool
ValueObject::IsCStringContainer(bool check_pointer)
{
    CompilerType pointee_or_element_compiler_type;
    const Flags type_flags (GetTypeInfo (&pointee_or_element_compiler_type));
    bool is_char_arr_ptr (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) &&
                          pointee_or_element_compiler_type.IsCharType ());
    if (!is_char_arr_ptr)
        return false;
    if (!check_pointer)
        return true;
    if (type_flags.Test(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)
{
    CompilerType pointee_or_element_compiler_type;
    const uint32_t type_info = GetTypeInfo (&pointee_or_element_compiler_type);
    const bool is_pointer_type = type_info & eTypeIsPointer;
    const bool is_array_type = type_info & eTypeIsArray;
    if (!(is_pointer_type || is_array_type))
        return 0;
    
    if (item_count == 0)
        return 0;
    
    ExecutionContext exe_ctx (GetExecutionContextRef());
    
    const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
    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 = GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
                    if (max_bytes > offset)
                    {
                        size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
                        addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                        if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
                            break;
                        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;
            error.Clear();
            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 = GetCompilerType().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;
}

static bool
CopyStringDataToBufferSP(const StreamString& source,
                         lldb::DataBufferSP& destination)
{
    destination.reset(new DataBufferHeap(source.GetSize()+1,0));
    memcpy(destination->GetBytes(), source.GetString().c_str(), source.GetSize());
    return true;
}

std::pair<size_t,bool>
ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp,
                                Error& error,
                                uint32_t max_length,
                                bool honor_array,
                                Format item_format)
{
    bool was_capped = false;
    StreamString s;
    ExecutionContext exe_ctx (GetExecutionContextRef());
    Target* target = exe_ctx.GetTargetPtr();
    
    if (!target)
    {
        s << "<no target to read from>";
        error.SetErrorString("no target to read from");
        CopyStringDataToBufferSP(s, buffer_sp);
        return {0,was_capped};
    }
    
    if (max_length == 0)
        max_length = target->GetMaximumSizeOfStringSummary();
    
    size_t bytes_read = 0;
    size_t total_bytes_read = 0;
    
    CompilerType compiler_type = GetCompilerType();
    CompilerType elem_or_pointee_compiler_type;
    const Flags type_flags (GetTypeInfo (&elem_or_pointee_compiler_type));
    if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) &&
        elem_or_pointee_compiler_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 (eTypeIsArray))
        {
            // We have an array
            uint64_t array_size = 0;
            if (compiler_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");
            CopyStringDataToBufferSP(s, buffer_sp);
            return {0,was_capped};
        }
        
        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;
                for (size_t offset = 0; offset < bytes_read; offset++)
                    s.Printf("%c", *data.PeekData(offset, 1));
                if (capped_data)
                    was_capped = true;
            }
        }
        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 = strnlen (cstr, k_max_buf_size);
                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;
                
                for (size_t offset = 0; offset < bytes_read; offset++)
                    s.Printf("%c", *data.PeekData(offset, 1));
                
                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)
            {
                if (capped_cstr)
                    was_capped = true;
            }
        }
    }
    else
    {
        error.SetErrorString("not a string object");
        s << "<not a string object>";
    }
    CopyStringDataToBufferSP(s, buffer_sp);
    return {total_bytes_read,was_capped};
}

std::pair<TypeValidatorResult, std::string>
ValueObject::GetValidationStatus ()
{
    if (!UpdateValueIfNeeded(true))
        return {TypeValidatorResult::Success,""}; // not the validator's job to discuss update problems
    
    if (m_validation_result.hasValue())
        return m_validation_result.getValue();
    
    if (!m_type_validator_sp)
        return {TypeValidatorResult::Success,""}; // no validator no failure
    
    auto outcome = m_type_validator_sp->FormatObject(this);
    
    return (m_validation_result = {outcome.m_result,outcome.m_message}).getValue();
}

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...
        CompilerType compiler_type = GetCompilerType();
        if (compiler_type)
        {
            bool is_signed;
            if (compiler_type.IsIntegerType (is_signed) || compiler_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 = GetValue().GetCompilerType().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 (CanProvideValue())
    {
        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 (CanProvideValue())
    {
        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(eTypeIsArray | 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(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(eTypeIsArray | 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;
                lldb::DataBufferSP buffer_sp;
                std::pair<size_t, bool> read_string = ReadPointedString(buffer_sp,
                                                                        error,
                                                                        0,
                                                                        (custom_format == eFormatVectorOfChar) ||
                                                                        (custom_format == eFormatCharArray));
                lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions options(*this);
                options.SetData(DataExtractor(buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults
                options.SetStream(&s);
                options.SetPrefixToken(0);
                options.SetQuote('"');
                options.SetSourceSize(buffer_sp->GetByteSize());
                options.SetIsTruncated(read_string.second);
                formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::ASCII>(options);
                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(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 (!CanProvideValue())
                {
                    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:
        {
            if(address_type)
                *address_type = m_value.GetValueAddressType ();
            return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
        }
        break;
    case Value::eValueTypeHostAddress:
        {
            if(address_type)
                *address_type = m_value.GetValueAddressType ();
            return 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 = GetCompilerType().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 <= 16)
    {
        // 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 GetCompilerType().GetConstTypeName();
}

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

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


LanguageType
ValueObject::GetObjectRuntimeLanguage ()
{
    return GetCompilerType().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 (CompilerType *pointee_or_element_compiler_type)
{
    return GetCompilerType().GetTypeInfo (pointee_or_element_compiler_type);
}

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

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

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

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

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

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

bool
ValueObject::IsRuntimeSupportValue ()
{
    Process *process(GetProcessSP().get());
    if (process)
    {
        LanguageRuntime *runtime = process->GetLanguageRuntime(GetObjectRuntimeLanguage());
        if (!runtime)
            runtime = process->GetObjCLanguageRuntime();
        if (runtime)
            return runtime->IsRuntimeSupportValue(*this);
    }
    return false;
}

bool
ValueObject::IsNilReference ()
{
    if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
    {
        return language->IsNilReference(*this);
    }
    return false;
}

bool
ValueObject::IsUninitializedReference ()
{
    if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage()))
    {
        return language->IsUninitializedReference(*this);
    }
    return false;
}

// 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::GetSyntheticArrayMember (size_t index, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    if (IsPointerType () || 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,
                                                                      GetCompilerType(),
                                                                      index_const_str,
                                                                      GetByteSize(),
                                                                      0,
                                                                      to-from+1,
                                                                      from,
                                                                      false,
                                                                      false,
                                                                      eAddressTypeInvalid,
                                                                      0);
            
            // 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 CompilerType& 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();
    
    ExecutionContext exe_ctx (GetExecutionContextRef());
    
    ValueObjectChild *synthetic_child = new ValueObjectChild(*this,
                                                             type,
                                                             name_const_str,
                                                             type.GetByteSize(exe_ctx.GetBestExecutionContextScope()),
                                                             offset,
                                                             0,
                                                             0,
                                                             false,
                                                             false,
                                                             eAddressTypeInvalid,
                                                             0);
    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;
}

ValueObjectSP
ValueObject::GetSyntheticBase (uint32_t offset, const CompilerType& type, bool can_create)
{
    ValueObjectSP synthetic_child_sp;
    
    char name_str[64];
    snprintf(name_str, sizeof(name_str), "%s", type.GetTypeName().AsCString("<unknown>"));
    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();
    
    const bool is_base_class = true;
    
    ExecutionContext exe_ctx (GetExecutionContextRef());
    
    ValueObjectChild *synthetic_child = new ValueObjectChild(*this,
                                                             type,
                                                             name_const_str,
                                                             type.GetByteSize(exe_ctx.GetBestExecutionContextScope()),
                                                             offset,
                                                             0,
                                                             0,
                                                             is_base_class,
                                                             false,
                                                             eAddressTypeInvalid,
                                                             0);
    if (synthetic_child)
    {
        AddSyntheticChild(name_const_str, synthetic_child);
        synthetic_child_sp = synthetic_child->GetSP();
        synthetic_child_sp->SetName(name_const_str);
    }
    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().SetSyntheticChildrenTraversal(GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None));
        
        // 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);
        CompilerType compiler_type = GetCompilerType();
        std::string cxx_class_name;
        bool this_had_base_class = ClangASTContext::GetCXXClassName (compiler_type, 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;
}


bool
ValueObject::IsBaseClass (uint32_t& depth)
{
    if (!IsBaseClass())
    {
        depth = 0;
        return false;
    }
    if (GetParent())
    {
        GetParent()->IsBaseClass(depth);
        depth = depth + 1;
        return true;
    }
    // TODO: a base of no parent? weird..
    depth = 1;
    return true;
}

void
ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat)
{
    // synthetic children do not actually "exist" as part of the hierarchy, and sometimes they are consed up in ways
    // that don't make sense from an underlying language/API standpoint. So, use a special code path here to return
    // something that can hopefully be used in expression
    if (m_is_synthetic_children_generated)
    {
        UpdateValueIfNeeded();
        
        if (m_value.GetValueType() == Value::eValueTypeLoadAddress)
        {
            if (IsPointerOrReferenceType())
            {
                s.Printf("((%s)0x%" PRIx64 ")",
                         GetTypeName().AsCString("void"),
                         GetValueAsUnsigned(0));
                return;
            }
            else
            {
                uint64_t load_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                if (load_addr != LLDB_INVALID_ADDRESS)
                {
                    s.Printf("(*( (%s *)0x%" PRIx64 "))",
                             GetTypeName().AsCString("void"),
                             load_addr);
                    return;
                }
            }
        }
        
        if (CanProvideValue())
        {
            s.Printf("((%s)%s)",
                     GetTypeName().AsCString("void"),
                     GetValueAsCString());
            return;
        }
        
        return;
    }
    
    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)
            {
                CompilerType non_base_class_parent_compiler_type = non_base_class_parent->GetCompilerType();
                if (non_base_class_parent_compiler_type)
                {
                    if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers)
                    {
                        s.PutCString("->");
                    }
                    else
                    {                    
                        const uint32_t non_base_class_parent_type_info = non_base_class_parent_compiler_type.GetTypeInfo();
                        
                        if (non_base_class_parent_type_info & eTypeIsPointer)
                        {
                            s.PutCString("->");
                        }
                        else if ((non_base_class_parent_type_info & eTypeHasChildren) &&
                                 !(non_base_class_parent_type_info & 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
        
        CompilerType root_compiler_type = root->GetCompilerType();
        CompilerType pointee_compiler_type;
        Flags pointee_compiler_type_info;
        
        Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type));
        if (pointee_compiler_type)
            pointee_compiler_type_info.Reset(pointee_compiler_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_compiler_type_info.Test(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_compiler_type_info.Test(eTypeIsObjC) &&  // if yo are trying to extract an ObjC IVar when this is forbidden
                    root_compiler_type_info.Test(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_compiler_type_info.Test(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
                    {
                        switch (options.m_synthetic_children_traversal)
                        {
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None:
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::FromSynthetic:
                                if (root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetNonSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic:
                                if (!root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both:
                                if (root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetNonSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                else
                                {
                                    child_valobj_sp = root->GetSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                        }
                    }
                    
                    // 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
                    {
                        switch (options.m_synthetic_children_traversal)
                        {
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None:
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::FromSynthetic:
                                if (root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetNonSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic:
                                if (!root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                            case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both:
                                if (root->IsSynthetic())
                                {
                                    child_valobj_sp = root->GetNonSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                else
                                {
                                    child_valobj_sp = root->GetSyntheticValue();
                                    if (child_valobj_sp.get())
                                        child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true);
                                }
                                break;
                        }
                    }
                    
                    // 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_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer) && !root_compiler_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T*
                {
                    if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar...
                    {
                        if (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None) // ...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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(eTypeIsArray))
                    {
                        ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true);
                        if (!child_valobj_sp)
                            child_valobj_sp = root->GetSyntheticArrayMember(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_compiler_type_info.Test(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_compiler_type_info.Test(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->GetCompilerType().GetMinimumLanguage() == eLanguageTypeObjC
                                && pointee_compiler_type_info.AllClear(eTypeIsPointer)
                                && root->HasSyntheticValue()
                                && (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic ||
                                    options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both))
                            {
                                root = root->GetSyntheticValue()->GetChildAtIndex(index, true);
                            }
                            else
                                root = root->GetSyntheticArrayMember(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_compiler_type_info.Test(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_compiler_type_info.Test(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_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic ||
                             options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both)
                    {
                        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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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
        
        CompilerType root_compiler_type = root->GetCompilerType();
        CompilerType pointee_compiler_type;
        Flags pointee_compiler_type_info;
        Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type));
        if (pointee_compiler_type)
            pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo());
        
        if (!expression_cstr || *expression_cstr == '\0')
        {
            *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString;
            list->Append(root);
            return 1;
        }
        
        switch (*expression_cstr)
        {
            case '[':
            {
                if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T*
                {
                    if (!root_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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->GetSyntheticArrayMember(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_compiler_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_compiler_type_info.Test(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_compiler_type_info.Test(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_compiler_type_info.Test(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(*this));
}

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)
{
    Dump (s, DumpValueObjectOptions(*this));
}

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(), 
                                                    GetCompilerType(),
                                                    name,
                                                    data,
                                                    GetAddressOf());
    }
    
    if (!valobj_sp)
    {
        ExecutionContext exe_ctx (GetExecutionContextRef());
        valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), m_error);
    }
    return valobj_sp;
}

ValueObjectSP
ValueObject::GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynValue,
                                                    bool synthValue)
{
    ValueObjectSP result_sp(GetSP());
    
    switch (dynValue)
    {
        case lldb::eDynamicCanRunTarget:
        case lldb::eDynamicDontRunTarget:
        {
            if (!result_sp->IsDynamic())
            {
                if (result_sp->GetDynamicValue(dynValue))
                    result_sp = result_sp->GetDynamicValue(dynValue);
            }
        }
            break;
        case lldb::eNoDynamicValues:
        {
            if (result_sp->IsDynamic())
            {
                if (result_sp->GetStaticValue())
                    result_sp = result_sp->GetStaticValue();
            }
        }
            break;
    }
    
    if (synthValue)
    {
        if (!result_sp->IsSynthetic())
        {
            if (result_sp->GetSyntheticValue())
                result_sp = result_sp->GetSyntheticValue();
        }
    }
    else
    {
        if (result_sp->IsSynthetic())
        {
            if (result_sp->GetNonSyntheticValue())
                result_sp = result_sp->GetNonSyntheticValue();
        }
    }
    
    return result_sp;
}

lldb::addr_t
ValueObject::GetCPPVTableAddress (AddressType &address_type)
{
    CompilerType pointee_type;
    CompilerType this_type(GetCompilerType());
    uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
    if (type_info)
    {
        bool ptr_or_ref = false;
        if (type_info & (eTypeIsPointer | eTypeIsReference))
        {
            ptr_or_ref = true;
            type_info = pointee_type.GetTypeInfo();
        }
        
        const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
        if ((type_info & cpp_class) == cpp_class)
        {
            if (ptr_or_ref)
            {
                address_type = GetAddressTypeOfChildren();
                return GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
            }
            else
                return GetAddressOf (false, &address_type);
        }
    }

    address_type = eAddressTypeInvalid;
    return LLDB_INVALID_ADDRESS;
}

ValueObjectSP
ValueObject::Dereference (Error &error)
{
    if (m_deref_valobj)
        return m_deref_valobj->GetSP();

    const bool is_pointer_or_reference_type = IsPointerOrReferenceType();
    if (is_pointer_or_reference_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;
        CompilerType compiler_type = GetCompilerType();
        CompilerType child_compiler_type;
        uint64_t language_flags;

        ExecutionContext exe_ctx (GetExecutionContextRef());

        child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx,
                                                                         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,
                                                                         this,
                                                                         language_flags);
        if (child_compiler_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_compiler_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,
                                                   language_flags);
        }
    }

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

        if (is_pointer_or_reference_type)
            error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str());
        else
            error.SetErrorStringWithFormat("not a pointer or reference 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 && address_type != eAddressTypeHost)
    {
        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:
            {
                CompilerType compiler_type = GetCompilerType();
                if (compiler_type)
                {
                    std::string name (1, '&');
                    name.append (m_name.AsCString(""));
                    ExecutionContext exe_ctx (GetExecutionContextRef());
                    m_addr_of_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(),
                                                                          compiler_type.GetPointerType(),
                                                                          ConstString (name.c_str()),
                                                                          addr, 
                                                                          eAddressTypeInvalid,
                                                                          m_data.GetAddressByteSize());
                }
            }
            break;
        default:
            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 CompilerType &compiler_type)
{
    return ValueObjectCast::Create (*this, GetName(), compiler_type);
}

ValueObjectSP
ValueObject::CastPointerType (const char *name, CompilerType &compiler_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, 
                                               compiler_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)
{
}

ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
    m_mod_id(),
    m_exe_ctx_ref(),
    m_needs_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)
{
}

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(bool accept_invalid_exe_ctx)
{
    // 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 (!accept_invalid_exe_ctx)
    {
        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_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;
    }
    
    if ((clear_mask & eClearUserVisibleDataItemsValidator) == eClearUserVisibleDataItemsValidator)
        m_validation_result.reset();
}

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)
{
    return CreateValueObjectFromExpression(name, expression, exe_ctx, EvaluateExpressionOptions());
}


lldb::ValueObjectSP
ValueObject::CreateValueObjectFromExpression (const char* name,
                                              const char* expression,
                                              const ExecutionContext& exe_ctx,
                                              const EvaluateExpressionOptions& options)
{
    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,
                                   options);
    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,
                                           CompilerType type)
{
    if (type)
    {
        CompilerType 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,
                                                                                     exe_ctx.GetByteOrder(),
                                                                                     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,
                                        CompilerType 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;
    return (m_root = FollowParentChain( [] (ValueObject* vo) -> bool {
        return (vo->m_parent != nullptr);
    }));
}

ValueObject*
ValueObject::FollowParentChain (std::function<bool(ValueObject*)> f)
{
    ValueObject* vo = this;
    while (vo)
    {
        if (f(vo) == false)
            break;
        vo = vo->m_parent;
    }
    return vo;
}

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;
}

lldb::LanguageType
ValueObject::GetPreferredDisplayLanguage ()
{
    lldb::LanguageType type = m_preferred_display_language;
    if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
    {
        if (GetRoot())
        {
            if (GetRoot() == this)
            {
                if (StackFrameSP frame_sp = GetFrameSP())
                {
                    const SymbolContext& sc(frame_sp->GetSymbolContext(eSymbolContextCompUnit));
                    if (CompileUnit* cu = sc.comp_unit)
                        type = cu->GetLanguage();
                }
            }
            else
            {
                type = GetRoot()->GetPreferredDisplayLanguage();
            }
        }
    }
    return (m_preferred_display_language = type); // only compute it once
}

void
ValueObject::SetPreferredDisplayLanguage (lldb::LanguageType lt)
{
    m_preferred_display_language = lt;
}

void
ValueObject::SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType lt)
{
    if (m_preferred_display_language == lldb::eLanguageTypeUnknown)
        SetPreferredDisplayLanguage(lt);
}

bool
ValueObject::CanProvideValue ()
{
    // we need to support invalid types as providers of values because some bare-board
    // debugging scenarios have no notion of types, but still manage to have raw numeric
    // values for things like registers. sigh.
    const CompilerType &type(GetCompilerType());
    return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}

bool
ValueObject::IsChecksumEmpty ()
{
    return m_value_checksum.empty();
}

ValueObjectSP
ValueObject::Persist ()
{
    if (!UpdateValueIfNeeded())
        return nullptr;
    
    TargetSP target_sp(GetTargetSP());
    if (!target_sp)
        return nullptr;
    
    PersistentExpressionState *persistent_state = target_sp->GetPersistentExpressionStateForLanguage(GetPreferredDisplayLanguage());
    
    if (!persistent_state)
        return nullptr;
    
    ConstString name(persistent_state->GetNextPersistentVariableName());
    
    ValueObjectSP const_result_sp = ValueObjectConstResult::Create (target_sp.get(), GetValue(), name);
    
    ExpressionVariableSP clang_var_sp = persistent_state->CreatePersistentVariable(const_result_sp);
    clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp;
    clang_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference;
    
    return clang_var_sp->GetValueObject();
}

bool
ValueObject::IsSyntheticChildrenGenerated ()
{
    return m_is_synthetic_children_generated;
}

void
ValueObject::SetSyntheticChildrenGenerated (bool b)
{
    m_is_synthetic_children_generated = b;
}

uint64_t
ValueObject::GetLanguageFlags ()
{
    return m_language_flags;
}

void
ValueObject::SetLanguageFlags (uint64_t flags)
{
    m_language_flags = flags;
}
