1 | //===-- ValueObjectCast.cpp -----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Core/ValueObjectCast.h" |
10 | |
11 | #include "lldb/Core/Value.h" |
12 | #include "lldb/Core/ValueObject.h" |
13 | #include "lldb/Symbol/CompilerType.h" |
14 | #include "lldb/Target/ExecutionContext.h" |
15 | #include "lldb/Utility/Scalar.h" |
16 | #include "lldb/Utility/Status.h" |
17 | #include <optional> |
18 | |
19 | namespace lldb_private { |
20 | class ConstString; |
21 | } |
22 | |
23 | using namespace lldb_private; |
24 | |
25 | lldb::ValueObjectSP ValueObjectCast::Create(ValueObject &parent, |
26 | ConstString name, |
27 | const CompilerType &cast_type) { |
28 | ValueObjectCast *cast_valobj_ptr = |
29 | new ValueObjectCast(parent, name, cast_type); |
30 | return cast_valobj_ptr->GetSP(); |
31 | } |
32 | |
33 | ValueObjectCast::ValueObjectCast(ValueObject &parent, ConstString name, |
34 | const CompilerType &cast_type) |
35 | : ValueObject(parent), m_cast_type(cast_type) { |
36 | SetName(name); |
37 | m_value.SetCompilerType(cast_type); |
38 | } |
39 | |
40 | ValueObjectCast::~ValueObjectCast() = default; |
41 | |
42 | CompilerType ValueObjectCast::GetCompilerTypeImpl() { return m_cast_type; } |
43 | |
44 | llvm::Expected<uint32_t> ValueObjectCast::CalculateNumChildren(uint32_t max) { |
45 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
46 | auto children_count = GetCompilerType().GetNumChildren( |
47 | omit_empty_base_classes: true, exe_ctx: &exe_ctx); |
48 | if (!children_count) |
49 | return children_count; |
50 | return *children_count <= max ? *children_count : max; |
51 | } |
52 | |
53 | std::optional<uint64_t> ValueObjectCast::GetByteSize() { |
54 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
55 | return m_value.GetValueByteSize(error_ptr: nullptr, exe_ctx: &exe_ctx); |
56 | } |
57 | |
58 | lldb::ValueType ValueObjectCast::GetValueType() const { |
59 | // Let our parent answer global, local, argument, etc... |
60 | return m_parent->GetValueType(); |
61 | } |
62 | |
63 | bool ValueObjectCast::UpdateValue() { |
64 | SetValueIsValid(false); |
65 | m_error.Clear(); |
66 | |
67 | if (m_parent->UpdateValueIfNeeded(update_format: false)) { |
68 | Value old_value(m_value); |
69 | m_update_point.SetUpdated(); |
70 | m_value = m_parent->GetValue(); |
71 | CompilerType compiler_type(GetCompilerType()); |
72 | m_value.SetCompilerType(compiler_type); |
73 | SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); |
74 | if (!CanProvideValue()) { |
75 | // this value object represents an aggregate type whose children have |
76 | // values, but this object does not. So we say we are changed if our |
77 | // location has changed. |
78 | SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || |
79 | m_value.GetScalar() != old_value.GetScalar()); |
80 | } |
81 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
82 | m_error = m_value.GetValueAsData(exe_ctx: &exe_ctx, data&: m_data, module: GetModule().get()); |
83 | SetValueDidChange(m_parent->GetValueDidChange()); |
84 | return true; |
85 | } |
86 | |
87 | // The dynamic value failed to get an error, pass the error along |
88 | if (m_error.Success() && m_parent->GetError().Fail()) |
89 | m_error = m_parent->GetError(); |
90 | SetValueIsValid(false); |
91 | return false; |
92 | } |
93 | |
94 | bool ValueObjectCast::IsInScope() { return m_parent->IsInScope(); } |
95 | |