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