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