Home | History | Annotate | Download | only in Core
      1 //===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/lldb-python.h"
     11 
     12 #include "lldb/Core/ValueObjectSyntheticFilter.h"
     13 
     14 // C Includes
     15 // C++ Includes
     16 // Other libraries and framework includes
     17 // Project includes
     18 #include "lldb/Core/ValueObject.h"
     19 #include "lldb/DataFormatters/FormatClasses.h"
     20 
     21 using namespace lldb_private;
     22 
     23 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
     24 {
     25 public:
     26     DummySyntheticFrontEnd(ValueObject &backend) :
     27     SyntheticChildrenFrontEnd(backend)
     28     {}
     29 
     30     size_t
     31     CalculateNumChildren()
     32     {
     33         return 0;
     34     }
     35 
     36     lldb::ValueObjectSP
     37     GetChildAtIndex (size_t idx)
     38     {
     39         return lldb::ValueObjectSP();
     40     }
     41 
     42     size_t
     43     GetIndexOfChildWithName (const ConstString &name)
     44     {
     45         return UINT32_MAX;
     46     }
     47 
     48     bool
     49     MightHaveChildren ()
     50     {
     51         return true;
     52     }
     53 
     54     bool
     55     Update()
     56     {
     57         return false;
     58     }
     59 
     60 };
     61 
     62 ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
     63     ValueObject(parent),
     64     m_synth_sp(filter),
     65     m_children_byindex(),
     66     m_name_toindex(),
     67     m_synthetic_children_count(UINT32_MAX),
     68     m_parent_type_name(parent.GetTypeName()),
     69     m_might_have_children(eLazyBoolCalculate)
     70 {
     71 #ifdef LLDB_CONFIGURATION_DEBUG
     72     std::string new_name(parent.GetName().AsCString());
     73     new_name += "$$__synth__";
     74     SetName (ConstString(new_name.c_str()));
     75 #else
     76     SetName(parent.GetName());
     77 #endif
     78     CopyParentData();
     79     CreateSynthFilter();
     80 }
     81 
     82 ValueObjectSynthetic::~ValueObjectSynthetic()
     83 {
     84 }
     85 
     86 ClangASTType
     87 ValueObjectSynthetic::GetClangTypeImpl ()
     88 {
     89     return m_parent->GetClangType();
     90 }
     91 
     92 ConstString
     93 ValueObjectSynthetic::GetTypeName()
     94 {
     95     return m_parent->GetTypeName();
     96 }
     97 
     98 ConstString
     99 ValueObjectSynthetic::GetQualifiedTypeName()
    100 {
    101     return m_parent->GetQualifiedTypeName();
    102 }
    103 
    104 size_t
    105 ValueObjectSynthetic::CalculateNumChildren()
    106 {
    107     UpdateValueIfNeeded();
    108     if (m_synthetic_children_count < UINT32_MAX)
    109         return m_synthetic_children_count;
    110     return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
    111 }
    112 
    113 lldb::ValueObjectSP
    114 ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
    115 {
    116     if (!m_parent)
    117         return lldb::ValueObjectSP();
    118     if (IsDynamic() && GetDynamicValueType() == valueType)
    119         return GetSP();
    120     return m_parent->GetDynamicValue(valueType);
    121 }
    122 
    123 bool
    124 ValueObjectSynthetic::MightHaveChildren()
    125 {
    126     if (m_might_have_children == eLazyBoolCalculate)
    127         m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
    128     return (m_might_have_children == eLazyBoolNo ? false : true);
    129 }
    130 
    131 uint64_t
    132 ValueObjectSynthetic::GetByteSize()
    133 {
    134     return m_parent->GetByteSize();
    135 }
    136 
    137 lldb::ValueType
    138 ValueObjectSynthetic::GetValueType() const
    139 {
    140     return m_parent->GetValueType();
    141 }
    142 
    143 void
    144 ValueObjectSynthetic::CreateSynthFilter ()
    145 {
    146     m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
    147     if (!m_synth_filter_ap.get())
    148         m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
    149 }
    150 
    151 bool
    152 ValueObjectSynthetic::UpdateValue ()
    153 {
    154     SetValueIsValid (false);
    155     m_error.Clear();
    156 
    157     if (!m_parent->UpdateValueIfNeeded(false))
    158     {
    159         // our parent could not update.. as we are meaningless without a parent, just stop
    160         if (m_parent->GetError().Fail())
    161             m_error = m_parent->GetError();
    162         return false;
    163     }
    164 
    165     // regenerate the synthetic filter if our typename changes
    166     // <rdar://problem/12424824>
    167     ConstString new_parent_type_name = m_parent->GetTypeName();
    168     if (new_parent_type_name != m_parent_type_name)
    169     {
    170         m_parent_type_name = new_parent_type_name;
    171         CreateSynthFilter();
    172     }
    173 
    174     // let our backend do its update
    175     if (m_synth_filter_ap->Update() == false)
    176     {
    177         // filter said that cached values are stale
    178         m_children_byindex.clear();
    179         m_name_toindex.clear();
    180         // usually, an object's value can change but this does not alter its children count
    181         // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
    182         // that they need to come back to us asking for children
    183         m_children_count_valid = false;
    184         m_synthetic_children_count = UINT32_MAX;
    185         m_might_have_children = eLazyBoolCalculate;
    186     }
    187 
    188     CopyParentData();
    189 
    190     SetValueIsValid(true);
    191     return true;
    192 }
    193 
    194 lldb::ValueObjectSP
    195 ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
    196 {
    197     UpdateValueIfNeeded();
    198 
    199     ByIndexIterator iter = m_children_byindex.find(idx);
    200 
    201     if (iter == m_children_byindex.end())
    202     {
    203         if (can_create && m_synth_filter_ap.get() != NULL)
    204         {
    205             lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
    206             if (!synth_guy)
    207                 return synth_guy;
    208             m_children_byindex[idx]= synth_guy.get();
    209             return synth_guy;
    210         }
    211         else
    212             return lldb::ValueObjectSP();
    213     }
    214     else
    215         return iter->second->GetSP();
    216 }
    217 
    218 lldb::ValueObjectSP
    219 ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
    220 {
    221     UpdateValueIfNeeded();
    222 
    223     uint32_t index = GetIndexOfChildWithName(name);
    224 
    225     if (index == UINT32_MAX)
    226         return lldb::ValueObjectSP();
    227 
    228     return GetChildAtIndex(index, can_create);
    229 }
    230 
    231 size_t
    232 ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
    233 {
    234     UpdateValueIfNeeded();
    235 
    236     NameToIndexIterator iter = m_name_toindex.find(name.GetCString());
    237 
    238     if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL)
    239     {
    240         uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
    241         if (index == UINT32_MAX)
    242             return index;
    243         m_name_toindex[name.GetCString()] = index;
    244         return index;
    245     }
    246     else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL)
    247         return UINT32_MAX;
    248     else /*if (iter != m_name_toindex.end())*/
    249         return iter->second;
    250 }
    251 
    252 bool
    253 ValueObjectSynthetic::IsInScope ()
    254 {
    255     return m_parent->IsInScope();
    256 }
    257 
    258 lldb::ValueObjectSP
    259 ValueObjectSynthetic::GetNonSyntheticValue ()
    260 {
    261     return m_parent->GetSP();
    262 }
    263 
    264 void
    265 ValueObjectSynthetic::CopyParentData ()
    266 {
    267     m_value = m_parent->GetValue();
    268     ExecutionContext exe_ctx (GetExecutionContextRef());
    269     m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
    270 }
    271