1 | //===-- Type.h --------------------------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_SYMBOL_TYPE_H |
10 | #define LLDB_SYMBOL_TYPE_H |
11 | |
12 | #include "lldb/Core/Declaration.h" |
13 | #include "lldb/Symbol/CompilerDecl.h" |
14 | #include "lldb/Symbol/CompilerType.h" |
15 | #include "lldb/Symbol/TypeList.h" |
16 | #include "lldb/Symbol/TypeMap.h" |
17 | #include "lldb/Symbol/TypeSystem.h" |
18 | #include "lldb/Utility/ConstString.h" |
19 | #include "lldb/Utility/UserID.h" |
20 | #include "lldb/lldb-private.h" |
21 | |
22 | #include "llvm/ADT/APSInt.h" |
23 | #include "llvm/ADT/DenseSet.h" |
24 | |
25 | #include <optional> |
26 | #include <set> |
27 | |
28 | namespace lldb_private { |
29 | class SymbolFileCommon; |
30 | |
31 | /// A SmallBitVector that represents a set of source languages (\p |
32 | /// lldb::LanguageType). Each lldb::LanguageType is represented by |
33 | /// the bit with the position of its enumerator. The largest |
34 | /// LanguageType is < 64, so this is space-efficient and on 64-bit |
35 | /// architectures a LanguageSet can be completely stack-allocated. |
36 | struct LanguageSet { |
37 | llvm::SmallBitVector bitvector; |
38 | LanguageSet(); |
39 | |
40 | /// If the set contains a single language only, return it. |
41 | std::optional<lldb::LanguageType> GetSingularLanguage(); |
42 | void Insert(lldb::LanguageType language); |
43 | bool Empty() const; |
44 | size_t Size() const; |
45 | bool operator[](unsigned i) const; |
46 | }; |
47 | |
48 | /// CompilerContext allows an array of these items to be passed to perform |
49 | /// detailed lookups in SymbolVendor and SymbolFile functions. |
50 | struct CompilerContext { |
51 | CompilerContext(CompilerContextKind t, ConstString n) : kind(t), name(n) {} |
52 | |
53 | bool operator==(const CompilerContext &rhs) const { |
54 | return kind == rhs.kind && name == rhs.name; |
55 | } |
56 | bool operator!=(const CompilerContext &rhs) const { return !(*this == rhs); } |
57 | |
58 | void Dump(Stream &s) const; |
59 | |
60 | CompilerContextKind kind; |
61 | ConstString name; |
62 | }; |
63 | |
64 | /// Match \p context_chain against \p pattern, which may contain "Any" |
65 | /// kinds. The \p context_chain should *not* contain any "Any" kinds. |
66 | bool contextMatches(llvm::ArrayRef<CompilerContext> context_chain, |
67 | llvm::ArrayRef<CompilerContext> pattern); |
68 | |
69 | FLAGS_ENUM(TypeQueryOptions){ |
70 | e_none = 0u, |
71 | /// If set, TypeQuery::m_context contains an exact context that must match |
72 | /// the full context. If not set, TypeQuery::m_context can contain a partial |
73 | /// type match where the full context isn't fully specified. |
74 | e_exact_match = (1u << 0), |
75 | /// If set, TypeQuery::m_context is a clang module compiler context. If not |
76 | /// set TypeQuery::m_context is normal type lookup context. |
77 | e_module_search = (1u << 1), |
78 | /// When true, the find types call should stop the query as soon as a single |
79 | /// matching type is found. When false, the type query should find all |
80 | /// matching types. |
81 | e_find_one = (1u << 2), |
82 | }; |
83 | LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions) |
84 | |
85 | /// A class that contains all state required for type lookups. |
86 | /// |
87 | /// Using a TypeQuery class for matching types simplifies the internal APIs we |
88 | /// need to implement type lookups in LLDB. Type lookups can fully specify the |
89 | /// exact typename by filling out a complete or partial CompilerContext array. |
90 | /// This technique allows for powerful searches and also allows the SymbolFile |
91 | /// classes to use the m_context array to lookup types by basename, then |
92 | /// eliminate potential matches without having to resolve types into each |
93 | /// TypeSystem. This makes type lookups vastly more efficient and allows the |
94 | /// SymbolFile objects to stop looking up types when the type matching is |
95 | /// complete, like if we are looking for only a single type in our search. |
96 | class TypeQuery { |
97 | public: |
98 | TypeQuery() = delete; |
99 | |
100 | /// Construct a type match object using a fully- or partially-qualified name. |
101 | /// |
102 | /// The specified \a type_name will be chopped up and the m_context will be |
103 | /// populated by separating the string by looking for "::". We do this because |
104 | /// symbol files have indexes that contain only the type's basename. This also |
105 | /// allows symbol files to efficiently not realize types that don't match the |
106 | /// specified context. Example of \a type_name values that can be specified |
107 | /// include: |
108 | /// "foo": Look for any type whose basename matches "foo". |
109 | /// If \a exact_match is true, then the type can't be contained in any |
110 | /// declaration context like a namespace, class, or other containing |
111 | /// scope. |
112 | /// If \a exact match is false, then we will find all matches including |
113 | /// ones that are contained in other declaration contexts, including top |
114 | /// level types. |
115 | /// "foo::bar": Look for any type whose basename matches "bar" but make sure |
116 | /// its parent declaration context is any named declaration context |
117 | /// (namespace, class, struct, etc) whose name matches "foo". |
118 | /// If \a exact_match is true, then the "foo" declaration context must |
119 | /// appear at the source file level or inside of a function. |
120 | /// If \a exact match is false, then the "foo" declaration context can |
121 | /// be contained in any other declaration contexts. |
122 | /// "class foo": Only match types that are classes whose basename matches |
123 | /// "foo". |
124 | /// "struct foo": Only match types that are structures whose basename |
125 | /// matches "foo". |
126 | /// "class foo::bar": Only match types that are classes whose basename |
127 | /// matches "bar" and that are contained in any named declaration context |
128 | /// named "foo". |
129 | /// |
130 | /// \param[in] type_name |
131 | /// A fully- or partially-qualified type name. This name will be parsed and |
132 | /// broken up and the m_context will be populated with the various parts of |
133 | /// the name. This typename can be prefixed with "struct ", "class ", |
134 | /// "union", "enum " or "typedef " before the actual type name to limit the |
135 | /// results of the types that match. The declaration context can be |
136 | /// specified with the "::" string. For example, "a::b::my_type". |
137 | /// |
138 | /// \param[in] options A set of boolean enumeration flags from the |
139 | /// TypeQueryOptions enumerations. \see TypeQueryOptions. |
140 | TypeQuery(llvm::StringRef name, TypeQueryOptions options = e_none); |
141 | |
142 | /// Construct a type-match object that matches a type basename that exists |
143 | /// in the specified declaration context. |
144 | /// |
145 | /// This allows the m_context to be first populated using a declaration |
146 | /// context to exactly identify the containing declaration context of a type. |
147 | /// This can be used when you have a forward declaration to a type and you |
148 | /// need to search for its complete type. |
149 | /// |
150 | /// \param[in] decl_ctx |
151 | /// A declaration context object that comes from a TypeSystem plug-in. This |
152 | /// object will be asked to populate the array of CompilerContext objects |
153 | /// by adding the top most declaration context first into the array and then |
154 | /// adding any containing declaration contexts. |
155 | /// |
156 | /// \param[in] type_basename |
157 | /// The basename of the type to lookup in the specified declaration context. |
158 | /// |
159 | /// \param[in] options A set of boolean enumeration flags from the |
160 | /// TypeQueryOptions enumerations. \see TypeQueryOptions. |
161 | TypeQuery(const CompilerDeclContext &decl_ctx, ConstString type_basename, |
162 | TypeQueryOptions options = e_none); |
163 | /// Construct a type-match object using a compiler declaration that specifies |
164 | /// a typename and a declaration context to use when doing exact type lookups. |
165 | /// |
166 | /// This allows the m_context to be first populated using a type declaration. |
167 | /// The type declaration might have a declaration context and each TypeSystem |
168 | /// plug-in can populate the declaration context needed to perform an exact |
169 | /// lookup for a type. |
170 | /// This can be used when you have a forward declaration to a type and you |
171 | /// need to search for its complete type. |
172 | /// |
173 | /// \param[in] decl |
174 | /// A type declaration context object that comes from a TypeSystem plug-in. |
175 | /// This object will be asked to full the array of CompilerContext objects |
176 | /// by adding the top most declaration context first into the array and then |
177 | /// adding any containing declaration contexts, and ending with the exact |
178 | /// typename and the kind of type it is (class, struct, union, enum, etc). |
179 | /// |
180 | /// \param[in] options A set of boolean enumeration flags from the |
181 | /// TypeQueryOptions enumerations. \see TypeQueryOptions. |
182 | TypeQuery(const CompilerDecl &decl, TypeQueryOptions options = e_none); |
183 | |
184 | /// Construct a type-match object using a CompilerContext array. |
185 | /// |
186 | /// Clients can manually create compiler contexts and use these to find |
187 | /// matches when searching for types. There are two types of contexts that |
188 | /// are supported when doing type searchs: type contexts and clang module |
189 | /// contexts. Type contexts have contexts that specify the type and its |
190 | /// containing declaration context like namespaces and classes. Clang module |
191 | /// contexts specify contexts more completely to find exact matches within |
192 | /// clang module debug information. They will include the modules that the |
193 | /// type is included in and any functions that the type might be defined in. |
194 | /// This allows very fine-grained type resolution. |
195 | /// |
196 | /// \param[in] context The compiler context to use when doing the search. |
197 | /// |
198 | /// \param[in] options A set of boolean enumeration flags from the |
199 | /// TypeQueryOptions enumerations. \see TypeQueryOptions. |
200 | TypeQuery(const llvm::ArrayRef<lldb_private::CompilerContext> &context, |
201 | TypeQueryOptions options = e_none); |
202 | |
203 | /// Construct a type-match object that duplicates all matching criterea, |
204 | /// but not any searched symbol files or the type map for matches. This allows |
205 | /// the m_context to be modified prior to performing another search. |
206 | TypeQuery(const TypeQuery &rhs) = default; |
207 | /// Assign a type-match object that duplicates all matching criterea, |
208 | /// but not any searched symbol files or the type map for matches. This allows |
209 | /// the m_context to be modified prior to performing another search. |
210 | TypeQuery &operator=(const TypeQuery &rhs) = default; |
211 | |
212 | /// Check of a CompilerContext array from matching type from a symbol file |
213 | /// matches the \a m_context. |
214 | /// |
215 | /// \param[in] context |
216 | /// A fully qualified CompilerContext array for a potential match that is |
217 | /// created by the symbol file prior to trying to actually resolve a type. |
218 | /// |
219 | /// \returns |
220 | /// True if the context matches, false if it doesn't. If e_exact_match |
221 | /// is set in m_options, then \a context must exactly match \a m_context. If |
222 | /// e_exact_match is not set, then the bottom m_context.size() objects in |
223 | /// \a context must match. This allows SymbolFile objects the fill in a |
224 | /// potential type basename match from the index into \a context, and see if |
225 | /// it matches prior to having to resolve a lldb_private::Type object for |
226 | /// the type from the index. This allows type parsing to be as efficient as |
227 | /// possible and only realize the types that match the query. |
228 | bool |
229 | ContextMatches(llvm::ArrayRef<lldb_private::CompilerContext> context) const; |
230 | |
231 | /// Get the type basename to use when searching the type indexes in each |
232 | /// SymbolFile object. |
233 | /// |
234 | /// Debug information indexes often contain indexes that track the basename |
235 | /// of types only, not a fully qualified path. This allows the indexes to be |
236 | /// smaller and allows for efficient lookups. |
237 | /// |
238 | /// \returns |
239 | /// The type basename to use when doing lookups as a constant string. |
240 | ConstString GetTypeBasename() const; |
241 | |
242 | /// Returns true if any matching languages have been specified in this type |
243 | /// matching object. |
244 | bool HasLanguage() const { return m_languages.has_value(); } |
245 | |
246 | /// Add a language family to the list of languages that should produce a |
247 | /// match. |
248 | void AddLanguage(lldb::LanguageType language); |
249 | |
250 | /// Set the list of languages that should produce a match to only the ones |
251 | /// specified in \ref languages. |
252 | void SetLanguages(LanguageSet languages); |
253 | |
254 | /// Check if the language matches any languages that have been added to this |
255 | /// match object. |
256 | /// |
257 | /// \returns |
258 | /// True if no language have been specified, or if some language have been |
259 | /// added using AddLanguage(...) and they match. False otherwise. |
260 | bool LanguageMatches(lldb::LanguageType language) const; |
261 | |
262 | bool GetExactMatch() const { return (m_options & e_exact_match) != 0; } |
263 | /// The \a m_context can be used in two ways: normal types searching with |
264 | /// the context containing a stanadard declaration context for a type, or |
265 | /// with the context being more complete for exact matches in clang modules. |
266 | /// Set this to true if you wish to search for a type in clang module. |
267 | bool GetModuleSearch() const { return (m_options & e_module_search) != 0; } |
268 | |
269 | /// Returns true if the type query is supposed to find only a single matching |
270 | /// type. Returns false if the type query should find all matches. |
271 | bool GetFindOne() const { return (m_options & e_find_one) != 0; } |
272 | void SetFindOne(bool b) { |
273 | if (b) |
274 | m_options |= e_find_one; |
275 | else |
276 | m_options &= (e_exact_match | e_find_one); |
277 | } |
278 | |
279 | /// Access the internal compiler context array. |
280 | /// |
281 | /// Clients can use this to populate the context manually. |
282 | std::vector<lldb_private::CompilerContext> &GetContextRef() { |
283 | return m_context; |
284 | } |
285 | |
286 | protected: |
287 | /// A full or partial compiler context array where the parent declaration |
288 | /// contexts appear at the top of the array starting at index zero and the |
289 | /// last entry contains the type and name of the type we are looking for. |
290 | std::vector<lldb_private::CompilerContext> m_context; |
291 | /// An options bitmask that contains enabled options for the type query. |
292 | /// \see TypeQueryOptions. |
293 | TypeQueryOptions m_options; |
294 | /// If this variable has a value, then the language family must match at least |
295 | /// one of the specified languages. If this variable has no value, then the |
296 | /// language of the type doesn't need to match any types that are searched. |
297 | std::optional<LanguageSet> m_languages; |
298 | }; |
299 | |
300 | /// This class tracks the state and results of a \ref TypeQuery. |
301 | /// |
302 | /// Any mutable state required for type lookups and the results are tracked in |
303 | /// this object. |
304 | class TypeResults { |
305 | public: |
306 | /// Construct a type results object |
307 | TypeResults() = default; |
308 | |
309 | /// When types that match a TypeQuery are found, this API is used to insert |
310 | /// the matching types. |
311 | /// |
312 | /// \return |
313 | /// True if the type was added, false if the \a type_sp was already in the |
314 | /// results. |
315 | bool InsertUnique(const lldb::TypeSP &type_sp); |
316 | |
317 | /// Check if the type matching has found all of the matches that it needs. |
318 | bool Done(const TypeQuery &query) const; |
319 | |
320 | /// Check if a SymbolFile object has already been searched by this type match |
321 | /// object. |
322 | /// |
323 | /// This function will add \a sym_file to the set of SymbolFile objects if it |
324 | /// isn't already in the set and return \a false. Returns true if \a sym_file |
325 | /// was already in the set and doesn't need to be searched. |
326 | /// |
327 | /// Any clients that search for types should first check that the symbol file |
328 | /// has not already been searched. If this function returns true, the type |
329 | /// search function should early return to avoid duplicating type searchihng |
330 | /// efforts. |
331 | /// |
332 | /// \param[in] sym_file |
333 | /// A SymbolFile pointer that will be used to track which symbol files have |
334 | /// already been searched. |
335 | /// |
336 | /// \returns |
337 | /// True if the symbol file has been search already, false otherwise. |
338 | bool AlreadySearched(lldb_private::SymbolFile *sym_file); |
339 | |
340 | /// Access the set of searched symbol files. |
341 | llvm::DenseSet<lldb_private::SymbolFile *> &GetSearchedSymbolFiles() { |
342 | return m_searched_symbol_files; |
343 | } |
344 | |
345 | lldb::TypeSP GetFirstType() const { return m_type_map.FirstType(); } |
346 | TypeMap &GetTypeMap() { return m_type_map; } |
347 | const TypeMap &GetTypeMap() const { return m_type_map; } |
348 | |
349 | private: |
350 | /// Matching types get added to this map as type search continues. |
351 | TypeMap m_type_map; |
352 | /// This set is used to track and make sure we only perform lookups in a |
353 | /// symbol file one time. |
354 | llvm::DenseSet<lldb_private::SymbolFile *> m_searched_symbol_files; |
355 | }; |
356 | |
357 | class SymbolFileType : public std::enable_shared_from_this<SymbolFileType>, |
358 | public UserID { |
359 | public: |
360 | SymbolFileType(SymbolFile &symbol_file, lldb::user_id_t uid) |
361 | : UserID(uid), m_symbol_file(symbol_file) {} |
362 | |
363 | SymbolFileType(SymbolFile &symbol_file, const lldb::TypeSP &type_sp); |
364 | |
365 | ~SymbolFileType() = default; |
366 | |
367 | Type *operator->() { return GetType(); } |
368 | |
369 | Type *GetType(); |
370 | SymbolFile &GetSymbolFile() const { return m_symbol_file; } |
371 | |
372 | protected: |
373 | SymbolFile &m_symbol_file; |
374 | lldb::TypeSP m_type_sp; |
375 | }; |
376 | |
377 | class Type : public std::enable_shared_from_this<Type>, public UserID { |
378 | public: |
379 | enum EncodingDataType { |
380 | /// Invalid encoding. |
381 | eEncodingInvalid, |
382 | /// This type is the type whose UID is m_encoding_uid. |
383 | eEncodingIsUID, |
384 | /// This type is the type whose UID is m_encoding_uid with the const |
385 | /// qualifier added. |
386 | eEncodingIsConstUID, |
387 | /// This type is the type whose UID is m_encoding_uid with the restrict |
388 | /// qualifier added. |
389 | eEncodingIsRestrictUID, |
390 | /// This type is the type whose UID is m_encoding_uid with the volatile |
391 | /// qualifier added. |
392 | eEncodingIsVolatileUID, |
393 | /// This type is alias to a type whose UID is m_encoding_uid. |
394 | eEncodingIsTypedefUID, |
395 | /// This type is pointer to a type whose UID is m_encoding_uid. |
396 | eEncodingIsPointerUID, |
397 | /// This type is L value reference to a type whose UID is m_encoding_uid. |
398 | eEncodingIsLValueReferenceUID, |
399 | /// This type is R value reference to a type whose UID is m_encoding_uid. |
400 | eEncodingIsRValueReferenceUID, |
401 | /// This type is the type whose UID is m_encoding_uid as an atomic type. |
402 | eEncodingIsAtomicUID, |
403 | /// This type is the synthetic type whose UID is m_encoding_uid. |
404 | eEncodingIsSyntheticUID |
405 | }; |
406 | |
407 | enum class ResolveState : unsigned char { |
408 | Unresolved = 0, |
409 | Forward = 1, |
410 | Layout = 2, |
411 | Full = 3 |
412 | }; |
413 | |
414 | void Dump(Stream *s, bool show_context, |
415 | lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); |
416 | |
417 | void DumpTypeName(Stream *s); |
418 | |
419 | /// Since Type instances only keep a "SymbolFile *" internally, other classes |
420 | /// like TypeImpl need make sure the module is still around before playing |
421 | /// with |
422 | /// Type instances. They can store a weak pointer to the Module; |
423 | lldb::ModuleSP GetModule(); |
424 | |
425 | /// GetModule may return module for compile unit's object file. |
426 | /// GetExeModule returns module for executable object file that contains |
427 | /// compile unit where type was actually defined. |
428 | /// GetModule and GetExeModule may return the same value. |
429 | lldb::ModuleSP GetExeModule(); |
430 | |
431 | void GetDescription(Stream *s, lldb::DescriptionLevel level, bool show_name, |
432 | ExecutionContextScope *exe_scope); |
433 | |
434 | SymbolFile *GetSymbolFile() { return m_symbol_file; } |
435 | const SymbolFile *GetSymbolFile() const { return m_symbol_file; } |
436 | |
437 | ConstString GetName(); |
438 | |
439 | ConstString GetBaseName(); |
440 | |
441 | std::optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope); |
442 | |
443 | uint32_t GetNumChildren(bool omit_empty_base_classes); |
444 | |
445 | bool IsAggregateType(); |
446 | |
447 | // Returns if the type is a templated decl. Does not look through typedefs. |
448 | bool IsTemplateType(); |
449 | |
450 | bool IsValidType() { return m_encoding_uid_type != eEncodingInvalid; } |
451 | |
452 | bool IsTypedef() { return m_encoding_uid_type == eEncodingIsTypedefUID; } |
453 | |
454 | lldb::TypeSP GetTypedefType(); |
455 | |
456 | ConstString GetName() const { return m_name; } |
457 | |
458 | ConstString GetQualifiedName(); |
459 | |
460 | bool (ExecutionContext *exe_ctx, lldb::addr_t address, |
461 | AddressType address_type, DataExtractor &data); |
462 | |
463 | bool (ExecutionContext *exe_ctx, lldb::addr_t address, |
464 | AddressType address_type, DataExtractor &data); |
465 | |
466 | lldb::Format GetFormat(); |
467 | |
468 | lldb::Encoding GetEncoding(uint64_t &count); |
469 | |
470 | SymbolContextScope *GetSymbolContextScope() { return m_context; } |
471 | const SymbolContextScope *GetSymbolContextScope() const { return m_context; } |
472 | void SetSymbolContextScope(SymbolContextScope *context) { |
473 | m_context = context; |
474 | } |
475 | |
476 | const lldb_private::Declaration &GetDeclaration() const; |
477 | |
478 | // Get the clang type, and resolve definitions for any |
479 | // class/struct/union/enum types completely. |
480 | CompilerType GetFullCompilerType(); |
481 | |
482 | // Get the clang type, and resolve definitions enough so that the type could |
483 | // have layout performed. This allows ptrs and refs to |
484 | // class/struct/union/enum types remain forward declarations. |
485 | CompilerType GetLayoutCompilerType(); |
486 | |
487 | // Get the clang type and leave class/struct/union/enum types as forward |
488 | // declarations if they haven't already been fully defined. |
489 | CompilerType GetForwardCompilerType(); |
490 | |
491 | static int Compare(const Type &a, const Type &b); |
492 | |
493 | // From a fully qualified typename, split the type into the type basename and |
494 | // the remaining type scope (namespaces/classes). |
495 | static bool GetTypeScopeAndBasename(llvm::StringRef name, |
496 | llvm::StringRef &scope, |
497 | llvm::StringRef &basename, |
498 | lldb::TypeClass &type_class); |
499 | void SetEncodingType(Type *encoding_type) { m_encoding_type = encoding_type; } |
500 | |
501 | uint32_t GetEncodingMask(); |
502 | |
503 | typedef uint32_t Payload; |
504 | /// Return the language-specific payload. |
505 | Payload GetPayload() { return m_payload; } |
506 | /// Return the language-specific payload. |
507 | void SetPayload(Payload opaque_payload) { m_payload = opaque_payload; } |
508 | |
509 | protected: |
510 | ConstString m_name; |
511 | SymbolFile *m_symbol_file = nullptr; |
512 | /// The symbol context in which this type is defined. |
513 | SymbolContextScope *m_context = nullptr; |
514 | Type *m_encoding_type = nullptr; |
515 | lldb::user_id_t m_encoding_uid = LLDB_INVALID_UID; |
516 | EncodingDataType m_encoding_uid_type = eEncodingInvalid; |
517 | uint64_t m_byte_size : 63; |
518 | uint64_t m_byte_size_has_value : 1; |
519 | Declaration m_decl; |
520 | CompilerType m_compiler_type; |
521 | ResolveState m_compiler_type_resolve_state = ResolveState::Unresolved; |
522 | /// Language-specific flags. |
523 | Payload m_payload; |
524 | |
525 | Type *GetEncodingType(); |
526 | |
527 | bool ResolveCompilerType(ResolveState compiler_type_resolve_state); |
528 | private: |
529 | /// Only allow Symbol File to create types, as they should own them by keeping |
530 | /// them in their TypeList. \see SymbolFileCommon::MakeType() reference in the |
531 | /// header documentation here so users will know what function to use if the |
532 | /// get a compile error. |
533 | friend class lldb_private::SymbolFileCommon; |
534 | |
535 | Type(lldb::user_id_t uid, SymbolFile *symbol_file, ConstString name, |
536 | std::optional<uint64_t> byte_size, SymbolContextScope *context, |
537 | lldb::user_id_t encoding_uid, EncodingDataType encoding_uid_type, |
538 | const Declaration &decl, const CompilerType &compiler_qual_type, |
539 | ResolveState compiler_type_resolve_state, uint32_t opaque_payload = 0); |
540 | |
541 | // This makes an invalid type. Used for functions that return a Type when |
542 | // they get an error. |
543 | Type(); |
544 | |
545 | Type(Type &t) = default; |
546 | |
547 | Type(Type &&t) = default; |
548 | |
549 | Type &operator=(const Type &t) = default; |
550 | |
551 | Type &operator=(Type &&t) = default; |
552 | }; |
553 | |
554 | // the two classes here are used by the public API as a backend to the SBType |
555 | // and SBTypeList classes |
556 | |
557 | class TypeImpl { |
558 | public: |
559 | TypeImpl() = default; |
560 | |
561 | ~TypeImpl() = default; |
562 | |
563 | TypeImpl(const lldb::TypeSP &type_sp); |
564 | |
565 | TypeImpl(const CompilerType &compiler_type); |
566 | |
567 | TypeImpl(const lldb::TypeSP &type_sp, const CompilerType &dynamic); |
568 | |
569 | TypeImpl(const CompilerType &compiler_type, const CompilerType &dynamic); |
570 | |
571 | void SetType(const lldb::TypeSP &type_sp); |
572 | |
573 | void SetType(const CompilerType &compiler_type); |
574 | |
575 | void SetType(const lldb::TypeSP &type_sp, const CompilerType &dynamic); |
576 | |
577 | void SetType(const CompilerType &compiler_type, const CompilerType &dynamic); |
578 | |
579 | bool operator==(const TypeImpl &rhs) const; |
580 | |
581 | bool operator!=(const TypeImpl &rhs) const; |
582 | |
583 | bool IsValid() const; |
584 | |
585 | explicit operator bool() const; |
586 | |
587 | void Clear(); |
588 | |
589 | lldb::ModuleSP GetModule() const; |
590 | |
591 | ConstString GetName() const; |
592 | |
593 | ConstString GetDisplayTypeName() const; |
594 | |
595 | TypeImpl GetPointerType() const; |
596 | |
597 | TypeImpl GetPointeeType() const; |
598 | |
599 | TypeImpl GetReferenceType() const; |
600 | |
601 | TypeImpl GetTypedefedType() const; |
602 | |
603 | TypeImpl GetDereferencedType() const; |
604 | |
605 | TypeImpl GetUnqualifiedType() const; |
606 | |
607 | TypeImpl GetCanonicalType() const; |
608 | |
609 | CompilerType GetCompilerType(bool prefer_dynamic); |
610 | |
611 | CompilerType::TypeSystemSPWrapper GetTypeSystem(bool prefer_dynamic); |
612 | |
613 | bool GetDescription(lldb_private::Stream &strm, |
614 | lldb::DescriptionLevel description_level); |
615 | |
616 | CompilerType FindDirectNestedType(llvm::StringRef name); |
617 | |
618 | private: |
619 | bool CheckModule(lldb::ModuleSP &module_sp) const; |
620 | bool CheckExeModule(lldb::ModuleSP &module_sp) const; |
621 | bool CheckModuleCommon(const lldb::ModuleWP &input_module_wp, |
622 | lldb::ModuleSP &module_sp) const; |
623 | |
624 | lldb::ModuleWP m_module_wp; |
625 | lldb::ModuleWP m_exe_module_wp; |
626 | CompilerType m_static_type; |
627 | CompilerType m_dynamic_type; |
628 | }; |
629 | |
630 | class TypeListImpl { |
631 | public: |
632 | TypeListImpl() = default; |
633 | |
634 | void Append(const lldb::TypeImplSP &type) { m_content.push_back(x: type); } |
635 | |
636 | class AppendVisitor { |
637 | public: |
638 | AppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {} |
639 | |
640 | void operator()(const lldb::TypeImplSP &type) { m_type_list.Append(type); } |
641 | |
642 | private: |
643 | TypeListImpl &m_type_list; |
644 | }; |
645 | |
646 | void Append(const lldb_private::TypeList &type_list); |
647 | |
648 | lldb::TypeImplSP GetTypeAtIndex(size_t idx) { |
649 | lldb::TypeImplSP type_sp; |
650 | if (idx < GetSize()) |
651 | type_sp = m_content[idx]; |
652 | return type_sp; |
653 | } |
654 | |
655 | size_t GetSize() { return m_content.size(); } |
656 | |
657 | private: |
658 | std::vector<lldb::TypeImplSP> m_content; |
659 | }; |
660 | |
661 | class TypeMemberImpl { |
662 | public: |
663 | TypeMemberImpl() = default; |
664 | |
665 | TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset, |
666 | ConstString name, uint32_t bitfield_bit_size = 0, |
667 | bool is_bitfield = false) |
668 | : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_name(name), |
669 | m_bitfield_bit_size(bitfield_bit_size), m_is_bitfield(is_bitfield) {} |
670 | |
671 | TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset) |
672 | : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), |
673 | m_bitfield_bit_size(0), m_is_bitfield(false) { |
674 | if (m_type_impl_sp) |
675 | m_name = m_type_impl_sp->GetName(); |
676 | } |
677 | |
678 | const lldb::TypeImplSP &GetTypeImpl() { return m_type_impl_sp; } |
679 | |
680 | ConstString GetName() const { return m_name; } |
681 | |
682 | uint64_t GetBitOffset() const { return m_bit_offset; } |
683 | |
684 | uint32_t GetBitfieldBitSize() const { return m_bitfield_bit_size; } |
685 | |
686 | void SetBitfieldBitSize(uint32_t bitfield_bit_size) { |
687 | m_bitfield_bit_size = bitfield_bit_size; |
688 | } |
689 | |
690 | bool GetIsBitfield() const { return m_is_bitfield; } |
691 | |
692 | void SetIsBitfield(bool is_bitfield) { m_is_bitfield = is_bitfield; } |
693 | |
694 | protected: |
695 | lldb::TypeImplSP m_type_impl_sp; |
696 | uint64_t m_bit_offset = 0; |
697 | ConstString m_name; |
698 | uint32_t m_bitfield_bit_size = 0; // Bit size for bitfield members only |
699 | bool m_is_bitfield = false; |
700 | }; |
701 | |
702 | /// |
703 | /// Sometimes you can find the name of the type corresponding to an object, but |
704 | /// we don't have debug |
705 | /// information for it. If that is the case, you can return one of these |
706 | /// objects, and then if it |
707 | /// has a full type, you can use that, but if not at least you can print the |
708 | /// name for informational |
709 | /// purposes. |
710 | /// |
711 | |
712 | class TypeAndOrName { |
713 | public: |
714 | TypeAndOrName() = default; |
715 | TypeAndOrName(lldb::TypeSP &type_sp); |
716 | TypeAndOrName(const CompilerType &compiler_type); |
717 | TypeAndOrName(const char *type_str); |
718 | TypeAndOrName(ConstString &type_const_string); |
719 | |
720 | bool operator==(const TypeAndOrName &other) const; |
721 | |
722 | bool operator!=(const TypeAndOrName &other) const; |
723 | |
724 | ConstString GetName() const; |
725 | |
726 | CompilerType GetCompilerType() const { return m_compiler_type; } |
727 | |
728 | void SetName(ConstString type_name); |
729 | |
730 | void SetName(const char *type_name_cstr); |
731 | |
732 | void SetName(llvm::StringRef name); |
733 | |
734 | void SetTypeSP(lldb::TypeSP type_sp); |
735 | |
736 | void SetCompilerType(CompilerType compiler_type); |
737 | |
738 | bool IsEmpty() const; |
739 | |
740 | bool HasName() const; |
741 | |
742 | bool HasCompilerType() const; |
743 | |
744 | bool HasType() const { return HasCompilerType(); } |
745 | |
746 | void Clear(); |
747 | |
748 | explicit operator bool() { return !IsEmpty(); } |
749 | |
750 | private: |
751 | CompilerType m_compiler_type; |
752 | ConstString m_type_name; |
753 | }; |
754 | |
755 | class TypeMemberFunctionImpl { |
756 | public: |
757 | TypeMemberFunctionImpl() = default; |
758 | |
759 | TypeMemberFunctionImpl(const CompilerType &type, const CompilerDecl &decl, |
760 | const std::string &name, |
761 | const lldb::MemberFunctionKind &kind) |
762 | : m_type(type), m_decl(decl), m_name(name), m_kind(kind) {} |
763 | |
764 | bool IsValid(); |
765 | |
766 | ConstString GetName() const; |
767 | |
768 | ConstString GetMangledName() const; |
769 | |
770 | CompilerType GetType() const; |
771 | |
772 | CompilerType GetReturnType() const; |
773 | |
774 | size_t GetNumArguments() const; |
775 | |
776 | CompilerType GetArgumentAtIndex(size_t idx) const; |
777 | |
778 | lldb::MemberFunctionKind GetKind() const; |
779 | |
780 | bool GetDescription(Stream &stream); |
781 | |
782 | protected: |
783 | std::string GetPrintableTypeName(); |
784 | |
785 | private: |
786 | CompilerType m_type; |
787 | CompilerDecl m_decl; |
788 | ConstString m_name; |
789 | lldb::MemberFunctionKind m_kind = lldb::eMemberFunctionKindUnknown; |
790 | }; |
791 | |
792 | class TypeEnumMemberImpl { |
793 | public: |
794 | TypeEnumMemberImpl() : m_name("<invalid>" ) {} |
795 | |
796 | TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, ConstString name, |
797 | const llvm::APSInt &value); |
798 | |
799 | TypeEnumMemberImpl(const TypeEnumMemberImpl &rhs) = default; |
800 | |
801 | TypeEnumMemberImpl &operator=(const TypeEnumMemberImpl &rhs); |
802 | |
803 | bool IsValid() { return m_valid; } |
804 | |
805 | ConstString GetName() const { return m_name; } |
806 | |
807 | const lldb::TypeImplSP &GetIntegerType() const { return m_integer_type_sp; } |
808 | |
809 | uint64_t GetValueAsUnsigned() const { return m_value.getZExtValue(); } |
810 | |
811 | int64_t GetValueAsSigned() const { return m_value.getSExtValue(); } |
812 | |
813 | protected: |
814 | lldb::TypeImplSP m_integer_type_sp; |
815 | ConstString m_name; |
816 | llvm::APSInt m_value; |
817 | bool m_valid = false; |
818 | }; |
819 | |
820 | class TypeEnumMemberListImpl { |
821 | public: |
822 | TypeEnumMemberListImpl() = default; |
823 | |
824 | void Append(const lldb::TypeEnumMemberImplSP &type) { |
825 | m_content.push_back(x: type); |
826 | } |
827 | |
828 | void Append(const lldb_private::TypeEnumMemberListImpl &type_list); |
829 | |
830 | lldb::TypeEnumMemberImplSP GetTypeEnumMemberAtIndex(size_t idx) { |
831 | lldb::TypeEnumMemberImplSP enum_member; |
832 | if (idx < GetSize()) |
833 | enum_member = m_content[idx]; |
834 | return enum_member; |
835 | } |
836 | |
837 | size_t GetSize() { return m_content.size(); } |
838 | |
839 | private: |
840 | std::vector<lldb::TypeEnumMemberImplSP> m_content; |
841 | }; |
842 | |
843 | } // namespace lldb_private |
844 | |
845 | #endif // LLDB_SYMBOL_TYPE_H |
846 | |