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/ValueObject/ValueObjectCast.h" |
10 | |
11 | #include "lldb/Core/Value.h" |
12 | #include "lldb/Symbol/CompilerType.h" |
13 | #include "lldb/Target/ExecutionContext.h" |
14 | #include "lldb/Utility/Scalar.h" |
15 | #include "lldb/Utility/Status.h" |
16 | #include "lldb/ValueObject/ValueObject.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(omit_empty_base_classes: true, exe_ctx: &exe_ctx); |
47 | if (!children_count) |
48 | return children_count; |
49 | return *children_count <= max ? *children_count : max; |
50 | } |
51 | |
52 | llvm::Expected<uint64_t> ValueObjectCast::GetByteSize() { |
53 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
54 | return m_value.GetValueByteSize(error_ptr: nullptr, exe_ctx: &exe_ctx); |
55 | } |
56 | |
57 | lldb::ValueType ValueObjectCast::GetValueType() const { |
58 | // Let our parent answer global, local, argument, etc... |
59 | return m_parent->GetValueType(); |
60 | } |
61 | |
62 | bool ValueObjectCast::UpdateValue() { |
63 | SetValueIsValid(false); |
64 | m_error.Clear(); |
65 | |
66 | if (m_parent->UpdateValueIfNeeded(update_format: false)) { |
67 | Value old_value(m_value); |
68 | m_update_point.SetUpdated(); |
69 | m_value = m_parent->GetValue(); |
70 | CompilerType compiler_type(GetCompilerType()); |
71 | m_value.SetCompilerType(compiler_type); |
72 | SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); |
73 | if (!CanProvideValue()) { |
74 | // this value object represents an aggregate type whose children have |
75 | // values, but this object does not. So we say we are changed if our |
76 | // location has changed. |
77 | SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || |
78 | m_value.GetScalar() != old_value.GetScalar()); |
79 | } |
80 | ExecutionContext exe_ctx(GetExecutionContextRef()); |
81 | m_error = m_value.GetValueAsData(exe_ctx: &exe_ctx, data&: m_data, module: GetModule().get()); |
82 | SetValueDidChange(m_parent->GetValueDidChange()); |
83 | return true; |
84 | } |
85 | |
86 | // The dynamic value failed to get an error, pass the error along |
87 | if (m_error.Success() && m_parent->GetError().Fail()) |
88 | m_error = m_parent->GetError().Clone(); |
89 | SetValueIsValid(false); |
90 | return false; |
91 | } |
92 | |
93 | bool ValueObjectCast::IsInScope() { return m_parent->IsInScope(); } |
94 | |