1 | //===-- Type.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 <algorithm> |
10 | #include <cstdio> |
11 | #include <iterator> |
12 | #include <optional> |
13 | |
14 | #include "lldb/Core/Module.h" |
15 | #include "lldb/Utility/DataBufferHeap.h" |
16 | #include "lldb/Utility/DataExtractor.h" |
17 | #include "lldb/Utility/LLDBLog.h" |
18 | #include "lldb/Utility/Log.h" |
19 | #include "lldb/Utility/Scalar.h" |
20 | #include "lldb/Utility/StreamString.h" |
21 | |
22 | #include "lldb/Symbol/CompilerType.h" |
23 | #include "lldb/Symbol/ObjectFile.h" |
24 | #include "lldb/Symbol/SymbolContextScope.h" |
25 | #include "lldb/Symbol/SymbolFile.h" |
26 | #include "lldb/Symbol/SymbolVendor.h" |
27 | #include "lldb/Symbol/Type.h" |
28 | #include "lldb/Symbol/TypeList.h" |
29 | #include "lldb/Symbol/TypeSystem.h" |
30 | |
31 | #include "lldb/Target/ExecutionContext.h" |
32 | #include "lldb/Target/Process.h" |
33 | #include "lldb/Target/Target.h" |
34 | #include "lldb/lldb-enumerations.h" |
35 | #include "lldb/lldb-private-enumerations.h" |
36 | |
37 | #include "llvm/ADT/StringRef.h" |
38 | |
39 | using namespace lldb; |
40 | using namespace lldb_private; |
41 | |
42 | llvm::raw_ostream &lldb_private::operator<<(llvm::raw_ostream &os, |
43 | const CompilerContext &rhs) { |
44 | StreamString lldb_stream; |
45 | rhs.Dump(s&: lldb_stream); |
46 | return os << lldb_stream.GetString(); |
47 | } |
48 | |
49 | static CompilerContextKind ConvertTypeClass(lldb::TypeClass type_class) { |
50 | if (type_class == eTypeClassAny) |
51 | return CompilerContextKind::AnyType; |
52 | CompilerContextKind result = {}; |
53 | if (type_class & (lldb::eTypeClassClass | lldb::eTypeClassStruct)) |
54 | result |= CompilerContextKind::ClassOrStruct; |
55 | if (type_class & lldb::eTypeClassUnion) |
56 | result |= CompilerContextKind::Union; |
57 | if (type_class & lldb::eTypeClassEnumeration) |
58 | result |= CompilerContextKind::Enum; |
59 | if (type_class & lldb::eTypeClassFunction) |
60 | result |= CompilerContextKind::Function; |
61 | if (type_class & lldb::eTypeClassTypedef) |
62 | result |= CompilerContextKind::Typedef; |
63 | return result; |
64 | } |
65 | |
66 | TypeQuery::TypeQuery(llvm::StringRef name, TypeQueryOptions options) |
67 | : m_options(options) { |
68 | if (std::optional<Type::ParsedName> parsed_name = |
69 | Type::GetTypeScopeAndBasename(name)) { |
70 | llvm::ArrayRef scope = parsed_name->scope; |
71 | if (!scope.empty()) { |
72 | if (scope[0] == "::") { |
73 | m_options |= e_exact_match; |
74 | scope = scope.drop_front(); |
75 | } |
76 | for (llvm::StringRef s : scope) { |
77 | m_context.push_back( |
78 | x: {CompilerContextKind::AnyDeclContext, ConstString(s)}); |
79 | } |
80 | } |
81 | m_context.push_back(x: {ConvertTypeClass(type_class: parsed_name->type_class), |
82 | ConstString(parsed_name->basename)}); |
83 | } else { |
84 | m_context.push_back(x: {CompilerContextKind::AnyType, ConstString(name)}); |
85 | } |
86 | } |
87 | |
88 | TypeQuery::TypeQuery(const CompilerDeclContext &decl_ctx, |
89 | ConstString type_basename, TypeQueryOptions options) |
90 | : m_options(options) { |
91 | // Always use an exact match if we are looking for a type in compiler context. |
92 | m_options |= e_exact_match; |
93 | m_context = decl_ctx.GetCompilerContext(); |
94 | m_context.push_back(x: {CompilerContextKind::AnyType, type_basename}); |
95 | } |
96 | |
97 | TypeQuery::TypeQuery( |
98 | const llvm::ArrayRef<lldb_private::CompilerContext> &context, |
99 | TypeQueryOptions options) |
100 | : m_context(context), m_options(options) { |
101 | // Always use an exact match if we are looking for a type in compiler context. |
102 | m_options |= e_exact_match; |
103 | } |
104 | |
105 | TypeQuery::TypeQuery(const CompilerDecl &decl, TypeQueryOptions options) |
106 | : m_options(options) { |
107 | // Always for an exact match if we are looking for a type using a declaration. |
108 | m_options |= e_exact_match; |
109 | m_context = decl.GetCompilerContext(); |
110 | } |
111 | |
112 | ConstString TypeQuery::GetTypeBasename() const { |
113 | if (m_context.empty()) |
114 | return ConstString(); |
115 | return m_context.back().name; |
116 | } |
117 | |
118 | void TypeQuery::AddLanguage(LanguageType language) { |
119 | if (!m_languages) |
120 | m_languages = LanguageSet(); |
121 | m_languages->Insert(language); |
122 | } |
123 | |
124 | void TypeQuery::SetLanguages(LanguageSet languages) { |
125 | m_languages = std::move(languages); |
126 | } |
127 | |
128 | bool TypeQuery::ContextMatches( |
129 | llvm::ArrayRef<CompilerContext> context_chain) const { |
130 | auto ctx = context_chain.rbegin(), ctx_end = context_chain.rend(); |
131 | for (auto pat = m_context.rbegin(), pat_end = m_context.rend(); |
132 | pat != pat_end;) { |
133 | |
134 | if (ctx == ctx_end) |
135 | return false; // Pattern too long. |
136 | |
137 | if (ctx->kind == CompilerContextKind::Namespace && ctx->name.IsEmpty()) { |
138 | // We're matching an anonymous namespace. These are optional, so we check |
139 | // if the pattern expects an anonymous namespace. |
140 | if (pat->name.IsEmpty() && (pat->kind & CompilerContextKind::Namespace) == |
141 | CompilerContextKind::Namespace) { |
142 | // Match, advance both iterators. |
143 | ++pat; |
144 | } |
145 | // Otherwise, only advance the context to skip over the anonymous |
146 | // namespace, and try matching again. |
147 | ++ctx; |
148 | continue; |
149 | } |
150 | |
151 | // See if there is a kind mismatch; they should have 1 bit in common. |
152 | if ((ctx->kind & pat->kind) == CompilerContextKind()) |
153 | return false; |
154 | |
155 | if (ctx->name != pat->name) |
156 | return false; |
157 | |
158 | ++ctx; |
159 | ++pat; |
160 | } |
161 | |
162 | // Skip over any remaining module and anonymous namespace entries if we were |
163 | // asked to do that. |
164 | auto should_skip = [this](const CompilerContext &ctx) { |
165 | if (ctx.kind == CompilerContextKind::Module) |
166 | return GetIgnoreModules(); |
167 | if (ctx.kind == CompilerContextKind::Namespace && ctx.name.IsEmpty()) |
168 | return !GetStrictNamespaces(); |
169 | return false; |
170 | }; |
171 | ctx = std::find_if_not(first: ctx, last: ctx_end, pred: should_skip); |
172 | |
173 | // At this point, we have exhausted the pattern and we have a partial match at |
174 | // least. If that's all we're looking for, we're done. |
175 | if (!GetExactMatch()) |
176 | return true; |
177 | |
178 | // We have an exact match if we've exhausted the target context as well. |
179 | return ctx == ctx_end; |
180 | } |
181 | |
182 | bool TypeQuery::LanguageMatches(lldb::LanguageType language) const { |
183 | // If we have no language filterm language always matches. |
184 | if (!m_languages.has_value()) |
185 | return true; |
186 | return (*m_languages)[language]; |
187 | } |
188 | |
189 | bool TypeResults::AlreadySearched(lldb_private::SymbolFile *sym_file) { |
190 | return !m_searched_symbol_files.insert(V: sym_file).second; |
191 | } |
192 | |
193 | bool TypeResults::InsertUnique(const lldb::TypeSP &type_sp) { |
194 | if (type_sp) |
195 | return m_type_map.InsertUnique(type: type_sp); |
196 | return false; |
197 | } |
198 | |
199 | bool TypeResults::Done(const TypeQuery &query) const { |
200 | if (query.GetFindOne()) |
201 | return !m_type_map.Empty(); |
202 | return false; |
203 | } |
204 | |
205 | void CompilerContext::Dump(Stream &s) const { |
206 | switch (kind) { |
207 | default: |
208 | s << "Invalid"; |
209 | break; |
210 | case CompilerContextKind::TranslationUnit: |
211 | s << "TranslationUnit"; |
212 | break; |
213 | case CompilerContextKind::Module: |
214 | s << "Module"; |
215 | break; |
216 | case CompilerContextKind::Namespace: |
217 | s << "Namespace"; |
218 | break; |
219 | case CompilerContextKind::ClassOrStruct: |
220 | s << "ClassOrStruct"; |
221 | break; |
222 | case CompilerContextKind::Union: |
223 | s << "Union"; |
224 | break; |
225 | case CompilerContextKind::Function: |
226 | s << "Function"; |
227 | break; |
228 | case CompilerContextKind::Variable: |
229 | s << "Variable"; |
230 | break; |
231 | case CompilerContextKind::Enum: |
232 | s << "Enumeration"; |
233 | break; |
234 | case CompilerContextKind::Typedef: |
235 | s << "Typedef"; |
236 | break; |
237 | case CompilerContextKind::AnyType: |
238 | s << "AnyType"; |
239 | break; |
240 | } |
241 | s << "("<< name << ")"; |
242 | } |
243 | |
244 | class TypeAppendVisitor { |
245 | public: |
246 | TypeAppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {} |
247 | |
248 | bool operator()(const lldb::TypeSP &type) { |
249 | m_type_list.Append(type: TypeImplSP(new TypeImpl(type))); |
250 | return true; |
251 | } |
252 | |
253 | private: |
254 | TypeListImpl &m_type_list; |
255 | }; |
256 | |
257 | void TypeListImpl::Append(const lldb_private::TypeList &type_list) { |
258 | TypeAppendVisitor cb(*this); |
259 | type_list.ForEach(callback: cb); |
260 | } |
261 | |
262 | SymbolFileType::SymbolFileType(SymbolFile &symbol_file, |
263 | const lldb::TypeSP &type_sp) |
264 | : UserID(type_sp ? type_sp->GetID() : LLDB_INVALID_UID), |
265 | m_symbol_file(symbol_file), m_type_sp(type_sp) {} |
266 | |
267 | Type *SymbolFileType::GetType() { |
268 | if (!m_type_sp) { |
269 | Type *resolved_type = m_symbol_file.ResolveTypeUID(type_uid: GetID()); |
270 | if (resolved_type) |
271 | m_type_sp = resolved_type->shared_from_this(); |
272 | } |
273 | return m_type_sp.get(); |
274 | } |
275 | |
276 | Type::Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, |
277 | std::optional<uint64_t> byte_size, SymbolContextScope *context, |
278 | user_id_t encoding_uid, EncodingDataType encoding_uid_type, |
279 | const Declaration &decl, const CompilerType &compiler_type, |
280 | ResolveState compiler_type_resolve_state, uint32_t opaque_payload) |
281 | : std::enable_shared_from_this<Type>(), UserID(uid), m_name(name), |
282 | m_symbol_file(symbol_file), m_context(context), |
283 | m_encoding_uid(encoding_uid), m_encoding_uid_type(encoding_uid_type), |
284 | m_decl(decl), m_compiler_type(compiler_type), |
285 | m_compiler_type_resolve_state(compiler_type ? compiler_type_resolve_state |
286 | : ResolveState::Unresolved), |
287 | m_payload(opaque_payload) { |
288 | if (byte_size) { |
289 | m_byte_size = *byte_size; |
290 | m_byte_size_has_value = true; |
291 | } else { |
292 | m_byte_size = 0; |
293 | m_byte_size_has_value = false; |
294 | } |
295 | } |
296 | |
297 | Type::Type() |
298 | : std::enable_shared_from_this<Type>(), UserID(0), m_name("<INVALID TYPE>"), |
299 | m_payload(0) { |
300 | m_byte_size = 0; |
301 | m_byte_size_has_value = false; |
302 | } |
303 | |
304 | void Type::GetDescription(Stream *s, lldb::DescriptionLevel level, |
305 | bool show_name, ExecutionContextScope *exe_scope) { |
306 | *s << "id = "<< (const UserID &)*this; |
307 | |
308 | // Call the name accessor to make sure we resolve the type name |
309 | if (show_name) { |
310 | ConstString type_name = GetName(); |
311 | if (type_name) { |
312 | *s << ", name = \""<< type_name << '"'; |
313 | ConstString qualified_type_name(GetQualifiedName()); |
314 | if (qualified_type_name != type_name) { |
315 | *s << ", qualified = \""<< qualified_type_name << '"'; |
316 | } |
317 | } |
318 | } |
319 | |
320 | // Call the get byte size accessor so we resolve our byte size |
321 | if (GetByteSize(exe_scope)) |
322 | s->Printf(format: ", byte-size = %"PRIu64, m_byte_size); |
323 | bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose); |
324 | m_decl.Dump(s, show_fullpaths); |
325 | |
326 | if (m_compiler_type.IsValid()) { |
327 | *s << ", compiler_type = \""; |
328 | GetForwardCompilerType().DumpTypeDescription(s); |
329 | *s << '"'; |
330 | } else if (m_encoding_uid != LLDB_INVALID_UID) { |
331 | s->Printf(format: ", type_uid = 0x%8.8"PRIx64, m_encoding_uid); |
332 | switch (m_encoding_uid_type) { |
333 | case eEncodingInvalid: |
334 | break; |
335 | case eEncodingIsUID: |
336 | s->PutCString(cstr: " (unresolved type)"); |
337 | break; |
338 | case eEncodingIsConstUID: |
339 | s->PutCString(cstr: " (unresolved const type)"); |
340 | break; |
341 | case eEncodingIsRestrictUID: |
342 | s->PutCString(cstr: " (unresolved restrict type)"); |
343 | break; |
344 | case eEncodingIsVolatileUID: |
345 | s->PutCString(cstr: " (unresolved volatile type)"); |
346 | break; |
347 | case eEncodingIsAtomicUID: |
348 | s->PutCString(cstr: " (unresolved atomic type)"); |
349 | break; |
350 | case eEncodingIsTypedefUID: |
351 | s->PutCString(cstr: " (unresolved typedef)"); |
352 | break; |
353 | case eEncodingIsPointerUID: |
354 | s->PutCString(cstr: " (unresolved pointer)"); |
355 | break; |
356 | case eEncodingIsLValueReferenceUID: |
357 | s->PutCString(cstr: " (unresolved L value reference)"); |
358 | break; |
359 | case eEncodingIsRValueReferenceUID: |
360 | s->PutCString(cstr: " (unresolved R value reference)"); |
361 | break; |
362 | case eEncodingIsSyntheticUID: |
363 | s->PutCString(cstr: " (synthetic type)"); |
364 | break; |
365 | case eEncodingIsLLVMPtrAuthUID: |
366 | s->PutCString(cstr: " (ptrauth type)"); |
367 | break; |
368 | } |
369 | } |
370 | } |
371 | |
372 | void Type::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) { |
373 | s->Printf(format: "%p: ", static_cast<void *>(this)); |
374 | s->Indent(); |
375 | *s << "Type"<< static_cast<const UserID &>(*this) << ' '; |
376 | if (m_name) |
377 | *s << ", name = \""<< m_name << "\""; |
378 | |
379 | if (m_byte_size_has_value) |
380 | s->Printf(format: ", size = %"PRIu64, m_byte_size); |
381 | |
382 | if (show_context && m_context != nullptr) { |
383 | s->PutCString(cstr: ", context = ( "); |
384 | m_context->DumpSymbolContext(s); |
385 | s->PutCString(cstr: " )"); |
386 | } |
387 | |
388 | bool show_fullpaths = false; |
389 | m_decl.Dump(s, show_fullpaths); |
390 | |
391 | if (m_compiler_type.IsValid()) { |
392 | *s << ", compiler_type = "<< m_compiler_type.GetOpaqueQualType() << ' '; |
393 | GetForwardCompilerType().DumpTypeDescription(s, level); |
394 | } else if (m_encoding_uid != LLDB_INVALID_UID) { |
395 | s->Format(format: ", type_data = {0:x-16}", args&: m_encoding_uid); |
396 | switch (m_encoding_uid_type) { |
397 | case eEncodingInvalid: |
398 | break; |
399 | case eEncodingIsUID: |
400 | s->PutCString(cstr: " (unresolved type)"); |
401 | break; |
402 | case eEncodingIsConstUID: |
403 | s->PutCString(cstr: " (unresolved const type)"); |
404 | break; |
405 | case eEncodingIsRestrictUID: |
406 | s->PutCString(cstr: " (unresolved restrict type)"); |
407 | break; |
408 | case eEncodingIsVolatileUID: |
409 | s->PutCString(cstr: " (unresolved volatile type)"); |
410 | break; |
411 | case eEncodingIsAtomicUID: |
412 | s->PutCString(cstr: " (unresolved atomic type)"); |
413 | break; |
414 | case eEncodingIsTypedefUID: |
415 | s->PutCString(cstr: " (unresolved typedef)"); |
416 | break; |
417 | case eEncodingIsPointerUID: |
418 | s->PutCString(cstr: " (unresolved pointer)"); |
419 | break; |
420 | case eEncodingIsLValueReferenceUID: |
421 | s->PutCString(cstr: " (unresolved L value reference)"); |
422 | break; |
423 | case eEncodingIsRValueReferenceUID: |
424 | s->PutCString(cstr: " (unresolved R value reference)"); |
425 | break; |
426 | case eEncodingIsSyntheticUID: |
427 | s->PutCString(cstr: " (synthetic type)"); |
428 | break; |
429 | case eEncodingIsLLVMPtrAuthUID: |
430 | s->PutCString(cstr: " (ptrauth type)"); |
431 | } |
432 | } |
433 | |
434 | // |
435 | // if (m_access) |
436 | // s->Printf(", access = %u", m_access); |
437 | s->EOL(); |
438 | } |
439 | |
440 | ConstString Type::GetName() { |
441 | if (!m_name) |
442 | m_name = GetForwardCompilerType().GetTypeName(); |
443 | return m_name; |
444 | } |
445 | |
446 | ConstString Type::GetBaseName() { |
447 | return GetForwardCompilerType().GetTypeName(/*BaseOnly*/ true); |
448 | } |
449 | |
450 | void Type::DumpTypeName(Stream *s) { GetName().Dump(s, value_if_empty: "<invalid-type-name>"); } |
451 | |
452 | Type *Type::GetEncodingType() { |
453 | if (m_encoding_type == nullptr && m_encoding_uid != LLDB_INVALID_UID) |
454 | m_encoding_type = m_symbol_file->ResolveTypeUID(type_uid: m_encoding_uid); |
455 | return m_encoding_type; |
456 | } |
457 | |
458 | llvm::Expected<uint64_t> Type::GetByteSize(ExecutionContextScope *exe_scope) { |
459 | if (m_byte_size_has_value) |
460 | return static_cast<uint64_t>(m_byte_size); |
461 | |
462 | switch (m_encoding_uid_type) { |
463 | case eEncodingInvalid: |
464 | return llvm::createStringError(Fmt: "could not get type size: invalid encoding"); |
465 | |
466 | case eEncodingIsSyntheticUID: |
467 | return llvm::createStringError( |
468 | Fmt: "could not get type size: synthetic encoding"); |
469 | |
470 | case eEncodingIsUID: |
471 | case eEncodingIsConstUID: |
472 | case eEncodingIsRestrictUID: |
473 | case eEncodingIsVolatileUID: |
474 | case eEncodingIsAtomicUID: |
475 | case eEncodingIsTypedefUID: { |
476 | Type *encoding_type = GetEncodingType(); |
477 | if (encoding_type) |
478 | if (std::optional<uint64_t> size = |
479 | llvm::expectedToOptional(E: encoding_type->GetByteSize(exe_scope))) { |
480 | m_byte_size = *size; |
481 | m_byte_size_has_value = true; |
482 | return static_cast<uint64_t>(m_byte_size); |
483 | } |
484 | |
485 | auto size_or_err = GetLayoutCompilerType().GetByteSize(exe_scope); |
486 | if (!size_or_err) |
487 | return size_or_err.takeError(); |
488 | m_byte_size = *size_or_err; |
489 | m_byte_size_has_value = true; |
490 | return static_cast<uint64_t>(m_byte_size); |
491 | } break; |
492 | |
493 | // If we are a pointer or reference, then this is just a pointer size; |
494 | case eEncodingIsPointerUID: |
495 | case eEncodingIsLValueReferenceUID: |
496 | case eEncodingIsRValueReferenceUID: |
497 | case eEncodingIsLLVMPtrAuthUID: { |
498 | if (ArchSpec arch = m_symbol_file->GetObjectFile()->GetArchitecture()) { |
499 | m_byte_size = arch.GetAddressByteSize(); |
500 | m_byte_size_has_value = true; |
501 | return static_cast<uint64_t>(m_byte_size); |
502 | } |
503 | } break; |
504 | } |
505 | return llvm::createStringError( |
506 | Fmt: "could not get type size: unexpected encoding"); |
507 | } |
508 | |
509 | llvm::Expected<uint32_t> Type::GetNumChildren(bool omit_empty_base_classes) { |
510 | return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes, exe_ctx: nullptr); |
511 | } |
512 | |
513 | bool Type::IsAggregateType() { |
514 | return GetForwardCompilerType().IsAggregateType(); |
515 | } |
516 | |
517 | bool Type::IsTemplateType() { |
518 | return GetForwardCompilerType().IsTemplateType(); |
519 | } |
520 | |
521 | lldb::TypeSP Type::GetTypedefType() { |
522 | lldb::TypeSP type_sp; |
523 | if (IsTypedef()) { |
524 | Type *typedef_type = m_symbol_file->ResolveTypeUID(type_uid: m_encoding_uid); |
525 | if (typedef_type) |
526 | type_sp = typedef_type->shared_from_this(); |
527 | } |
528 | return type_sp; |
529 | } |
530 | |
531 | lldb::Format Type::GetFormat() { return GetForwardCompilerType().GetFormat(); } |
532 | |
533 | lldb::Encoding Type::GetEncoding(uint64_t &count) { |
534 | // Make sure we resolve our type if it already hasn't been. |
535 | return GetForwardCompilerType().GetEncoding(count); |
536 | } |
537 | |
538 | bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, |
539 | AddressType address_type, DataExtractor &data) { |
540 | if (address_type == eAddressTypeFile) { |
541 | // Can't convert a file address to anything valid without more context |
542 | // (which Module it came from) |
543 | return false; |
544 | } |
545 | |
546 | const uint64_t byte_size = |
547 | llvm::expectedToOptional( |
548 | E: GetByteSize(exe_scope: exe_ctx ? exe_ctx->GetBestExecutionContextScope() |
549 | : nullptr)) |
550 | .value_or(u: 0); |
551 | if (data.GetByteSize() < byte_size) { |
552 | lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); |
553 | data.SetData(data_sp); |
554 | } |
555 | |
556 | uint8_t *dst = const_cast<uint8_t *>(data.PeekData(offset: 0, length: byte_size)); |
557 | if (dst != nullptr) { |
558 | if (address_type == eAddressTypeHost) { |
559 | // The address is an address in this process, so just copy it |
560 | if (addr == 0) |
561 | return false; |
562 | memcpy(dest: dst, src: reinterpret_cast<uint8_t *>(addr), n: byte_size); |
563 | return true; |
564 | } else { |
565 | if (exe_ctx) { |
566 | Process *process = exe_ctx->GetProcessPtr(); |
567 | if (process) { |
568 | Status error; |
569 | return exe_ctx->GetProcessPtr()->ReadMemory(vm_addr: addr, buf: dst, size: byte_size, |
570 | error) == byte_size; |
571 | } |
572 | } |
573 | } |
574 | } |
575 | return false; |
576 | } |
577 | |
578 | bool Type::WriteToMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, |
579 | AddressType address_type, DataExtractor &data) { |
580 | return false; |
581 | } |
582 | |
583 | const Declaration &Type::GetDeclaration() const { return m_decl; } |
584 | |
585 | bool Type::ResolveCompilerType(ResolveState compiler_type_resolve_state) { |
586 | // TODO: This needs to consider the correct type system to use. |
587 | Type *encoding_type = nullptr; |
588 | if (!m_compiler_type.IsValid()) { |
589 | encoding_type = GetEncodingType(); |
590 | if (encoding_type) { |
591 | switch (m_encoding_uid_type) { |
592 | case eEncodingIsUID: { |
593 | CompilerType encoding_compiler_type = |
594 | encoding_type->GetForwardCompilerType(); |
595 | if (encoding_compiler_type.IsValid()) { |
596 | m_compiler_type = encoding_compiler_type; |
597 | m_compiler_type_resolve_state = |
598 | encoding_type->m_compiler_type_resolve_state; |
599 | } |
600 | } break; |
601 | |
602 | case eEncodingIsConstUID: |
603 | m_compiler_type = |
604 | encoding_type->GetForwardCompilerType().AddConstModifier(); |
605 | break; |
606 | |
607 | case eEncodingIsRestrictUID: |
608 | m_compiler_type = |
609 | encoding_type->GetForwardCompilerType().AddRestrictModifier(); |
610 | break; |
611 | |
612 | case eEncodingIsVolatileUID: |
613 | m_compiler_type = |
614 | encoding_type->GetForwardCompilerType().AddVolatileModifier(); |
615 | break; |
616 | |
617 | case eEncodingIsAtomicUID: |
618 | m_compiler_type = |
619 | encoding_type->GetForwardCompilerType().GetAtomicType(); |
620 | break; |
621 | |
622 | case eEncodingIsTypedefUID: |
623 | m_compiler_type = encoding_type->GetForwardCompilerType().CreateTypedef( |
624 | name: m_name.AsCString(value_if_empty: "__lldb_invalid_typedef_name"), |
625 | decl_ctx: GetSymbolFile()->GetDeclContextContainingUID(uid: GetID()), payload: m_payload); |
626 | m_name.Clear(); |
627 | break; |
628 | |
629 | case eEncodingIsPointerUID: |
630 | m_compiler_type = |
631 | encoding_type->GetForwardCompilerType().GetPointerType(); |
632 | break; |
633 | |
634 | case eEncodingIsLValueReferenceUID: |
635 | m_compiler_type = |
636 | encoding_type->GetForwardCompilerType().GetLValueReferenceType(); |
637 | break; |
638 | |
639 | case eEncodingIsRValueReferenceUID: |
640 | m_compiler_type = |
641 | encoding_type->GetForwardCompilerType().GetRValueReferenceType(); |
642 | break; |
643 | |
644 | case eEncodingIsLLVMPtrAuthUID: |
645 | m_compiler_type = |
646 | encoding_type->GetForwardCompilerType().AddPtrAuthModifier( |
647 | payload: m_payload); |
648 | break; |
649 | |
650 | default: |
651 | llvm_unreachable("Unhandled encoding_data_type."); |
652 | } |
653 | } else { |
654 | // We have no encoding type, return void? |
655 | auto type_system_or_err = |
656 | m_symbol_file->GetTypeSystemForLanguage(language: eLanguageTypeC); |
657 | if (auto err = type_system_or_err.takeError()) { |
658 | LLDB_LOG_ERROR( |
659 | GetLog(LLDBLog::Symbols), std::move(err), |
660 | "Unable to construct void type from TypeSystemClang: {0}"); |
661 | } else { |
662 | CompilerType void_compiler_type; |
663 | auto ts = *type_system_or_err; |
664 | if (ts) |
665 | void_compiler_type = ts->GetBasicTypeFromAST(basic_type: eBasicTypeVoid); |
666 | switch (m_encoding_uid_type) { |
667 | case eEncodingIsUID: |
668 | m_compiler_type = void_compiler_type; |
669 | break; |
670 | |
671 | case eEncodingIsConstUID: |
672 | m_compiler_type = void_compiler_type.AddConstModifier(); |
673 | break; |
674 | |
675 | case eEncodingIsRestrictUID: |
676 | m_compiler_type = void_compiler_type.AddRestrictModifier(); |
677 | break; |
678 | |
679 | case eEncodingIsVolatileUID: |
680 | m_compiler_type = void_compiler_type.AddVolatileModifier(); |
681 | break; |
682 | |
683 | case eEncodingIsAtomicUID: |
684 | m_compiler_type = void_compiler_type.GetAtomicType(); |
685 | break; |
686 | |
687 | case eEncodingIsTypedefUID: |
688 | m_compiler_type = void_compiler_type.CreateTypedef( |
689 | name: m_name.AsCString(value_if_empty: "__lldb_invalid_typedef_name"), |
690 | decl_ctx: GetSymbolFile()->GetDeclContextContainingUID(uid: GetID()), payload: m_payload); |
691 | break; |
692 | |
693 | case eEncodingIsPointerUID: |
694 | m_compiler_type = void_compiler_type.GetPointerType(); |
695 | break; |
696 | |
697 | case eEncodingIsLValueReferenceUID: |
698 | m_compiler_type = void_compiler_type.GetLValueReferenceType(); |
699 | break; |
700 | |
701 | case eEncodingIsRValueReferenceUID: |
702 | m_compiler_type = void_compiler_type.GetRValueReferenceType(); |
703 | break; |
704 | |
705 | case eEncodingIsLLVMPtrAuthUID: |
706 | llvm_unreachable("Cannot handle eEncodingIsLLVMPtrAuthUID without " |
707 | "valid encoding_type"); |
708 | |
709 | default: |
710 | llvm_unreachable("Unhandled encoding_data_type."); |
711 | } |
712 | } |
713 | } |
714 | |
715 | // When we have a EncodingUID, our "m_flags.compiler_type_resolve_state" is |
716 | // set to eResolveStateUnresolved so we need to update it to say that we |
717 | // now have a forward declaration since that is what we created above. |
718 | if (m_compiler_type.IsValid()) |
719 | m_compiler_type_resolve_state = ResolveState::Forward; |
720 | } |
721 | |
722 | // Check if we have a forward reference to a class/struct/union/enum? |
723 | if (compiler_type_resolve_state == ResolveState::Layout || |
724 | compiler_type_resolve_state == ResolveState::Full) { |
725 | // Check if we have a forward reference to a class/struct/union/enum? |
726 | if (m_compiler_type.IsValid() && |
727 | m_compiler_type_resolve_state < compiler_type_resolve_state) { |
728 | m_compiler_type_resolve_state = ResolveState::Full; |
729 | if (!m_compiler_type.IsDefined()) { |
730 | // We have a forward declaration, we need to resolve it to a complete |
731 | // definition. |
732 | m_symbol_file->CompleteType(compiler_type&: m_compiler_type); |
733 | } |
734 | } |
735 | } |
736 | |
737 | // If we have an encoding type, then we need to make sure it is resolved |
738 | // appropriately. |
739 | if (m_encoding_uid != LLDB_INVALID_UID) { |
740 | if (encoding_type == nullptr) |
741 | encoding_type = GetEncodingType(); |
742 | if (encoding_type) { |
743 | ResolveState encoding_compiler_type_resolve_state = |
744 | compiler_type_resolve_state; |
745 | |
746 | if (compiler_type_resolve_state == ResolveState::Layout) { |
747 | switch (m_encoding_uid_type) { |
748 | case eEncodingIsPointerUID: |
749 | case eEncodingIsLValueReferenceUID: |
750 | case eEncodingIsRValueReferenceUID: |
751 | encoding_compiler_type_resolve_state = ResolveState::Forward; |
752 | break; |
753 | default: |
754 | break; |
755 | } |
756 | } |
757 | encoding_type->ResolveCompilerType(compiler_type_resolve_state: encoding_compiler_type_resolve_state); |
758 | } |
759 | } |
760 | return m_compiler_type.IsValid(); |
761 | } |
762 | uint32_t Type::GetEncodingMask() { |
763 | uint32_t encoding_mask = 1u << m_encoding_uid_type; |
764 | Type *encoding_type = GetEncodingType(); |
765 | assert(encoding_type != this); |
766 | if (encoding_type) |
767 | encoding_mask |= encoding_type->GetEncodingMask(); |
768 | return encoding_mask; |
769 | } |
770 | |
771 | CompilerType Type::GetFullCompilerType() { |
772 | ResolveCompilerType(compiler_type_resolve_state: ResolveState::Full); |
773 | return m_compiler_type; |
774 | } |
775 | |
776 | CompilerType Type::GetLayoutCompilerType() { |
777 | ResolveCompilerType(compiler_type_resolve_state: ResolveState::Layout); |
778 | return m_compiler_type; |
779 | } |
780 | |
781 | CompilerType Type::GetForwardCompilerType() { |
782 | ResolveCompilerType(compiler_type_resolve_state: ResolveState::Forward); |
783 | return m_compiler_type; |
784 | } |
785 | |
786 | ConstString Type::GetQualifiedName() { |
787 | return GetForwardCompilerType().GetTypeName(); |
788 | } |
789 | |
790 | std::optional<Type::ParsedName> |
791 | Type::GetTypeScopeAndBasename(llvm::StringRef name) { |
792 | ParsedName result; |
793 | |
794 | if (name.empty()) |
795 | return std::nullopt; |
796 | |
797 | if (name.consume_front(Prefix: "struct ")) |
798 | result.type_class = eTypeClassStruct; |
799 | else if (name.consume_front(Prefix: "class ")) |
800 | result.type_class = eTypeClassClass; |
801 | else if (name.consume_front(Prefix: "union ")) |
802 | result.type_class = eTypeClassUnion; |
803 | else if (name.consume_front(Prefix: "enum ")) |
804 | result.type_class = eTypeClassEnumeration; |
805 | else if (name.consume_front(Prefix: "typedef ")) |
806 | result.type_class = eTypeClassTypedef; |
807 | |
808 | if (name.consume_front(Prefix: "::")) |
809 | result.scope.push_back(Elt: "::"); |
810 | |
811 | bool prev_is_colon = false; |
812 | size_t template_depth = 0; |
813 | size_t name_begin = 0; |
814 | for (const auto &pos : llvm::enumerate(First&: name)) { |
815 | switch (pos.value()) { |
816 | case ':': |
817 | if (prev_is_colon && template_depth == 0) { |
818 | llvm::StringRef scope_name = name.slice(Start: name_begin, End: pos.index() - 1); |
819 | // The itanium demangler uses this string to represent anonymous |
820 | // namespaces. Convert it to a more language-agnostic form (which is |
821 | // also used in DWARF). |
822 | if (scope_name == "(anonymous namespace)") |
823 | scope_name = ""; |
824 | result.scope.push_back(Elt: scope_name); |
825 | name_begin = pos.index() + 1; |
826 | } |
827 | break; |
828 | case '<': |
829 | ++template_depth; |
830 | break; |
831 | case '>': |
832 | if (template_depth == 0) |
833 | return std::nullopt; // Invalid name. |
834 | --template_depth; |
835 | break; |
836 | } |
837 | prev_is_colon = pos.value() == ':'; |
838 | } |
839 | |
840 | if (name_begin < name.size() && template_depth == 0) |
841 | result.basename = name.substr(Start: name_begin); |
842 | else |
843 | return std::nullopt; |
844 | |
845 | return result; |
846 | } |
847 | |
848 | ModuleSP Type::GetModule() { |
849 | if (m_symbol_file) |
850 | return m_symbol_file->GetObjectFile()->GetModule(); |
851 | return ModuleSP(); |
852 | } |
853 | |
854 | ModuleSP Type::GetExeModule() { |
855 | if (m_compiler_type) { |
856 | auto ts = m_compiler_type.GetTypeSystem(); |
857 | if (!ts) |
858 | return {}; |
859 | SymbolFile *symbol_file = ts->GetSymbolFile(); |
860 | if (symbol_file) |
861 | return symbol_file->GetObjectFile()->GetModule(); |
862 | } |
863 | return {}; |
864 | } |
865 | |
866 | TypeAndOrName::TypeAndOrName(TypeSP &in_type_sp) { |
867 | if (in_type_sp) { |
868 | m_compiler_type = in_type_sp->GetForwardCompilerType(); |
869 | m_type_name = in_type_sp->GetName(); |
870 | } |
871 | } |
872 | |
873 | TypeAndOrName::TypeAndOrName(const char *in_type_str) |
874 | : m_type_name(in_type_str) {} |
875 | |
876 | TypeAndOrName::TypeAndOrName(ConstString &in_type_const_string) |
877 | : m_type_name(in_type_const_string) {} |
878 | |
879 | bool TypeAndOrName::operator==(const TypeAndOrName &other) const { |
880 | if (m_compiler_type != other.m_compiler_type) |
881 | return false; |
882 | if (m_type_name != other.m_type_name) |
883 | return false; |
884 | return true; |
885 | } |
886 | |
887 | bool TypeAndOrName::operator!=(const TypeAndOrName &other) const { |
888 | return !(*this == other); |
889 | } |
890 | |
891 | ConstString TypeAndOrName::GetName() const { |
892 | if (m_type_name) |
893 | return m_type_name; |
894 | if (m_compiler_type) |
895 | return m_compiler_type.GetTypeName(); |
896 | return ConstString("<invalid>"); |
897 | } |
898 | |
899 | void TypeAndOrName::SetName(ConstString type_name) { |
900 | m_type_name = type_name; |
901 | } |
902 | |
903 | void TypeAndOrName::SetName(const char *type_name_cstr) { |
904 | m_type_name.SetCString(type_name_cstr); |
905 | } |
906 | |
907 | void TypeAndOrName::SetName(llvm::StringRef type_name) { |
908 | m_type_name.SetString(type_name); |
909 | } |
910 | |
911 | void TypeAndOrName::SetTypeSP(lldb::TypeSP type_sp) { |
912 | if (type_sp) { |
913 | m_compiler_type = type_sp->GetForwardCompilerType(); |
914 | m_type_name = type_sp->GetName(); |
915 | } else |
916 | Clear(); |
917 | } |
918 | |
919 | void TypeAndOrName::SetCompilerType(CompilerType compiler_type) { |
920 | m_compiler_type = compiler_type; |
921 | if (m_compiler_type) |
922 | m_type_name = m_compiler_type.GetTypeName(); |
923 | } |
924 | |
925 | bool TypeAndOrName::IsEmpty() const { |
926 | return !((bool)m_type_name || (bool)m_compiler_type); |
927 | } |
928 | |
929 | void TypeAndOrName::Clear() { |
930 | m_type_name.Clear(); |
931 | m_compiler_type.Clear(); |
932 | } |
933 | |
934 | bool TypeAndOrName::HasName() const { return (bool)m_type_name; } |
935 | |
936 | bool TypeAndOrName::HasCompilerType() const { |
937 | return m_compiler_type.IsValid(); |
938 | } |
939 | |
940 | TypeImpl::TypeImpl(const lldb::TypeSP &type_sp) |
941 | : m_module_wp(), m_static_type(), m_dynamic_type() { |
942 | SetType(type_sp); |
943 | } |
944 | |
945 | TypeImpl::TypeImpl(const CompilerType &compiler_type) |
946 | : m_module_wp(), m_static_type(), m_dynamic_type() { |
947 | SetType(compiler_type); |
948 | } |
949 | |
950 | TypeImpl::TypeImpl(const lldb::TypeSP &type_sp, const CompilerType &dynamic) |
951 | : m_module_wp(), m_static_type(), m_dynamic_type(dynamic) { |
952 | SetType(type_sp, dynamic); |
953 | } |
954 | |
955 | TypeImpl::TypeImpl(const CompilerType &static_type, |
956 | const CompilerType &dynamic_type) |
957 | : m_module_wp(), m_static_type(), m_dynamic_type() { |
958 | SetType(compiler_type: static_type, dynamic: dynamic_type); |
959 | } |
960 | |
961 | void TypeImpl::SetType(const lldb::TypeSP &type_sp) { |
962 | if (type_sp) { |
963 | m_static_type = type_sp->GetForwardCompilerType(); |
964 | m_exe_module_wp = type_sp->GetExeModule(); |
965 | m_module_wp = type_sp->GetModule(); |
966 | } else { |
967 | m_static_type.Clear(); |
968 | m_module_wp = lldb::ModuleWP(); |
969 | } |
970 | } |
971 | |
972 | void TypeImpl::SetType(const CompilerType &compiler_type) { |
973 | m_module_wp = lldb::ModuleWP(); |
974 | m_static_type = compiler_type; |
975 | } |
976 | |
977 | void TypeImpl::SetType(const lldb::TypeSP &type_sp, |
978 | const CompilerType &dynamic) { |
979 | SetType(type_sp); |
980 | m_dynamic_type = dynamic; |
981 | } |
982 | |
983 | void TypeImpl::SetType(const CompilerType &compiler_type, |
984 | const CompilerType &dynamic) { |
985 | m_module_wp = lldb::ModuleWP(); |
986 | m_static_type = compiler_type; |
987 | m_dynamic_type = dynamic; |
988 | } |
989 | |
990 | bool TypeImpl::CheckModule(lldb::ModuleSP &module_sp) const { |
991 | return CheckModuleCommon(input_module_wp: m_module_wp, module_sp); |
992 | } |
993 | |
994 | bool TypeImpl::CheckExeModule(lldb::ModuleSP &module_sp) const { |
995 | return CheckModuleCommon(input_module_wp: m_exe_module_wp, module_sp); |
996 | } |
997 | |
998 | bool TypeImpl::CheckModuleCommon(const lldb::ModuleWP &input_module_wp, |
999 | lldb::ModuleSP &module_sp) const { |
1000 | // Check if we have a module for this type. If we do and the shared pointer |
1001 | // is can be successfully initialized with m_module_wp, return true. Else |
1002 | // return false if we didn't have a module, or if we had a module and it has |
1003 | // been deleted. Any functions doing anything with a TypeSP in this TypeImpl |
1004 | // class should call this function and only do anything with the ivars if |
1005 | // this function returns true. If we have a module, the "module_sp" will be |
1006 | // filled in with a strong reference to the module so that the module will at |
1007 | // least stay around long enough for the type query to succeed. |
1008 | module_sp = input_module_wp.lock(); |
1009 | if (!module_sp) { |
1010 | lldb::ModuleWP empty_module_wp; |
1011 | // If either call to "std::weak_ptr::owner_before(...) value returns true, |
1012 | // this indicates that m_module_wp once contained (possibly still does) a |
1013 | // reference to a valid shared pointer. This helps us know if we had a |
1014 | // valid reference to a section which is now invalid because the module it |
1015 | // was in was deleted |
1016 | if (empty_module_wp.owner_before(rhs: input_module_wp) || |
1017 | input_module_wp.owner_before(rhs: empty_module_wp)) { |
1018 | // input_module_wp had a valid reference to a module, but all strong |
1019 | // references have been released and the module has been deleted |
1020 | return false; |
1021 | } |
1022 | } |
1023 | // We either successfully locked the module, or didn't have one to begin with |
1024 | return true; |
1025 | } |
1026 | |
1027 | bool TypeImpl::operator==(const TypeImpl &rhs) const { |
1028 | return m_static_type == rhs.m_static_type && |
1029 | m_dynamic_type == rhs.m_dynamic_type; |
1030 | } |
1031 | |
1032 | bool TypeImpl::operator!=(const TypeImpl &rhs) const { |
1033 | return !(*this == rhs); |
1034 | } |
1035 | |
1036 | bool TypeImpl::IsValid() const { |
1037 | // just a name is not valid |
1038 | ModuleSP module_sp; |
1039 | if (CheckModule(module_sp)) |
1040 | return m_static_type.IsValid() || m_dynamic_type.IsValid(); |
1041 | return false; |
1042 | } |
1043 | |
1044 | TypeImpl::operator bool() const { return IsValid(); } |
1045 | |
1046 | void TypeImpl::Clear() { |
1047 | m_module_wp = lldb::ModuleWP(); |
1048 | m_static_type.Clear(); |
1049 | m_dynamic_type.Clear(); |
1050 | } |
1051 | |
1052 | ModuleSP TypeImpl::GetModule() const { |
1053 | lldb::ModuleSP module_sp; |
1054 | if (CheckExeModule(module_sp)) |
1055 | return module_sp; |
1056 | return nullptr; |
1057 | } |
1058 | |
1059 | ConstString TypeImpl::GetName() const { |
1060 | ModuleSP module_sp; |
1061 | if (CheckModule(module_sp)) { |
1062 | if (m_dynamic_type) |
1063 | return m_dynamic_type.GetTypeName(); |
1064 | return m_static_type.GetTypeName(); |
1065 | } |
1066 | return ConstString(); |
1067 | } |
1068 | |
1069 | ConstString TypeImpl::GetDisplayTypeName() const { |
1070 | ModuleSP module_sp; |
1071 | if (CheckModule(module_sp)) { |
1072 | if (m_dynamic_type) |
1073 | return m_dynamic_type.GetDisplayTypeName(); |
1074 | return m_static_type.GetDisplayTypeName(); |
1075 | } |
1076 | return ConstString(); |
1077 | } |
1078 | |
1079 | TypeImpl TypeImpl::GetPointerType() const { |
1080 | ModuleSP module_sp; |
1081 | if (CheckModule(module_sp)) { |
1082 | if (m_dynamic_type.IsValid()) { |
1083 | return TypeImpl(m_static_type.GetPointerType(), |
1084 | m_dynamic_type.GetPointerType()); |
1085 | } |
1086 | return TypeImpl(m_static_type.GetPointerType()); |
1087 | } |
1088 | return TypeImpl(); |
1089 | } |
1090 | |
1091 | TypeImpl TypeImpl::GetPointeeType() const { |
1092 | ModuleSP module_sp; |
1093 | if (CheckModule(module_sp)) { |
1094 | if (m_dynamic_type.IsValid()) { |
1095 | return TypeImpl(m_static_type.GetPointeeType(), |
1096 | m_dynamic_type.GetPointeeType()); |
1097 | } |
1098 | return TypeImpl(m_static_type.GetPointeeType()); |
1099 | } |
1100 | return TypeImpl(); |
1101 | } |
1102 | |
1103 | TypeImpl TypeImpl::GetReferenceType() const { |
1104 | ModuleSP module_sp; |
1105 | if (CheckModule(module_sp)) { |
1106 | if (m_dynamic_type.IsValid()) { |
1107 | return TypeImpl(m_static_type.GetLValueReferenceType(), |
1108 | m_dynamic_type.GetLValueReferenceType()); |
1109 | } |
1110 | return TypeImpl(m_static_type.GetLValueReferenceType()); |
1111 | } |
1112 | return TypeImpl(); |
1113 | } |
1114 | |
1115 | TypeImpl TypeImpl::GetTypedefedType() const { |
1116 | ModuleSP module_sp; |
1117 | if (CheckModule(module_sp)) { |
1118 | if (m_dynamic_type.IsValid()) { |
1119 | return TypeImpl(m_static_type.GetTypedefedType(), |
1120 | m_dynamic_type.GetTypedefedType()); |
1121 | } |
1122 | return TypeImpl(m_static_type.GetTypedefedType()); |
1123 | } |
1124 | return TypeImpl(); |
1125 | } |
1126 | |
1127 | TypeImpl TypeImpl::GetDereferencedType() const { |
1128 | ModuleSP module_sp; |
1129 | if (CheckModule(module_sp)) { |
1130 | if (m_dynamic_type.IsValid()) { |
1131 | return TypeImpl(m_static_type.GetNonReferenceType(), |
1132 | m_dynamic_type.GetNonReferenceType()); |
1133 | } |
1134 | return TypeImpl(m_static_type.GetNonReferenceType()); |
1135 | } |
1136 | return TypeImpl(); |
1137 | } |
1138 | |
1139 | TypeImpl TypeImpl::GetUnqualifiedType() const { |
1140 | ModuleSP module_sp; |
1141 | if (CheckModule(module_sp)) { |
1142 | if (m_dynamic_type.IsValid()) { |
1143 | return TypeImpl(m_static_type.GetFullyUnqualifiedType(), |
1144 | m_dynamic_type.GetFullyUnqualifiedType()); |
1145 | } |
1146 | return TypeImpl(m_static_type.GetFullyUnqualifiedType()); |
1147 | } |
1148 | return TypeImpl(); |
1149 | } |
1150 | |
1151 | TypeImpl TypeImpl::GetCanonicalType() const { |
1152 | ModuleSP module_sp; |
1153 | if (CheckModule(module_sp)) { |
1154 | if (m_dynamic_type.IsValid()) { |
1155 | return TypeImpl(m_static_type.GetCanonicalType(), |
1156 | m_dynamic_type.GetCanonicalType()); |
1157 | } |
1158 | return TypeImpl(m_static_type.GetCanonicalType()); |
1159 | } |
1160 | return TypeImpl(); |
1161 | } |
1162 | |
1163 | CompilerType TypeImpl::GetCompilerType(bool prefer_dynamic) { |
1164 | ModuleSP module_sp; |
1165 | if (CheckModule(module_sp)) { |
1166 | if (prefer_dynamic) { |
1167 | if (m_dynamic_type.IsValid()) |
1168 | return m_dynamic_type; |
1169 | } |
1170 | return m_static_type; |
1171 | } |
1172 | return CompilerType(); |
1173 | } |
1174 | |
1175 | CompilerType::TypeSystemSPWrapper TypeImpl::GetTypeSystem(bool prefer_dynamic) { |
1176 | ModuleSP module_sp; |
1177 | if (CheckModule(module_sp)) { |
1178 | if (prefer_dynamic) { |
1179 | if (m_dynamic_type.IsValid()) |
1180 | return m_dynamic_type.GetTypeSystem(); |
1181 | } |
1182 | return m_static_type.GetTypeSystem(); |
1183 | } |
1184 | return {}; |
1185 | } |
1186 | |
1187 | bool TypeImpl::GetDescription(lldb_private::Stream &strm, |
1188 | lldb::DescriptionLevel description_level) { |
1189 | ModuleSP module_sp; |
1190 | if (CheckModule(module_sp)) { |
1191 | if (m_dynamic_type.IsValid()) { |
1192 | strm.Printf(format: "Dynamic:\n"); |
1193 | m_dynamic_type.DumpTypeDescription(s: &strm); |
1194 | strm.Printf(format: "\nStatic:\n"); |
1195 | } |
1196 | m_static_type.DumpTypeDescription(s: &strm); |
1197 | } else { |
1198 | strm.PutCString(cstr: "Invalid TypeImpl module for type has been deleted\n"); |
1199 | } |
1200 | return true; |
1201 | } |
1202 | |
1203 | CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) { |
1204 | if (name.empty()) |
1205 | return CompilerType(); |
1206 | return GetCompilerType(/*prefer_dynamic=*/false) |
1207 | .GetDirectNestedTypeWithName(name); |
1208 | } |
1209 | |
1210 | bool TypeMemberFunctionImpl::IsValid() { |
1211 | return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown; |
1212 | } |
1213 | |
1214 | ConstString TypeMemberFunctionImpl::GetName() const { return m_name; } |
1215 | |
1216 | ConstString TypeMemberFunctionImpl::GetMangledName() const { |
1217 | return m_decl.GetMangledName(); |
1218 | } |
1219 | |
1220 | CompilerType TypeMemberFunctionImpl::GetType() const { return m_type; } |
1221 | |
1222 | lldb::MemberFunctionKind TypeMemberFunctionImpl::GetKind() const { |
1223 | return m_kind; |
1224 | } |
1225 | |
1226 | bool TypeMemberFunctionImpl::GetDescription(Stream &stream) { |
1227 | switch (m_kind) { |
1228 | case lldb::eMemberFunctionKindUnknown: |
1229 | return false; |
1230 | case lldb::eMemberFunctionKindConstructor: |
1231 | stream.Printf(format: "constructor for %s", |
1232 | m_type.GetTypeName().AsCString(value_if_empty: "<unknown>")); |
1233 | break; |
1234 | case lldb::eMemberFunctionKindDestructor: |
1235 | stream.Printf(format: "destructor for %s", |
1236 | m_type.GetTypeName().AsCString(value_if_empty: "<unknown>")); |
1237 | break; |
1238 | case lldb::eMemberFunctionKindInstanceMethod: |
1239 | stream.Printf(format: "instance method %s of type %s", m_name.AsCString(), |
1240 | m_decl.GetDeclContext().GetName().AsCString()); |
1241 | break; |
1242 | case lldb::eMemberFunctionKindStaticMethod: |
1243 | stream.Printf(format: "static method %s of type %s", m_name.AsCString(), |
1244 | m_decl.GetDeclContext().GetName().AsCString()); |
1245 | break; |
1246 | } |
1247 | return true; |
1248 | } |
1249 | |
1250 | CompilerType TypeMemberFunctionImpl::GetReturnType() const { |
1251 | if (m_type) |
1252 | return m_type.GetFunctionReturnType(); |
1253 | return m_decl.GetFunctionReturnType(); |
1254 | } |
1255 | |
1256 | size_t TypeMemberFunctionImpl::GetNumArguments() const { |
1257 | if (m_type) |
1258 | return m_type.GetNumberOfFunctionArguments(); |
1259 | else |
1260 | return m_decl.GetNumFunctionArguments(); |
1261 | } |
1262 | |
1263 | CompilerType TypeMemberFunctionImpl::GetArgumentAtIndex(size_t idx) const { |
1264 | if (m_type) |
1265 | return m_type.GetFunctionArgumentAtIndex(index: idx); |
1266 | else |
1267 | return m_decl.GetFunctionArgumentType(arg_idx: idx); |
1268 | } |
1269 | |
1270 | TypeEnumMemberImpl::TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, |
1271 | ConstString name, |
1272 | const llvm::APSInt &value) |
1273 | : m_integer_type_sp(integer_type_sp), m_name(name), m_value(value), |
1274 | m_valid((bool)name && (bool)integer_type_sp) |
1275 | |
1276 | {} |
1277 |
Definitions
- operator<<
- ConvertTypeClass
- TypeQuery
- TypeQuery
- TypeQuery
- TypeQuery
- GetTypeBasename
- AddLanguage
- SetLanguages
- ContextMatches
- LanguageMatches
- AlreadySearched
- InsertUnique
- Done
- Dump
- TypeAppendVisitor
- TypeAppendVisitor
- operator()
- Append
- SymbolFileType
- GetType
- Type
- Type
- GetDescription
- Dump
- GetName
- GetBaseName
- DumpTypeName
- GetEncodingType
- GetByteSize
- GetNumChildren
- IsAggregateType
- IsTemplateType
- GetTypedefType
- GetFormat
- GetEncoding
- ReadFromMemory
- WriteToMemory
- GetDeclaration
- ResolveCompilerType
- GetEncodingMask
- GetFullCompilerType
- GetLayoutCompilerType
- GetForwardCompilerType
- GetQualifiedName
- GetTypeScopeAndBasename
- GetModule
- GetExeModule
- TypeAndOrName
- TypeAndOrName
- TypeAndOrName
- operator==
- operator!=
- GetName
- SetName
- SetName
- SetName
- SetTypeSP
- SetCompilerType
- IsEmpty
- Clear
- HasName
- HasCompilerType
- TypeImpl
- TypeImpl
- TypeImpl
- TypeImpl
- SetType
- SetType
- SetType
- SetType
- CheckModule
- CheckExeModule
- CheckModuleCommon
- operator==
- operator!=
- IsValid
- operator bool
- Clear
- GetModule
- GetName
- GetDisplayTypeName
- GetPointerType
- GetPointeeType
- GetReferenceType
- GetTypedefedType
- GetDereferencedType
- GetUnqualifiedType
- GetCanonicalType
- GetCompilerType
- GetTypeSystem
- GetDescription
- FindDirectNestedType
- IsValid
- GetName
- GetMangledName
- GetType
- GetKind
- GetDescription
- GetReturnType
- GetNumArguments
- GetArgumentAtIndex
Improve your Profiling and Debugging skills
Find out more