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