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 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 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 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 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 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 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 88*0fca6ea1SDimitry Andric llvm::Expected<uint32_t> 89*0fca6ea1SDimitry Andric ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { 900b57cec5SDimitry Andric const bool success = UpdateValueIfNeeded(false); 910b57cec5SDimitry Andric if (success && m_dynamic_type_info.HasType()) { 920b57cec5SDimitry Andric ExecutionContext exe_ctx(GetExecutionContextRef()); 930b57cec5SDimitry Andric auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx); 94*0fca6ea1SDimitry Andric if (!children_count) 95*0fca6ea1SDimitry Andric return children_count; 96*0fca6ea1SDimitry Andric return *children_count <= max ? *children_count : max; 970b57cec5SDimitry Andric } else 980b57cec5SDimitry Andric return m_parent->GetNumChildren(max); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101bdd1243dSDimitry Andric std::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 1100b57cec5SDimitry Andric lldb::ValueType ValueObjectDynamicValue::GetValueType() const { 1110b57cec5SDimitry Andric return m_parent->GetValueType(); 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric 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); 15506c3fb27SDimitry Andric if (auto *preferred_runtime = 15606c3fb27SDimitry Andric runtime->GetPreferredLanguageRuntime(*m_parent)) { 15706c3fb27SDimitry Andric // Try the preferred runtime first. 15806c3fb27SDimitry Andric found_dynamic_type = preferred_runtime->GetDynamicTypeAndAddress( 15906c3fb27SDimitry Andric *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 16006c3fb27SDimitry Andric value_type); 16106c3fb27SDimitry Andric if (found_dynamic_type) 16206c3fb27SDimitry Andric // Set the operative `runtime` for later use in this function. 16306c3fb27SDimitry Andric runtime = preferred_runtime; 16406c3fb27SDimitry Andric } 16506c3fb27SDimitry Andric if (!found_dynamic_type) 16606c3fb27SDimitry Andric // Fallback to the runtime for `known_type`. 1670b57cec5SDimitry Andric found_dynamic_type = runtime->GetDynamicTypeAndAddress( 1680b57cec5SDimitry Andric *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 1690b57cec5SDimitry Andric value_type); 1700b57cec5SDimitry Andric } else { 1710b57cec5SDimitry Andric runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus); 1720b57cec5SDimitry Andric if (runtime) 1730b57cec5SDimitry Andric found_dynamic_type = runtime->GetDynamicTypeAndAddress( 1740b57cec5SDimitry Andric *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 1750b57cec5SDimitry Andric value_type); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric if (!found_dynamic_type) { 1780b57cec5SDimitry Andric runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC); 1790b57cec5SDimitry Andric if (runtime) 1800b57cec5SDimitry Andric found_dynamic_type = runtime->GetDynamicTypeAndAddress( 1810b57cec5SDimitry Andric *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, 1820b57cec5SDimitry Andric value_type); 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // Getting the dynamic value may have run the program a bit, and so marked us 1870b57cec5SDimitry Andric // as needing updating, but we really don't... 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric m_update_point.SetUpdated(); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric if (runtime && found_dynamic_type) { 1920b57cec5SDimitry Andric if (class_type_or_name.HasType()) { 1930b57cec5SDimitry Andric m_type_impl = 1940b57cec5SDimitry Andric TypeImpl(m_parent->GetCompilerType(), 1950b57cec5SDimitry Andric runtime->FixUpDynamicType(class_type_or_name, *m_parent) 1960b57cec5SDimitry Andric .GetCompilerType()); 1970b57cec5SDimitry Andric } else { 1980b57cec5SDimitry Andric m_type_impl.Clear(); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric } else { 2010b57cec5SDimitry Andric m_type_impl.Clear(); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 20406c3fb27SDimitry Andric // If we don't have a dynamic type, set ourselves to be invalid and return 20506c3fb27SDimitry Andric // false. We used to try to produce a dynamic ValueObject that behaved "like" 20606c3fb27SDimitry Andric // its parent, but that failed for ValueObjectConstResult, which is too 20706c3fb27SDimitry Andric // complex a beast to try to emulate. If we return an invalid ValueObject, 20806c3fb27SDimitry Andric // clients will end up getting the static value instead, which behaves 20906c3fb27SDimitry Andric // correctly. 2100b57cec5SDimitry Andric if (!found_dynamic_type) { 2110b57cec5SDimitry Andric if (m_dynamic_type_info) 2120b57cec5SDimitry Andric SetValueDidChange(true); 2130b57cec5SDimitry Andric ClearDynamicTypeInformation(); 2140b57cec5SDimitry Andric m_dynamic_type_info.Clear(); 21506c3fb27SDimitry Andric m_error.SetErrorString("no dynamic type found"); 21606c3fb27SDimitry Andric return false; 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric Value old_value(m_value); 2200b57cec5SDimitry Andric 22181ad6265SDimitry Andric Log *log = GetLog(LLDBLog::Types); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric bool has_changed_type = false; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric if (!m_dynamic_type_info) { 2260b57cec5SDimitry Andric m_dynamic_type_info = class_type_or_name; 2270b57cec5SDimitry Andric has_changed_type = true; 2280b57cec5SDimitry Andric } else if (class_type_or_name != m_dynamic_type_info) { 2290b57cec5SDimitry Andric // We are another type, we need to tear down our children... 2300b57cec5SDimitry Andric m_dynamic_type_info = class_type_or_name; 2310b57cec5SDimitry Andric SetValueDidChange(true); 2320b57cec5SDimitry Andric has_changed_type = true; 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric if (has_changed_type) 2360b57cec5SDimitry Andric ClearDynamicTypeInformation(); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric if (!m_address.IsValid() || m_address != dynamic_address) { 2390b57cec5SDimitry Andric if (m_address.IsValid()) 2400b57cec5SDimitry Andric SetValueDidChange(true); 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric // We've moved, so we should be fine... 2430b57cec5SDimitry Andric m_address = dynamic_address; 2440b57cec5SDimitry Andric lldb::TargetSP target_sp(GetTargetSP()); 2450b57cec5SDimitry Andric lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); 2460b57cec5SDimitry Andric m_value.GetScalar() = load_address; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric if (runtime) 2500b57cec5SDimitry Andric m_dynamic_type_info = 2510b57cec5SDimitry Andric runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType()); 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric m_value.SetValueType(value_type); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric if (has_changed_type && log) 2589dba64beSDimitry Andric LLDB_LOGF(log, "[%s %p] has a new dynamic type %s", GetName().GetCString(), 2590b57cec5SDimitry Andric static_cast<void *>(this), GetTypeName().GetCString()); 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric if (m_address.IsValid() && m_dynamic_type_info) { 2620b57cec5SDimitry Andric // The variable value is in the Scalar value inside the m_value. We can 2630b57cec5SDimitry Andric // point our m_data right to it. 2649dba64beSDimitry Andric m_error = m_value.GetValueAsData(&exe_ctx, m_data, GetModule().get()); 2650b57cec5SDimitry Andric if (m_error.Success()) { 2660b57cec5SDimitry Andric if (!CanProvideValue()) { 2670b57cec5SDimitry Andric // this value object represents an aggregate type whose children have 2680b57cec5SDimitry Andric // values, but this object does not. So we say we are changed if our 2690b57cec5SDimitry Andric // location has changed. 2700b57cec5SDimitry Andric SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || 2710b57cec5SDimitry Andric m_value.GetScalar() != old_value.GetScalar()); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric SetValueIsValid(true); 2750b57cec5SDimitry Andric return true; 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric // We get here if we've failed above... 2800b57cec5SDimitry Andric SetValueIsValid(false); 2810b57cec5SDimitry Andric return false; 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str, 2870b57cec5SDimitry Andric Status &error) { 2880b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) { 2890b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 2900b57cec5SDimitry Andric return false; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 2940b57cec5SDimitry Andric uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 2970b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 2980b57cec5SDimitry Andric return false; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric // if we are at an offset from our parent, in order to set ourselves 3020b57cec5SDimitry Andric // correctly we would need to change the new value so that it refers to the 3030b57cec5SDimitry Andric // correct dynamic type. we choose not to deal with that - if anything more 3040b57cec5SDimitry Andric // than a value overwrite is required, you should be using the expression 3050b57cec5SDimitry Andric // parser instead of the value editing facility 3060b57cec5SDimitry Andric if (my_value != parent_value) { 3070b57cec5SDimitry Andric // but NULL'ing out a value should always be allowed 3080b57cec5SDimitry Andric if (strcmp(value_str, "0")) { 3090b57cec5SDimitry Andric error.SetErrorString( 3100b57cec5SDimitry Andric "unable to modify dynamic value, use 'expression' command"); 3110b57cec5SDimitry Andric return false; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric bool ret_val = m_parent->SetValueFromCString(value_str, error); 3160b57cec5SDimitry Andric SetNeedsUpdate(); 3170b57cec5SDimitry Andric return ret_val; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric bool ValueObjectDynamicValue::SetData(DataExtractor &data, Status &error) { 3210b57cec5SDimitry Andric if (!UpdateValueIfNeeded(false)) { 3220b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 3230b57cec5SDimitry Andric return false; 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); 3270b57cec5SDimitry Andric uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { 3300b57cec5SDimitry Andric error.SetErrorString("unable to read value"); 3310b57cec5SDimitry Andric return false; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric // if we are at an offset from our parent, in order to set ourselves 3350b57cec5SDimitry Andric // correctly we would need to change the new value so that it refers to the 3360b57cec5SDimitry Andric // correct dynamic type. we choose not to deal with that - if anything more 3370b57cec5SDimitry Andric // than a value overwrite is required, you should be using the expression 3380b57cec5SDimitry Andric // parser instead of the value editing facility 3390b57cec5SDimitry Andric if (my_value != parent_value) { 3400b57cec5SDimitry Andric // but NULL'ing out a value should always be allowed 3410b57cec5SDimitry Andric lldb::offset_t offset = 0; 3420b57cec5SDimitry Andric 3435ffd83dbSDimitry Andric if (data.GetAddress(&offset) != 0) { 3440b57cec5SDimitry Andric error.SetErrorString( 3450b57cec5SDimitry Andric "unable to modify dynamic value, use 'expression' command"); 3460b57cec5SDimitry Andric return false; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool ret_val = m_parent->SetData(data, error); 3510b57cec5SDimitry Andric SetNeedsUpdate(); 3520b57cec5SDimitry Andric return ret_val; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric void ValueObjectDynamicValue::SetPreferredDisplayLanguage( 3560b57cec5SDimitry Andric lldb::LanguageType lang) { 3570b57cec5SDimitry Andric this->ValueObject::SetPreferredDisplayLanguage(lang); 3580b57cec5SDimitry Andric if (m_parent) 3590b57cec5SDimitry Andric m_parent->SetPreferredDisplayLanguage(lang); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() { 3630b57cec5SDimitry Andric if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { 3640b57cec5SDimitry Andric if (m_parent) 3650b57cec5SDimitry Andric return m_parent->GetPreferredDisplayLanguage(); 3660b57cec5SDimitry Andric return lldb::eLanguageTypeUnknown; 3670b57cec5SDimitry Andric } else 3680b57cec5SDimitry Andric return m_preferred_display_language; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() { 3720b57cec5SDimitry Andric if (m_parent) 3730b57cec5SDimitry Andric return m_parent->IsSyntheticChildrenGenerated(); 3740b57cec5SDimitry Andric return false; 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) { 3780b57cec5SDimitry Andric if (m_parent) 3790b57cec5SDimitry Andric m_parent->SetSyntheticChildrenGenerated(b); 3800b57cec5SDimitry Andric this->ValueObject::SetSyntheticChildrenGenerated(b); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) { 3840b57cec5SDimitry Andric if (m_parent) 3850b57cec5SDimitry Andric return m_parent->GetDeclaration(decl); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric return ValueObject::GetDeclaration(decl); 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric uint64_t ValueObjectDynamicValue::GetLanguageFlags() { 3910b57cec5SDimitry Andric if (m_parent) 3920b57cec5SDimitry Andric return m_parent->GetLanguageFlags(); 3930b57cec5SDimitry Andric return this->ValueObject::GetLanguageFlags(); 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) { 3970b57cec5SDimitry Andric if (m_parent) 3980b57cec5SDimitry Andric m_parent->SetLanguageFlags(flags); 3990b57cec5SDimitry Andric else 4000b57cec5SDimitry Andric this->ValueObject::SetLanguageFlags(flags); 4010b57cec5SDimitry Andric } 402