15ffd83dbSDimitry Andric //===-- ValueObjectDynamicValue.cpp ---------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Core/ValueObjectDynamicValue.h"
100b57cec5SDimitry Andric #include "lldb/Core/Value.h"
110b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h"
120b57cec5SDimitry Andric #include "lldb/Symbol/CompilerType.h"
130b57cec5SDimitry Andric #include "lldb/Symbol/Type.h"
140b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
150b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
160b57cec5SDimitry Andric #include "lldb/Target/Process.h"
170b57cec5SDimitry Andric #include "lldb/Target/Target.h"
180b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Logging.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
230b57cec5SDimitry Andric #include "lldb/lldb-types.h"
240b57cec5SDimitry Andric 
25*5f7ddb14SDimitry Andric #include <cstring>
260b57cec5SDimitry Andric namespace lldb_private {
270b57cec5SDimitry Andric class Declaration;
280b57cec5SDimitry Andric }
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric using namespace lldb_private;
310b57cec5SDimitry Andric 
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)320b57cec5SDimitry Andric ValueObjectDynamicValue::ValueObjectDynamicValue(
330b57cec5SDimitry Andric     ValueObject &parent, lldb::DynamicValueType use_dynamic)
340b57cec5SDimitry Andric     : ValueObject(parent), m_address(), m_dynamic_type_info(),
350b57cec5SDimitry Andric       m_use_dynamic(use_dynamic) {
360b57cec5SDimitry Andric   SetName(parent.GetName());
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
~ValueObjectDynamicValue()390b57cec5SDimitry Andric ValueObjectDynamicValue::~ValueObjectDynamicValue() {
400b57cec5SDimitry Andric   m_owning_valobj_sp.reset();
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
GetCompilerTypeImpl()430b57cec5SDimitry Andric CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
440b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
450b57cec5SDimitry Andric   if (success) {
460b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
470b57cec5SDimitry Andric       return m_value.GetCompilerType();
480b57cec5SDimitry Andric     else
490b57cec5SDimitry Andric       return m_parent->GetCompilerType();
500b57cec5SDimitry Andric   }
510b57cec5SDimitry Andric   return m_parent->GetCompilerType();
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
GetTypeName()540b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetTypeName() {
550b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
560b57cec5SDimitry Andric   if (success) {
570b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
580b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric   return m_parent->GetTypeName();
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
GetTypeImpl()630b57cec5SDimitry Andric TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
640b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
650b57cec5SDimitry Andric   if (success && m_type_impl.IsValid()) {
660b57cec5SDimitry Andric     return m_type_impl;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric   return m_parent->GetTypeImpl();
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
GetQualifiedTypeName()710b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
720b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
730b57cec5SDimitry Andric   if (success) {
740b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
750b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric   return m_parent->GetQualifiedTypeName();
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
GetDisplayTypeName()800b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
810b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
820b57cec5SDimitry Andric   if (success) {
830b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
840b57cec5SDimitry Andric       return GetCompilerType().GetDisplayTypeName();
850b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
860b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
870b57cec5SDimitry Andric   }
880b57cec5SDimitry Andric   return m_parent->GetDisplayTypeName();
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
CalculateNumChildren(uint32_t max)910b57cec5SDimitry Andric size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
920b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
930b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
940b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
950b57cec5SDimitry Andric     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
960b57cec5SDimitry Andric     return children_count <= max ? children_count : max;
970b57cec5SDimitry Andric   } else
980b57cec5SDimitry Andric     return m_parent->GetNumChildren(max);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
GetByteSize()101af732203SDimitry Andric llvm::Optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
1020b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
1030b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
1040b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
1050b57cec5SDimitry Andric     return m_value.GetValueByteSize(nullptr, &exe_ctx);
1060b57cec5SDimitry Andric   } else
1070b57cec5SDimitry Andric     return m_parent->GetByteSize();
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
GetValueType() const1100b57cec5SDimitry Andric lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
1110b57cec5SDimitry Andric   return m_parent->GetValueType();
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
UpdateValue()1140b57cec5SDimitry Andric bool ValueObjectDynamicValue::UpdateValue() {
1150b57cec5SDimitry Andric   SetValueIsValid(false);
1160b57cec5SDimitry Andric   m_error.Clear();
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric   if (!m_parent->UpdateValueIfNeeded(false)) {
1190b57cec5SDimitry Andric     // The dynamic value failed to get an error, pass the error along
1200b57cec5SDimitry Andric     if (m_error.Success() && m_parent->GetError().Fail())
1210b57cec5SDimitry Andric       m_error = m_parent->GetError();
1220b57cec5SDimitry Andric     return false;
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // Setting our type_sp to NULL will route everything back through our parent
1260b57cec5SDimitry Andric   // which is equivalent to not using dynamic values.
1270b57cec5SDimitry Andric   if (m_use_dynamic == lldb::eNoDynamicValues) {
1280b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
1290b57cec5SDimitry Andric     return true;
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1330b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1340b57cec5SDimitry Andric   if (target) {
1350b57cec5SDimitry Andric     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
1360b57cec5SDimitry Andric     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // First make sure our Type and/or Address haven't changed:
1400b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1410b57cec5SDimitry Andric   if (!process)
1420b57cec5SDimitry Andric     return false;
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   TypeAndOrName class_type_or_name;
1450b57cec5SDimitry Andric   Address dynamic_address;
1460b57cec5SDimitry Andric   bool found_dynamic_type = false;
1470b57cec5SDimitry Andric   Value::ValueType value_type;
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   LanguageRuntime *runtime = nullptr;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
1520b57cec5SDimitry Andric   if (known_type != lldb::eLanguageTypeUnknown &&
1530b57cec5SDimitry Andric       known_type != lldb::eLanguageTypeC) {
1540b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(known_type);
1550b57cec5SDimitry Andric     if (runtime)
1560b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1570b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1580b57cec5SDimitry Andric           value_type);
1590b57cec5SDimitry Andric   } else {
1600b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
1610b57cec5SDimitry Andric     if (runtime)
1620b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1630b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1640b57cec5SDimitry Andric           value_type);
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     if (!found_dynamic_type) {
1670b57cec5SDimitry Andric       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1680b57cec5SDimitry Andric       if (runtime)
1690b57cec5SDimitry Andric         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1700b57cec5SDimitry Andric             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1710b57cec5SDimitry Andric             value_type);
1720b57cec5SDimitry Andric     }
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // Getting the dynamic value may have run the program a bit, and so marked us
1760b57cec5SDimitry Andric   // as needing updating, but we really don't...
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   m_update_point.SetUpdated();
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   if (runtime && found_dynamic_type) {
1810b57cec5SDimitry Andric     if (class_type_or_name.HasType()) {
1820b57cec5SDimitry Andric       m_type_impl =
1830b57cec5SDimitry Andric           TypeImpl(m_parent->GetCompilerType(),
1840b57cec5SDimitry Andric                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
1850b57cec5SDimitry Andric                        .GetCompilerType());
1860b57cec5SDimitry Andric     } else {
1870b57cec5SDimitry Andric       m_type_impl.Clear();
1880b57cec5SDimitry Andric     }
1890b57cec5SDimitry Andric   } else {
1900b57cec5SDimitry Andric     m_type_impl.Clear();
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // If we don't have a dynamic type, then make ourselves just a echo of our
1940b57cec5SDimitry Andric   // parent. Or we could return false, and make ourselves an echo of our
1950b57cec5SDimitry Andric   // parent?
1960b57cec5SDimitry Andric   if (!found_dynamic_type) {
1970b57cec5SDimitry Andric     if (m_dynamic_type_info)
1980b57cec5SDimitry Andric       SetValueDidChange(true);
1990b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2000b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
2010b57cec5SDimitry Andric     m_value = m_parent->GetValue();
2029dba64beSDimitry Andric     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
2030b57cec5SDimitry Andric     return m_error.Success();
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   Value old_value(m_value);
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   bool has_changed_type = false;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   if (!m_dynamic_type_info) {
2130b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2140b57cec5SDimitry Andric     has_changed_type = true;
2150b57cec5SDimitry Andric   } else if (class_type_or_name != m_dynamic_type_info) {
2160b57cec5SDimitry Andric     // We are another type, we need to tear down our children...
2170b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2180b57cec5SDimitry Andric     SetValueDidChange(true);
2190b57cec5SDimitry Andric     has_changed_type = true;
2200b57cec5SDimitry Andric   }
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (has_changed_type)
2230b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   if (!m_address.IsValid() || m_address != dynamic_address) {
2260b57cec5SDimitry Andric     if (m_address.IsValid())
2270b57cec5SDimitry Andric       SetValueDidChange(true);
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     // We've moved, so we should be fine...
2300b57cec5SDimitry Andric     m_address = dynamic_address;
2310b57cec5SDimitry Andric     lldb::TargetSP target_sp(GetTargetSP());
2320b57cec5SDimitry Andric     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
2330b57cec5SDimitry Andric     m_value.GetScalar() = load_address;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   if (runtime)
2370b57cec5SDimitry Andric     m_dynamic_type_info =
2380b57cec5SDimitry Andric         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   m_value.SetValueType(value_type);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (has_changed_type && log)
2459dba64beSDimitry Andric     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
2460b57cec5SDimitry Andric               static_cast<void *>(this), GetTypeName().GetCString());
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   if (m_address.IsValid() && m_dynamic_type_info) {
2490b57cec5SDimitry Andric     // The variable value is in the Scalar value inside the m_value. We can
2500b57cec5SDimitry Andric     // point our m_data right to it.
2519dba64beSDimitry Andric     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
2520b57cec5SDimitry Andric     if (m_error.Success()) {
2530b57cec5SDimitry Andric       if (!CanProvideValue()) {
2540b57cec5SDimitry Andric         // this value object represents an aggregate type whose children have
2550b57cec5SDimitry Andric         // values, but this object does not. So we say we are changed if our
2560b57cec5SDimitry Andric         // location has changed.
2570b57cec5SDimitry Andric         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
2580b57cec5SDimitry Andric                           m_value.GetScalar() != old_value.GetScalar());
2590b57cec5SDimitry Andric       }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric       SetValueIsValid(true);
2620b57cec5SDimitry Andric       return true;
2630b57cec5SDimitry Andric     }
2640b57cec5SDimitry Andric   }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   // We get here if we've failed above...
2670b57cec5SDimitry Andric   SetValueIsValid(false);
2680b57cec5SDimitry Andric   return false;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
IsInScope()2710b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
2720b57cec5SDimitry Andric 
SetValueFromCString(const char * value_str,Status & error)2730b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
2740b57cec5SDimitry Andric                                                   Status &error) {
2750b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
2760b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2770b57cec5SDimitry Andric     return false;
2780b57cec5SDimitry Andric   }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
2810b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
2840b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2850b57cec5SDimitry Andric     return false;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
2890b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
2900b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
2910b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
2920b57cec5SDimitry Andric   // parser instead of the value editing facility
2930b57cec5SDimitry Andric   if (my_value != parent_value) {
2940b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
2950b57cec5SDimitry Andric     if (strcmp(value_str, "0")) {
2960b57cec5SDimitry Andric       error.SetErrorString(
2970b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
2980b57cec5SDimitry Andric       return false;
2990b57cec5SDimitry Andric     }
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   bool ret_val = m_parent->SetValueFromCString(value_str, error);
3030b57cec5SDimitry Andric   SetNeedsUpdate();
3040b57cec5SDimitry Andric   return ret_val;
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
SetData(DataExtractor & data,Status & error)3070b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
3080b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
3090b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3100b57cec5SDimitry Andric     return false;
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
3140b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
3170b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3180b57cec5SDimitry Andric     return false;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
3220b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
3230b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
3240b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
3250b57cec5SDimitry Andric   // parser instead of the value editing facility
3260b57cec5SDimitry Andric   if (my_value != parent_value) {
3270b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
3280b57cec5SDimitry Andric     lldb::offset_t offset = 0;
3290b57cec5SDimitry Andric 
3305ffd83dbSDimitry Andric     if (data.GetAddress(&offset) != 0) {
3310b57cec5SDimitry Andric       error.SetErrorString(
3320b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
3330b57cec5SDimitry Andric       return false;
3340b57cec5SDimitry Andric     }
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   bool ret_val = m_parent->SetData(data, error);
3380b57cec5SDimitry Andric   SetNeedsUpdate();
3390b57cec5SDimitry Andric   return ret_val;
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
SetPreferredDisplayLanguage(lldb::LanguageType lang)3420b57cec5SDimitry Andric void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
3430b57cec5SDimitry Andric     lldb::LanguageType lang) {
3440b57cec5SDimitry Andric   this->ValueObject::SetPreferredDisplayLanguage(lang);
3450b57cec5SDimitry Andric   if (m_parent)
3460b57cec5SDimitry Andric     m_parent->SetPreferredDisplayLanguage(lang);
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
GetPreferredDisplayLanguage()3490b57cec5SDimitry Andric lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
3500b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
3510b57cec5SDimitry Andric     if (m_parent)
3520b57cec5SDimitry Andric       return m_parent->GetPreferredDisplayLanguage();
3530b57cec5SDimitry Andric     return lldb::eLanguageTypeUnknown;
3540b57cec5SDimitry Andric   } else
3550b57cec5SDimitry Andric     return m_preferred_display_language;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
IsSyntheticChildrenGenerated()3580b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
3590b57cec5SDimitry Andric   if (m_parent)
3600b57cec5SDimitry Andric     return m_parent->IsSyntheticChildrenGenerated();
3610b57cec5SDimitry Andric   return false;
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
SetSyntheticChildrenGenerated(bool b)3640b57cec5SDimitry Andric void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
3650b57cec5SDimitry Andric   if (m_parent)
3660b57cec5SDimitry Andric     m_parent->SetSyntheticChildrenGenerated(b);
3670b57cec5SDimitry Andric   this->ValueObject::SetSyntheticChildrenGenerated(b);
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
GetDeclaration(Declaration & decl)3700b57cec5SDimitry Andric bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
3710b57cec5SDimitry Andric   if (m_parent)
3720b57cec5SDimitry Andric     return m_parent->GetDeclaration(decl);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   return ValueObject::GetDeclaration(decl);
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
GetLanguageFlags()3770b57cec5SDimitry Andric uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
3780b57cec5SDimitry Andric   if (m_parent)
3790b57cec5SDimitry Andric     return m_parent->GetLanguageFlags();
3800b57cec5SDimitry Andric   return this->ValueObject::GetLanguageFlags();
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
SetLanguageFlags(uint64_t flags)3830b57cec5SDimitry Andric void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
3840b57cec5SDimitry Andric   if (m_parent)
3850b57cec5SDimitry Andric     m_parent->SetLanguageFlags(flags);
3860b57cec5SDimitry Andric   else
3870b57cec5SDimitry Andric     this->ValueObject::SetLanguageFlags(flags);
3880b57cec5SDimitry Andric }
389