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"
1981ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
200b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
210b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
230b57cec5SDimitry Andric #include "lldb/lldb-types.h"
240b57cec5SDimitry Andric 
25fe6060f1SDimitry Andric #include <cstring>
26bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric namespace lldb_private {
280b57cec5SDimitry Andric class Declaration;
290b57cec5SDimitry Andric }
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace lldb_private;
320b57cec5SDimitry Andric 
ValueObjectDynamicValue(ValueObject & parent,lldb::DynamicValueType use_dynamic)330b57cec5SDimitry Andric ValueObjectDynamicValue::ValueObjectDynamicValue(
340b57cec5SDimitry Andric     ValueObject &parent, lldb::DynamicValueType use_dynamic)
350b57cec5SDimitry Andric     : ValueObject(parent), m_address(), m_dynamic_type_info(),
360b57cec5SDimitry Andric       m_use_dynamic(use_dynamic) {
370b57cec5SDimitry Andric   SetName(parent.GetName());
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
GetCompilerTypeImpl()400b57cec5SDimitry Andric CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() {
410b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
420b57cec5SDimitry Andric   if (success) {
430b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
440b57cec5SDimitry Andric       return m_value.GetCompilerType();
450b57cec5SDimitry Andric     else
460b57cec5SDimitry Andric       return m_parent->GetCompilerType();
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric   return m_parent->GetCompilerType();
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
GetTypeName()510b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetTypeName() {
520b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
530b57cec5SDimitry Andric   if (success) {
540b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
550b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
560b57cec5SDimitry Andric   }
570b57cec5SDimitry Andric   return m_parent->GetTypeName();
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
GetTypeImpl()600b57cec5SDimitry Andric TypeImpl ValueObjectDynamicValue::GetTypeImpl() {
610b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
620b57cec5SDimitry Andric   if (success && m_type_impl.IsValid()) {
630b57cec5SDimitry Andric     return m_type_impl;
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric   return m_parent->GetTypeImpl();
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
GetQualifiedTypeName()680b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetQualifiedTypeName() {
690b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
700b57cec5SDimitry Andric   if (success) {
710b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
720b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric   return m_parent->GetQualifiedTypeName();
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
GetDisplayTypeName()770b57cec5SDimitry Andric ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
780b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
790b57cec5SDimitry Andric   if (success) {
800b57cec5SDimitry Andric     if (m_dynamic_type_info.HasType())
810b57cec5SDimitry Andric       return GetCompilerType().GetDisplayTypeName();
820b57cec5SDimitry Andric     if (m_dynamic_type_info.HasName())
830b57cec5SDimitry Andric       return m_dynamic_type_info.GetName();
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric   return m_parent->GetDisplayTypeName();
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
CalculateNumChildren(uint32_t max)880b57cec5SDimitry Andric size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
890b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
900b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
910b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
920b57cec5SDimitry Andric     auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
930b57cec5SDimitry Andric     return children_count <= max ? children_count : max;
940b57cec5SDimitry Andric   } else
950b57cec5SDimitry Andric     return m_parent->GetNumChildren(max);
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
GetByteSize()98bdd1243dSDimitry Andric std::optional<uint64_t> ValueObjectDynamicValue::GetByteSize() {
990b57cec5SDimitry Andric   const bool success = UpdateValueIfNeeded(false);
1000b57cec5SDimitry Andric   if (success && m_dynamic_type_info.HasType()) {
1010b57cec5SDimitry Andric     ExecutionContext exe_ctx(GetExecutionContextRef());
1020b57cec5SDimitry Andric     return m_value.GetValueByteSize(nullptr, &exe_ctx);
1030b57cec5SDimitry Andric   } else
1040b57cec5SDimitry Andric     return m_parent->GetByteSize();
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
GetValueType() const1070b57cec5SDimitry Andric lldb::ValueType ValueObjectDynamicValue::GetValueType() const {
1080b57cec5SDimitry Andric   return m_parent->GetValueType();
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
UpdateValue()1110b57cec5SDimitry Andric bool ValueObjectDynamicValue::UpdateValue() {
1120b57cec5SDimitry Andric   SetValueIsValid(false);
1130b57cec5SDimitry Andric   m_error.Clear();
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   if (!m_parent->UpdateValueIfNeeded(false)) {
1160b57cec5SDimitry Andric     // The dynamic value failed to get an error, pass the error along
1170b57cec5SDimitry Andric     if (m_error.Success() && m_parent->GetError().Fail())
1180b57cec5SDimitry Andric       m_error = m_parent->GetError();
1190b57cec5SDimitry Andric     return false;
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // Setting our type_sp to NULL will route everything back through our parent
1230b57cec5SDimitry Andric   // which is equivalent to not using dynamic values.
1240b57cec5SDimitry Andric   if (m_use_dynamic == lldb::eNoDynamicValues) {
1250b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
1260b57cec5SDimitry Andric     return true;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetExecutionContextRef());
1300b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1310b57cec5SDimitry Andric   if (target) {
1320b57cec5SDimitry Andric     m_data.SetByteOrder(target->GetArchitecture().GetByteOrder());
1330b57cec5SDimitry Andric     m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // First make sure our Type and/or Address haven't changed:
1370b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1380b57cec5SDimitry Andric   if (!process)
1390b57cec5SDimitry Andric     return false;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   TypeAndOrName class_type_or_name;
1420b57cec5SDimitry Andric   Address dynamic_address;
1430b57cec5SDimitry Andric   bool found_dynamic_type = false;
1440b57cec5SDimitry Andric   Value::ValueType value_type;
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   LanguageRuntime *runtime = nullptr;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage();
1490b57cec5SDimitry Andric   if (known_type != lldb::eLanguageTypeUnknown &&
1500b57cec5SDimitry Andric       known_type != lldb::eLanguageTypeC) {
1510b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(known_type);
152*fe013be4SDimitry Andric     if (auto *preferred_runtime =
153*fe013be4SDimitry Andric             runtime->GetPreferredLanguageRuntime(*m_parent)) {
154*fe013be4SDimitry Andric       // Try the preferred runtime first.
155*fe013be4SDimitry Andric       found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress(
156*fe013be4SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
157*fe013be4SDimitry Andric           value_type);
158*fe013be4SDimitry Andric       if (found_dynamic_type)
159*fe013be4SDimitry Andric         // Set the operative `runtime` for later use in this function.
160*fe013be4SDimitry Andric         runtime = preferred_runtime;
161*fe013be4SDimitry Andric     }
162*fe013be4SDimitry Andric     if (!found_dynamic_type)
163*fe013be4SDimitry Andric       // Fallback to the runtime for `known_type`.
1640b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1650b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1660b57cec5SDimitry Andric           value_type);
1670b57cec5SDimitry Andric   } else {
1680b57cec5SDimitry Andric     runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus);
1690b57cec5SDimitry Andric     if (runtime)
1700b57cec5SDimitry Andric       found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1710b57cec5SDimitry Andric           *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1720b57cec5SDimitry Andric           value_type);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     if (!found_dynamic_type) {
1750b57cec5SDimitry Andric       runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC);
1760b57cec5SDimitry Andric       if (runtime)
1770b57cec5SDimitry Andric         found_dynamic_type = runtime->GetDynamicTypeAndAddress(
1780b57cec5SDimitry Andric             *m_parent, m_use_dynamic, class_type_or_name, dynamic_address,
1790b57cec5SDimitry Andric             value_type);
1800b57cec5SDimitry Andric     }
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   // Getting the dynamic value may have run the program a bit, and so marked us
1840b57cec5SDimitry Andric   // as needing updating, but we really don't...
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   m_update_point.SetUpdated();
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   if (runtime && found_dynamic_type) {
1890b57cec5SDimitry Andric     if (class_type_or_name.HasType()) {
1900b57cec5SDimitry Andric       m_type_impl =
1910b57cec5SDimitry Andric           TypeImpl(m_parent->GetCompilerType(),
1920b57cec5SDimitry Andric                    runtime->FixUpDynamicType(class_type_or_name, *m_parent)
1930b57cec5SDimitry Andric                        .GetCompilerType());
1940b57cec5SDimitry Andric     } else {
1950b57cec5SDimitry Andric       m_type_impl.Clear();
1960b57cec5SDimitry Andric     }
1970b57cec5SDimitry Andric   } else {
1980b57cec5SDimitry Andric     m_type_impl.Clear();
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric 
201*fe013be4SDimitry Andric   // If we don't have a dynamic type, set ourselves to be invalid and return
202*fe013be4SDimitry Andric   // false.  We used to try to produce a dynamic ValueObject that behaved "like"
203*fe013be4SDimitry Andric   // its parent, but that failed for ValueObjectConstResult, which is too
204*fe013be4SDimitry Andric   // complex a beast to try to emulate.  If we return an invalid ValueObject,
205*fe013be4SDimitry Andric   // clients will end up getting the static value instead, which behaves
206*fe013be4SDimitry Andric   // correctly.
2070b57cec5SDimitry Andric   if (!found_dynamic_type) {
2080b57cec5SDimitry Andric     if (m_dynamic_type_info)
2090b57cec5SDimitry Andric       SetValueDidChange(true);
2100b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2110b57cec5SDimitry Andric     m_dynamic_type_info.Clear();
212*fe013be4SDimitry Andric     m_error.SetErrorString("no dynamic type found");
213*fe013be4SDimitry Andric     return false;
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   Value old_value(m_value);
2170b57cec5SDimitry Andric 
21881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Types);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   bool has_changed_type = false;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (!m_dynamic_type_info) {
2230b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2240b57cec5SDimitry Andric     has_changed_type = true;
2250b57cec5SDimitry Andric   } else if (class_type_or_name != m_dynamic_type_info) {
2260b57cec5SDimitry Andric     // We are another type, we need to tear down our children...
2270b57cec5SDimitry Andric     m_dynamic_type_info = class_type_or_name;
2280b57cec5SDimitry Andric     SetValueDidChange(true);
2290b57cec5SDimitry Andric     has_changed_type = true;
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   if (has_changed_type)
2330b57cec5SDimitry Andric     ClearDynamicTypeInformation();
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   if (!m_address.IsValid() || m_address != dynamic_address) {
2360b57cec5SDimitry Andric     if (m_address.IsValid())
2370b57cec5SDimitry Andric       SetValueDidChange(true);
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     // We've moved, so we should be fine...
2400b57cec5SDimitry Andric     m_address = dynamic_address;
2410b57cec5SDimitry Andric     lldb::TargetSP target_sp(GetTargetSP());
2420b57cec5SDimitry Andric     lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get());
2430b57cec5SDimitry Andric     m_value.GetScalar() = load_address;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   if (runtime)
2470b57cec5SDimitry Andric     m_dynamic_type_info =
2480b57cec5SDimitry Andric         runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent);
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType());
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric   m_value.SetValueType(value_type);
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   if (has_changed_type && log)
2559dba64beSDimitry Andric     LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(),
2560b57cec5SDimitry Andric               static_cast<void *>(this), GetTypeName().GetCString());
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   if (m_address.IsValid() && m_dynamic_type_info) {
2590b57cec5SDimitry Andric     // The variable value is in the Scalar value inside the m_value. We can
2600b57cec5SDimitry Andric     // point our m_data right to it.
2619dba64beSDimitry Andric     m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get());
2620b57cec5SDimitry Andric     if (m_error.Success()) {
2630b57cec5SDimitry Andric       if (!CanProvideValue()) {
2640b57cec5SDimitry Andric         // this value object represents an aggregate type whose children have
2650b57cec5SDimitry Andric         // values, but this object does not. So we say we are changed if our
2660b57cec5SDimitry Andric         // location has changed.
2670b57cec5SDimitry Andric         SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() ||
2680b57cec5SDimitry Andric                           m_value.GetScalar() != old_value.GetScalar());
2690b57cec5SDimitry Andric       }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric       SetValueIsValid(true);
2720b57cec5SDimitry Andric       return true;
2730b57cec5SDimitry Andric     }
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   // We get here if we've failed above...
2770b57cec5SDimitry Andric   SetValueIsValid(false);
2780b57cec5SDimitry Andric   return false;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
IsInScope()2810b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); }
2820b57cec5SDimitry Andric 
SetValueFromCString(const char * value_str,Status & error)2830b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str,
2840b57cec5SDimitry Andric                                                   Status &error) {
2850b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
2860b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2870b57cec5SDimitry Andric     return false;
2880b57cec5SDimitry Andric   }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
2910b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
2940b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
2950b57cec5SDimitry Andric     return false;
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
2990b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
3000b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
3010b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
3020b57cec5SDimitry Andric   // parser instead of the value editing facility
3030b57cec5SDimitry Andric   if (my_value != parent_value) {
3040b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
3050b57cec5SDimitry Andric     if (strcmp(value_str, "0")) {
3060b57cec5SDimitry Andric       error.SetErrorString(
3070b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
3080b57cec5SDimitry Andric       return false;
3090b57cec5SDimitry Andric     }
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   bool ret_val = m_parent->SetValueFromCString(value_str, error);
3130b57cec5SDimitry Andric   SetNeedsUpdate();
3140b57cec5SDimitry Andric   return ret_val;
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric 
SetData(DataExtractor & data,Status & error)3170b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) {
3180b57cec5SDimitry Andric   if (!UpdateValueIfNeeded(false)) {
3190b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3200b57cec5SDimitry Andric     return false;
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   uint64_t my_value = GetValueAsUnsigned(UINT64_MAX);
3240b57cec5SDimitry Andric   uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX);
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   if (my_value == UINT64_MAX || parent_value == UINT64_MAX) {
3270b57cec5SDimitry Andric     error.SetErrorString("unable to read value");
3280b57cec5SDimitry Andric     return false;
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   // if we are at an offset from our parent, in order to set ourselves
3320b57cec5SDimitry Andric   // correctly we would need to change the new value so that it refers to the
3330b57cec5SDimitry Andric   // correct dynamic type. we choose not to deal with that - if anything more
3340b57cec5SDimitry Andric   // than a value overwrite is required, you should be using the expression
3350b57cec5SDimitry Andric   // parser instead of the value editing facility
3360b57cec5SDimitry Andric   if (my_value != parent_value) {
3370b57cec5SDimitry Andric     // but NULL'ing out a value should always be allowed
3380b57cec5SDimitry Andric     lldb::offset_t offset = 0;
3390b57cec5SDimitry Andric 
3405ffd83dbSDimitry Andric     if (data.GetAddress(&offset) != 0) {
3410b57cec5SDimitry Andric       error.SetErrorString(
3420b57cec5SDimitry Andric           "unable to modify dynamic value, use 'expression' command");
3430b57cec5SDimitry Andric       return false;
3440b57cec5SDimitry Andric     }
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   bool ret_val = m_parent->SetData(data, error);
3480b57cec5SDimitry Andric   SetNeedsUpdate();
3490b57cec5SDimitry Andric   return ret_val;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric 
SetPreferredDisplayLanguage(lldb::LanguageType lang)3520b57cec5SDimitry Andric void ValueObjectDynamicValue::SetPreferredDisplayLanguage(
3530b57cec5SDimitry Andric     lldb::LanguageType lang) {
3540b57cec5SDimitry Andric   this->ValueObject::SetPreferredDisplayLanguage(lang);
3550b57cec5SDimitry Andric   if (m_parent)
3560b57cec5SDimitry Andric     m_parent->SetPreferredDisplayLanguage(lang);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric 
GetPreferredDisplayLanguage()3590b57cec5SDimitry Andric lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() {
3600b57cec5SDimitry Andric   if (m_preferred_display_language == lldb::eLanguageTypeUnknown) {
3610b57cec5SDimitry Andric     if (m_parent)
3620b57cec5SDimitry Andric       return m_parent->GetPreferredDisplayLanguage();
3630b57cec5SDimitry Andric     return lldb::eLanguageTypeUnknown;
3640b57cec5SDimitry Andric   } else
3650b57cec5SDimitry Andric     return m_preferred_display_language;
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
IsSyntheticChildrenGenerated()3680b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() {
3690b57cec5SDimitry Andric   if (m_parent)
3700b57cec5SDimitry Andric     return m_parent->IsSyntheticChildrenGenerated();
3710b57cec5SDimitry Andric   return false;
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
SetSyntheticChildrenGenerated(bool b)3740b57cec5SDimitry Andric void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) {
3750b57cec5SDimitry Andric   if (m_parent)
3760b57cec5SDimitry Andric     m_parent->SetSyntheticChildrenGenerated(b);
3770b57cec5SDimitry Andric   this->ValueObject::SetSyntheticChildrenGenerated(b);
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
GetDeclaration(Declaration & decl)3800b57cec5SDimitry Andric bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) {
3810b57cec5SDimitry Andric   if (m_parent)
3820b57cec5SDimitry Andric     return m_parent->GetDeclaration(decl);
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   return ValueObject::GetDeclaration(decl);
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric 
GetLanguageFlags()3870b57cec5SDimitry Andric uint64_t ValueObjectDynamicValue::GetLanguageFlags() {
3880b57cec5SDimitry Andric   if (m_parent)
3890b57cec5SDimitry Andric     return m_parent->GetLanguageFlags();
3900b57cec5SDimitry Andric   return this->ValueObject::GetLanguageFlags();
3910b57cec5SDimitry Andric }
3920b57cec5SDimitry Andric 
SetLanguageFlags(uint64_t flags)3930b57cec5SDimitry Andric void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) {
3940b57cec5SDimitry Andric   if (m_parent)
3950b57cec5SDimitry Andric     m_parent->SetLanguageFlags(flags);
3960b57cec5SDimitry Andric   else
3970b57cec5SDimitry Andric     this->ValueObject::SetLanguageFlags(flags);
3980b57cec5SDimitry Andric }
399