xref: /src/contrib/llvm-project/lldb/source/Core/ValueObjectDynamicValue.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- ValueObjectDynamicValue.cpp ---------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f034231aSEd Maste #include "lldb/Core/ValueObjectDynamicValue.h"
10f034231aSEd Maste #include "lldb/Core/Value.h"
11f034231aSEd Maste #include "lldb/Core/ValueObject.h"
12e81d9d49SDimitry Andric #include "lldb/Symbol/CompilerType.h"
13f034231aSEd Maste #include "lldb/Symbol/Type.h"
14f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
15f034231aSEd Maste #include "lldb/Target/LanguageRuntime.h"
16f034231aSEd Maste #include "lldb/Target/Process.h"
17f034231aSEd Maste #include "lldb/Target/Target.h"
1894994d37SDimitry Andric #include "lldb/Utility/DataExtractor.h"
19145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
2074a628f7SDimitry Andric #include "lldb/Utility/Log.h"
2194994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
2294994d37SDimitry Andric #include "lldb/Utility/Status.h"
2394994d37SDimitry Andric #include "lldb/lldb-types.h"
2474a628f7SDimitry Andric 
25344a3780SDimitry Andric #include <cstring>
26e3b55780SDimitry Andric #include <optional>
2774a628f7SDimitry Andric namespace lldb_private {
2874a628f7SDimitry Andric class Declaration;
2974a628f7SDimitry Andric }
30f034231aSEd Maste 
31f034231aSEd Maste using namespace lldb_private;
32f034231aSEd Maste 
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)3314f1b3e8SDimitry Andric ValueObjectDynamicValue::ValueObjectDynamicValue(
3414f1b3e8SDimitry Andric     ValueObject &parent, lldb::DynamicValueType use_dynamic)
3514f1b3e8SDimitry Andric     : ValueObject(parent), m_address(), m_dynamic_type_info(),
3614f1b3e8SDimitry Andric       m_use_dynamic(use_dynamic) {
37f034231aSEd Maste   SetName(parent.GetName());
38f034231aSEd Maste }
39f034231aSEd Maste 
GetCompilerTypeImpl()4014f1b3e8SDimitry Andric CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
41f21a844fSEd Maste   const bool success = UpdateValueIfNeeded(false);
4214f1b3e8SDimitry Andric   if (success) {
43f21a844fSEd Maste     if (m_dynamic_type_info.HasType())
44e81d9d49SDimitry Andric       return m_value.GetCompilerType();
45f034231aSEd Maste     else
46e81d9d49SDimitry Andric       return m_parent->GetCompilerType();
47f034231aSEd Maste   }
48e81d9d49SDimitry Andric   return m_parent->GetCompilerType();
49f21a844fSEd Maste }
50f034231aSEd Maste 
GetTypeName()5114f1b3e8SDimitry Andric ConstString ValueObjectDynamicValue::GetTypeName() {
52f034231aSEd Maste   const bool success = UpdateValueIfNeeded(false);
5314f1b3e8SDimitry Andric   if (success) {
54f034231aSEd Maste     if (m_dynamic_type_info.HasName())
55f034231aSEd Maste       return m_dynamic_type_info.GetName();
56f034231aSEd Maste   }
57f034231aSEd Maste   return m_parent->GetTypeName();
58f034231aSEd Maste }
59f034231aSEd Maste 
GetTypeImpl()6014f1b3e8SDimitry Andric TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
61f21a844fSEd Maste   const bool success = UpdateValueIfNeeded(false);
6214f1b3e8SDimitry Andric   if (success && m_type_impl.IsValid()) {
63f21a844fSEd Maste     return m_type_impl;
64f21a844fSEd Maste   }
65f21a844fSEd Maste   return m_parent->GetTypeImpl();
66f21a844fSEd Maste }
67f21a844fSEd Maste 
GetQualifiedTypeName()6814f1b3e8SDimitry Andric ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
69f034231aSEd Maste   const bool success = UpdateValueIfNeeded(false);
7014f1b3e8SDimitry Andric   if (success) {
71f034231aSEd Maste     if (m_dynamic_type_info.HasName())
72f034231aSEd Maste       return m_dynamic_type_info.GetName();
73f034231aSEd Maste   }
740cac4ca3SEd Maste   return m_parent->GetQualifiedTypeName();
750cac4ca3SEd Maste }
760cac4ca3SEd Maste 
GetDisplayTypeName()7714f1b3e8SDimitry Andric ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
780cac4ca3SEd Maste   const bool success = UpdateValueIfNeeded(false);
7914f1b3e8SDimitry Andric   if (success) {
800cac4ca3SEd Maste     if (m_dynamic_type_info.HasType())
81e81d9d49SDimitry Andric       return GetCompilerType().GetDisplayTypeName();
820cac4ca3SEd Maste     if (m_dynamic_type_info.HasName())
830cac4ca3SEd Maste       return m_dynamic_type_info.GetName();
840cac4ca3SEd Maste   }
850cac4ca3SEd Maste   return m_parent->GetDisplayTypeName();
86f034231aSEd Maste }
87f034231aSEd Maste 
88ac9a064cSDimitry Andric llvm::Expected<uint32_t>
CalculateNumChildren(uint32_t max)89ac9a064cSDimitry Andric ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
90f034231aSEd Maste   const bool success = UpdateValueIfNeeded(false);
9114f1b3e8SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
9294994d37SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
9394994d37SDimitry Andric     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
94ac9a064cSDimitry Andric     if (!children_count)
95ac9a064cSDimitry Andric       return children_count;
96ac9a064cSDimitry Andric     return *children_count <= max ? *children_count : max;
9714f1b3e8SDimitry Andric   } else
98e81d9d49SDimitry Andric     return m_parent->GetNumChildren(max);
99f034231aSEd Maste }
100f034231aSEd Maste 
GetByteSize()101e3b55780SDimitry Andric std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
102f034231aSEd Maste   const bool success = UpdateValueIfNeeded(false);
10314f1b3e8SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
104e81d9d49SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
105e81d9d49SDimitry Andric     return m_value.GetValueByteSize(nullptr, &exe_ctx);
10614f1b3e8SDimitry Andric   } else
107f034231aSEd Maste     return m_parent->GetByteSize();
108f034231aSEd Maste }
109f034231aSEd Maste 
GetValueType() const11014f1b3e8SDimitry Andric lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
111f034231aSEd Maste   return m_parent->GetValueType();
112f034231aSEd Maste }
113f034231aSEd Maste 
UpdateValue()11414f1b3e8SDimitry Andric bool ValueObjectDynamicValue::UpdateValue() {
115f034231aSEd Maste   SetValueIsValid(false);
116f034231aSEd Maste   m_error.Clear();
117f034231aSEd Maste 
11814f1b3e8SDimitry Andric   if (!m_parent->UpdateValueIfNeeded(false)) {
119f034231aSEd Maste     // The dynamic value failed to get an error, pass the error along
120f034231aSEd Maste     if (m_error.Success() && m_parent->GetError().Fail())
121f034231aSEd Maste       m_error = m_parent->GetError();
122f034231aSEd Maste     return false;
123f034231aSEd Maste   }
124f034231aSEd Maste 
125f73363f1SDimitry Andric   // Setting our type_sp to NULL will route everything back through our parent
126f73363f1SDimitry Andric   // which is equivalent to not using dynamic values.
12714f1b3e8SDimitry Andric   if (m_use_dynamic == lldb::eNoDynamicValues) {
128f034231aSEd Maste     m_dynamic_type_info.Clear();
129f034231aSEd Maste     return true;
130f034231aSEd Maste   }
131f034231aSEd Maste 
132f034231aSEd Maste   ExecutionContext exe_ctx(GetExecutionContextRef());
133f034231aSEd Maste   Target *target = exe_ctx.GetTargetPtr();
13414f1b3e8SDimitry Andric   if (target) {
135f034231aSEd Maste     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
136f034231aSEd Maste     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
137f034231aSEd Maste   }
138f034231aSEd Maste 
139f034231aSEd Maste   // First make sure our Type and/or Address haven't changed:
140f034231aSEd Maste   Process *process = exe_ctx.GetProcessPtr();
141f034231aSEd Maste   if (!process)
142f034231aSEd Maste     return false;
143f034231aSEd Maste 
144f034231aSEd Maste   TypeAndOrName class_type_or_name;
145f034231aSEd Maste   Address dynamic_address;
146f034231aSEd Maste   bool found_dynamic_type = false;
147e81d9d49SDimitry Andric   Value::ValueType value_type;
148e81d9d49SDimitry Andric 
149e81d9d49SDimitry Andric   LanguageRuntime *runtime = nullptr;
150f034231aSEd Maste 
151f034231aSEd Maste   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
15214f1b3e8SDimitry Andric   if (known_type != lldb::eLanguageTypeUnknown &&
15314f1b3e8SDimitry Andric       known_type != lldb::eLanguageTypeC) {
154e81d9d49SDimitry Andric     runtime = process->GetLanguageRuntime(known_type);
1557fa27ce4SDimitry Andric     if (auto *preferred_runtime =
1567fa27ce4SDimitry Andric             runtime->GetPreferredLanguageRuntime(*m_parent)) {
1577fa27ce4SDimitry Andric       // Try the preferred runtime first.
1587fa27ce4SDimitry Andric       found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress(
1597fa27ce4SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1607fa27ce4SDimitry Andric           value_type);
1617fa27ce4SDimitry Andric       if (found_dynamic_type)
1627fa27ce4SDimitry Andric         // Set the operative `runtime` for later use in this function.
1637fa27ce4SDimitry Andric         runtime = preferred_runtime;
1647fa27ce4SDimitry Andric     }
1657fa27ce4SDimitry Andric     if (!found_dynamic_type)
1667fa27ce4SDimitry Andric       // Fallback to the runtime for `known_type`.
16714f1b3e8SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
16814f1b3e8SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
16914f1b3e8SDimitry Andric           value_type);
17014f1b3e8SDimitry Andric   } else {
171e81d9d49SDimitry Andric     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
172e81d9d49SDimitry Andric     if (runtime)
17314f1b3e8SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
17414f1b3e8SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
17514f1b3e8SDimitry Andric           value_type);
176f034231aSEd Maste 
17714f1b3e8SDimitry Andric     if (!found_dynamic_type) {
178e81d9d49SDimitry Andric       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
179e81d9d49SDimitry Andric       if (runtime)
18014f1b3e8SDimitry Andric         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
18114f1b3e8SDimitry Andric             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
18214f1b3e8SDimitry Andric             value_type);
183f034231aSEd Maste     }
184f034231aSEd Maste   }
185f034231aSEd Maste 
18614f1b3e8SDimitry Andric   // Getting the dynamic value may have run the program a bit, and so marked us
187f73363f1SDimitry Andric   // as needing updating, but we really don't...
188f034231aSEd Maste 
189f034231aSEd Maste   m_update_point.SetUpdated();
190f034231aSEd Maste 
19114f1b3e8SDimitry Andric   if (runtime && found_dynamic_type) {
19214f1b3e8SDimitry Andric     if (class_type_or_name.HasType()) {
19314f1b3e8SDimitry Andric       m_type_impl =
19414f1b3e8SDimitry Andric           TypeImpl(m_parent->GetCompilerType(),
19514f1b3e8SDimitry Andric                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
19614f1b3e8SDimitry Andric                        .GetCompilerType());
19714f1b3e8SDimitry Andric     } else {
198f21a844fSEd Maste       m_type_impl.Clear();
199f21a844fSEd Maste     }
20014f1b3e8SDimitry Andric   } else {
201f21a844fSEd Maste     m_type_impl.Clear();
202f21a844fSEd Maste   }
203f21a844fSEd Maste 
2047fa27ce4SDimitry Andric   // If we don't have a dynamic type, set ourselves to be invalid and return
2057fa27ce4SDimitry Andric   // false.  We used to try to produce a dynamic ValueObject that behaved "like"
2067fa27ce4SDimitry Andric   // its parent, but that failed for ValueObjectConstResult, which is too
2077fa27ce4SDimitry Andric   // complex a beast to try to emulate.  If we return an invalid ValueObject,
2087fa27ce4SDimitry Andric   // clients will end up getting the static value instead, which behaves
2097fa27ce4SDimitry Andric   // correctly.
21014f1b3e8SDimitry Andric   if (!found_dynamic_type) {
211f034231aSEd Maste     if (m_dynamic_type_info)
212f034231aSEd Maste       SetValueDidChange(true);
213f034231aSEd Maste     ClearDynamicTypeInformation();
214f034231aSEd Maste     m_dynamic_type_info.Clear();
2157fa27ce4SDimitry Andric     m_error.SetErrorString("no dynamic type found");
2167fa27ce4SDimitry Andric     return false;
217f034231aSEd Maste   }
218f034231aSEd Maste 
219f034231aSEd Maste   Value old_value(m_value);
220f034231aSEd Maste 
221145449b1SDimitry Andric   Log *log = GetLog(LLDBLog::Types);
222f034231aSEd Maste 
223f034231aSEd Maste   bool has_changed_type = false;
224f034231aSEd Maste 
22514f1b3e8SDimitry Andric   if (!m_dynamic_type_info) {
226f034231aSEd Maste     m_dynamic_type_info = class_type_or_name;
227f034231aSEd Maste     has_changed_type = true;
22814f1b3e8SDimitry Andric   } else if (class_type_or_name != m_dynamic_type_info) {
229f034231aSEd Maste     // We are another type, we need to tear down our children...
230f034231aSEd Maste     m_dynamic_type_info = class_type_or_name;
231f034231aSEd Maste     SetValueDidChange(true);
232f034231aSEd Maste     has_changed_type = true;
233f034231aSEd Maste   }
234f034231aSEd Maste 
235f034231aSEd Maste   if (has_changed_type)
236f034231aSEd Maste     ClearDynamicTypeInformation();
237f034231aSEd Maste 
23814f1b3e8SDimitry Andric   if (!m_address.IsValid() || m_address != dynamic_address) {
239f034231aSEd Maste     if (m_address.IsValid())
240f034231aSEd Maste       SetValueDidChange(true);
241f034231aSEd Maste 
242f034231aSEd Maste     // We've moved, so we should be fine...
243f034231aSEd Maste     m_address = dynamic_address;
244f034231aSEd Maste     lldb::TargetSP target_sp(GetTargetSP());
245f034231aSEd Maste     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
246f034231aSEd Maste     m_value.GetScalar() = load_address;
247f034231aSEd Maste   }
248f034231aSEd Maste 
249e81d9d49SDimitry Andric   if (runtime)
25014f1b3e8SDimitry Andric     m_dynamic_type_info =
25114f1b3e8SDimitry Andric         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
252f034231aSEd Maste 
253e81d9d49SDimitry Andric   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
254f034231aSEd Maste 
255e81d9d49SDimitry Andric   m_value.SetValueType(value_type);
256f034231aSEd Maste 
257f034231aSEd Maste   if (has_changed_type && log)
258ead24645SDimitry Andric     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
2590cac4ca3SEd Maste               static_cast<void *>(this), GetTypeName().GetCString());
260f034231aSEd Maste 
26114f1b3e8SDimitry Andric   if (m_address.IsValid() && m_dynamic_type_info) {
262f73363f1SDimitry Andric     // The variable value is in the Scalar value inside the m_value. We can
263f73363f1SDimitry Andric     // point our m_data right to it.
264ead24645SDimitry Andric     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
26514f1b3e8SDimitry Andric     if (m_error.Success()) {
26614f1b3e8SDimitry Andric       if (!CanProvideValue()) {
267f73363f1SDimitry Andric         // this value object represents an aggregate type whose children have
268f73363f1SDimitry Andric         // values, but this object does not. So we say we are changed if our
269f73363f1SDimitry Andric         // location has changed.
27014f1b3e8SDimitry Andric         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
27114f1b3e8SDimitry Andric                           m_value.GetScalar() != old_value.GetScalar());
272f034231aSEd Maste       }
273f034231aSEd Maste 
274f034231aSEd Maste       SetValueIsValid(true);
275f034231aSEd Maste       return true;
276f034231aSEd Maste     }
277f034231aSEd Maste   }
278f034231aSEd Maste 
279f034231aSEd Maste   // We get here if we've failed above...
280f034231aSEd Maste   SetValueIsValid(false);
281f034231aSEd Maste   return false;
282f034231aSEd Maste }
283f034231aSEd Maste 
IsInScope()28414f1b3e8SDimitry Andric bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
285f034231aSEd Maste 
SetValueFromCString(const char * value_str,Status & error)28614f1b3e8SDimitry Andric bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
287b76161e4SDimitry Andric                                                   Status &error) {
28814f1b3e8SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
289f034231aSEd Maste     error.SetErrorString("unable to read value");
290f034231aSEd Maste     return false;
291f034231aSEd Maste   }
292f034231aSEd Maste 
293f034231aSEd Maste   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
294f034231aSEd Maste   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
295f034231aSEd Maste 
29614f1b3e8SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
297f034231aSEd Maste     error.SetErrorString("unable to read value");
298f034231aSEd Maste     return false;
299f034231aSEd Maste   }
300f034231aSEd Maste 
301f73363f1SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
302f73363f1SDimitry Andric   // correctly we would need to change the new value so that it refers to the
303f73363f1SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
304f73363f1SDimitry Andric   // than a value overwrite is required, you should be using the expression
305f73363f1SDimitry Andric   // parser instead of the value editing facility
30614f1b3e8SDimitry Andric   if (my_value != parent_value) {
307f034231aSEd Maste     // but NULL'ing out a value should always be allowed
30814f1b3e8SDimitry Andric     if (strcmp(value_str, "0")) {
30914f1b3e8SDimitry Andric       error.SetErrorString(
31014f1b3e8SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
311f034231aSEd Maste       return false;
312f034231aSEd Maste     }
313f034231aSEd Maste   }
314f034231aSEd Maste 
315f034231aSEd Maste   bool ret_val = m_parent->SetValueFromCString(value_str, error);
316f034231aSEd Maste   SetNeedsUpdate();
317f034231aSEd Maste   return ret_val;
318f034231aSEd Maste }
319f034231aSEd Maste 
SetData(DataExtractor & data,Status & error)320b76161e4SDimitry Andric bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
32114f1b3e8SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
322f034231aSEd Maste     error.SetErrorString("unable to read value");
323f034231aSEd Maste     return false;
324f034231aSEd Maste   }
325f034231aSEd Maste 
326f034231aSEd Maste   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
327f034231aSEd Maste   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
328f034231aSEd Maste 
32914f1b3e8SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
330f034231aSEd Maste     error.SetErrorString("unable to read value");
331f034231aSEd Maste     return false;
332f034231aSEd Maste   }
333f034231aSEd Maste 
334f73363f1SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
335f73363f1SDimitry Andric   // correctly we would need to change the new value so that it refers to the
336f73363f1SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
337f73363f1SDimitry Andric   // than a value overwrite is required, you should be using the expression
338f73363f1SDimitry Andric   // parser instead of the value editing facility
33914f1b3e8SDimitry Andric   if (my_value != parent_value) {
340f034231aSEd Maste     // but NULL'ing out a value should always be allowed
341f034231aSEd Maste     lldb::offset_t offset = 0;
342f034231aSEd Maste 
343cfca06d7SDimitry Andric     if (data.GetAddress(&offset) != 0) {
34414f1b3e8SDimitry Andric       error.SetErrorString(
34514f1b3e8SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
346f034231aSEd Maste       return false;
347f034231aSEd Maste     }
348f034231aSEd Maste   }
349f034231aSEd Maste 
350f034231aSEd Maste   bool ret_val = m_parent->SetData(data, error);
351f034231aSEd Maste   SetNeedsUpdate();
352f034231aSEd Maste   return ret_val;
353f034231aSEd Maste }
354e81d9d49SDimitry Andric 
SetPreferredDisplayLanguage(lldb::LanguageType lang)35514f1b3e8SDimitry Andric void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
35614f1b3e8SDimitry Andric     lldb::LanguageType lang) {
357e81d9d49SDimitry Andric   this->ValueObject::SetPreferredDisplayLanguage(lang);
358e81d9d49SDimitry Andric   if (m_parent)
359e81d9d49SDimitry Andric     m_parent->SetPreferredDisplayLanguage(lang);
360e81d9d49SDimitry Andric }
361e81d9d49SDimitry Andric 
GetPreferredDisplayLanguage()36214f1b3e8SDimitry Andric lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
36314f1b3e8SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
364e81d9d49SDimitry Andric     if (m_parent)
365e81d9d49SDimitry Andric       return m_parent->GetPreferredDisplayLanguage();
366e81d9d49SDimitry Andric     return lldb::eLanguageTypeUnknown;
36714f1b3e8SDimitry Andric   } else
368e81d9d49SDimitry Andric     return m_preferred_display_language;
369e81d9d49SDimitry Andric }
370e81d9d49SDimitry Andric 
IsSyntheticChildrenGenerated()37114f1b3e8SDimitry Andric bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
372f3fbd1c0SDimitry Andric   if (m_parent)
373f3fbd1c0SDimitry Andric     return m_parent->IsSyntheticChildrenGenerated();
374f3fbd1c0SDimitry Andric   return false;
375f3fbd1c0SDimitry Andric }
376f3fbd1c0SDimitry Andric 
SetSyntheticChildrenGenerated(bool b)37714f1b3e8SDimitry Andric void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
378f3fbd1c0SDimitry Andric   if (m_parent)
379f3fbd1c0SDimitry Andric     m_parent->SetSyntheticChildrenGenerated(b);
380f3fbd1c0SDimitry Andric   this->ValueObject::SetSyntheticChildrenGenerated(b);
381f3fbd1c0SDimitry Andric }
382f3fbd1c0SDimitry Andric 
GetDeclaration(Declaration & decl)38314f1b3e8SDimitry Andric bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
384e81d9d49SDimitry Andric   if (m_parent)
385e81d9d49SDimitry Andric     return m_parent->GetDeclaration(decl);
386e81d9d49SDimitry Andric 
387e81d9d49SDimitry Andric   return ValueObject::GetDeclaration(decl);
388e81d9d49SDimitry Andric }
389e81d9d49SDimitry Andric 
GetLanguageFlags()39014f1b3e8SDimitry Andric uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
391e81d9d49SDimitry Andric   if (m_parent)
392e81d9d49SDimitry Andric     return m_parent->GetLanguageFlags();
393e81d9d49SDimitry Andric   return this->ValueObject::GetLanguageFlags();
394e81d9d49SDimitry Andric }
395e81d9d49SDimitry Andric 
SetLanguageFlags(uint64_t flags)39614f1b3e8SDimitry Andric void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
397e81d9d49SDimitry Andric   if (m_parent)
398e81d9d49SDimitry Andric     m_parent->SetLanguageFlags(flags);
399e81d9d49SDimitry Andric   else
400e81d9d49SDimitry Andric     this->ValueObject::SetLanguageFlags(flags);
401e81d9d49SDimitry Andric }
402