LLDB mainline
MsvcStlVariant.cpp
Go to the documentation of this file.
1//===-- MsvcStlVariant.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 "MsvcStl.h"
12#include <optional>
13
14using namespace lldb;
15using namespace lldb_private;
16
17namespace {
18
19// A variant when using DWARF looks as follows:
20// (lldb) fr v -R v1
21// (std::variant<int, double, char>) v1 = {
22// std::_SMF_control<std::_Variant_base<int, double, char>, int, double, char>
23// = {
24// std::_Variant_storage<int, double, char> = {
25// = {
26// _Head = 0
27// _Tail = {
28// = {
29// _Head = 2
30// _Tail = {
31// = {
32// _Head = '\0'
33// _Tail = {}
34// }
35// }
36// }
37// }
38// }
39// }
40// _Which = '\x01'
41// }
42// }
43
44ValueObjectSP GetStorageMember(ValueObject &valobj, llvm::StringRef name) {
45 // Find the union
46 ValueObjectSP union_sp = valobj.GetChildAtIndex(0);
47 if (!union_sp)
48 return nullptr;
49 return union_sp->GetChildMemberWithName(name);
50}
51
52ValueObjectSP GetHead(ValueObject &valobj) {
53 return GetStorageMember(valobj, "_Head");
54}
55ValueObjectSP GetTail(ValueObject &valobj) {
56 return GetStorageMember(valobj, "_Tail");
57}
58
59std::optional<int64_t> GetIndexValue(ValueObject &valobj) {
60 ValueObjectSP index_sp = valobj.GetChildMemberWithName("_Which");
61 if (!index_sp)
62 return std::nullopt;
63
64 return {index_sp->GetValueAsSigned(-1)};
65}
66
67ValueObjectSP GetNthStorage(ValueObject &outer, int64_t index) {
68 // We need to find the std::_Variant_storage base class.
69
70 // -> std::_SMF_control (typedef to std::_Variant_base)
71 ValueObjectSP container_sp = outer.GetSP()->GetChildAtIndex(0);
72 if (!container_sp)
73 return nullptr;
74 // -> std::_Variant_storage
75 container_sp = container_sp->GetChildAtIndex(0);
76 if (!container_sp)
77 return nullptr;
78
79 for (int64_t i = 0; i < index; i++) {
80 container_sp = GetTail(*container_sp);
81 if (!container_sp)
82 return nullptr;
83 }
84 return container_sp;
85}
86
87} // namespace
88
90 if (auto valobj_sp = valobj.GetNonSyntheticValue()) {
91 return valobj_sp->GetChildMemberWithName("_Which") != nullptr;
92 }
93 return false;
94}
95
97 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
98 ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
99 if (!valobj_sp)
100 return false;
101
102 auto index = GetIndexValue(*valobj_sp);
103 if (!index)
104 return false;
105
106 if (*index < 0) {
107 stream.Printf(" No Value");
108 return true;
109 }
110
111 ValueObjectSP storage = GetNthStorage(*valobj_sp, *index);
112 if (!storage)
113 return false;
114 CompilerType storage_type = storage->GetCompilerType();
115 if (!storage_type)
116 return false;
117 // Resolve the typedef
118 if (storage_type.IsTypedefType())
119 storage_type = storage_type.GetTypedefedType();
120
121 CompilerType active_type = storage_type.GetTypeTemplateArgument(1, true);
122 if (!active_type)
123 return false;
124
125 stream << " Active Type = " << active_type.GetDisplayTypeName() << " ";
126 return true;
127}
128
129namespace {
130class VariantFrontEnd : public SyntheticChildrenFrontEnd {
131public:
132 VariantFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
133 Update();
134 }
135
136 llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
137 auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
138 if (!optional_idx) {
139 return llvm::createStringError("Type has no child named '%s'",
140 name.AsCString());
141 }
142 return *optional_idx;
143 }
144
145 lldb::ChildCacheState Update() override;
146 llvm::Expected<uint32_t> CalculateNumChildren() override { return m_size; }
147 ValueObjectSP GetChildAtIndex(uint32_t idx) override;
148
149private:
150 size_t m_size = 0;
151};
152} // namespace
153
154lldb::ChildCacheState VariantFrontEnd::Update() {
155 m_size = 0;
156
157 auto index = GetIndexValue(m_backend);
158 if (index && *index >= 0)
159 m_size = 1;
160
162}
163
164ValueObjectSP VariantFrontEnd::GetChildAtIndex(uint32_t idx) {
165 if (idx >= m_size)
166 return nullptr;
167
168 auto index = GetIndexValue(m_backend);
169 if (!index)
170 return nullptr;
171
172 ValueObjectSP storage_sp = GetNthStorage(m_backend, *index);
173 if (!storage_sp)
174 return nullptr;
175
176 ValueObjectSP head_sp = GetHead(*storage_sp);
177 if (!head_sp)
178 return nullptr;
179
180 return head_sp->Clone(ConstString("Value"));
181}
182
185 if (valobj_sp)
186 return new VariantFrontEnd(*valobj_sp);
187 return nullptr;
188}
static std::optional< size_t > CalculateNumChildren(CompilerType container_elem_type, uint64_t num_elements, CompilerType element_type)
Calculates the number of elements stored in a container (with element type 'container_elem_type') as ...
Generic representation of a type in a programming language.
CompilerType GetTypeTemplateArgument(size_t idx, bool expand_pack=false) const
ConstString GetDisplayTypeName() const
CompilerType GetTypedefedType() const
If the current object represents a typedef type, get the underlying type.
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const char * GetCString() const
Get the string value as a C string.
A stream class that can stream formatted output to a file.
Definition Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true)
lldb::ValueObjectSP GetSP()
virtual lldb::ValueObjectSP GetChildMemberWithName(llvm::StringRef name, bool can_create=true)
virtual lldb::ValueObjectSP GetNonSyntheticValue()
std::optional< size_t > ExtractIndexFromString(const char *item_name)
bool MsvcStlVariantSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options)
SyntheticChildrenFrontEnd * MsvcStlVariantSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp)
bool IsMsvcStlVariant(ValueObject &valobj)
A class that represents a running process on the host machine.
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP