/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Symbol/CompilerType.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- CompilerType.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_COMPILERTYPE_H |
10 | | #define LLDB_SYMBOL_COMPILERTYPE_H |
11 | | |
12 | | #include <functional> |
13 | | #include <optional> |
14 | | #include <string> |
15 | | #include <vector> |
16 | | |
17 | | #include "lldb/lldb-private.h" |
18 | | #include "llvm/ADT/APSInt.h" |
19 | | #include "llvm/Support/Casting.h" |
20 | | |
21 | | namespace lldb_private { |
22 | | |
23 | | class DataExtractor; |
24 | | class TypeSystem; |
25 | | |
26 | | /// Generic representation of a type in a programming language. |
27 | | /// |
28 | | /// This class serves as an abstraction for a type inside one of the TypeSystems |
29 | | /// implemented by the language plugins. It does not have any actual logic in it |
30 | | /// but only stores an opaque pointer and a pointer to the TypeSystem that |
31 | | /// gives meaning to this opaque pointer. All methods of this class should call |
32 | | /// their respective method in the TypeSystem interface and pass the opaque |
33 | | /// pointer along. |
34 | | /// |
35 | | /// \see lldb_private::TypeSystem |
36 | | class CompilerType { |
37 | | public: |
38 | | /// Creates a CompilerType with the given TypeSystem and opaque compiler type. |
39 | | /// |
40 | | /// This constructor should only be called from the respective TypeSystem |
41 | | /// implementation. |
42 | | /// |
43 | | /// \see lldb_private::TypeSystemClang::GetType(clang::QualType) |
44 | | CompilerType(lldb::TypeSystemWP type_system, |
45 | | lldb::opaque_compiler_type_t type) |
46 | 570k | : m_type_system(type_system), m_type(type) { |
47 | 570k | assert(Verify() && "verification failed"); |
48 | 570k | } |
49 | | |
50 | | /// This is a minimal wrapper of a TypeSystem shared pointer as |
51 | | /// returned by CompilerType which conventien dyn_cast support. |
52 | | class TypeSystemSPWrapper { |
53 | | lldb::TypeSystemSP m_typesystem_sp; |
54 | | |
55 | | public: |
56 | 0 | TypeSystemSPWrapper() = default; |
57 | | TypeSystemSPWrapper(lldb::TypeSystemSP typesystem_sp) |
58 | 5.94M | : m_typesystem_sp(typesystem_sp) {} |
59 | | |
60 | 1.23M | template <class TypeSystemType> bool isa_and_nonnull() { |
61 | 1.23M | if (auto *ts = m_typesystem_sp.get()) |
62 | 1.23M | return llvm::isa<TypeSystemType>(ts); |
63 | 0 | return false; |
64 | 1.23M | } |
65 | | |
66 | | /// Return a shared_ptr<TypeSystemType> if dyn_cast succeeds. |
67 | | template <class TypeSystemType> |
68 | 1.23M | std::shared_ptr<TypeSystemType> dyn_cast_or_null() { |
69 | 1.23M | if (isa_and_nonnull<TypeSystemType>()) |
70 | 1.23M | return std::shared_ptr<TypeSystemType>( |
71 | 1.23M | m_typesystem_sp, llvm::cast<TypeSystemType>(m_typesystem_sp.get())); |
72 | 0 | return nullptr; |
73 | 1.23M | } |
74 | | |
75 | 4.57M | explicit operator bool() const { |
76 | 4.57M | return static_cast<bool>(m_typesystem_sp); |
77 | 4.57M | } |
78 | | bool operator==(const TypeSystemSPWrapper &other) const; |
79 | 33 | bool operator!=(const TypeSystemSPWrapper &other) const { |
80 | 33 | return !(*this == other); |
81 | 33 | } |
82 | | |
83 | | /// Only to be used in a one-off situations like |
84 | | /// if (typesystem && typesystem->method()) |
85 | | /// Do not store this pointer! |
86 | | TypeSystem *operator->() const; |
87 | | |
88 | 132k | lldb::TypeSystemSP GetSharedPointer() const { return m_typesystem_sp; } |
89 | | }; |
90 | | |
91 | | CompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type) |
92 | 122k | : m_type_system(type_system.GetSharedPointer()), m_type(type) { |
93 | 122k | assert(Verify() && "verification failed"); |
94 | 122k | } |
95 | | |
96 | | CompilerType(const CompilerType &rhs) |
97 | 13.0M | : m_type_system(rhs.m_type_system), m_type(rhs.m_type) {} |
98 | | |
99 | 968k | CompilerType() = default; |
100 | | |
101 | | /// Operators. |
102 | | /// \{ |
103 | 571k | const CompilerType &operator=(const CompilerType &rhs) { |
104 | 571k | m_type_system = rhs.m_type_system; |
105 | 571k | m_type = rhs.m_type; |
106 | 571k | return *this; |
107 | 571k | } |
108 | | |
109 | 1.29k | bool operator<(const CompilerType &rhs) const { |
110 | 1.29k | auto lts = m_type_system.lock(); |
111 | 1.29k | auto rts = rhs.m_type_system.lock(); |
112 | 1.29k | if (lts.get() == rts.get()) |
113 | 1.29k | return m_type < rhs.m_type; |
114 | 0 | return lts.get() < rts.get(); |
115 | 1.29k | } |
116 | | /// \} |
117 | | |
118 | | /// Tests. |
119 | | /// \{ |
120 | 13.6M | explicit operator bool() const { |
121 | 13.6M | return m_type_system.lock() && m_type10.9M ; |
122 | 13.6M | } |
123 | | |
124 | 11.9M | bool IsValid() const { return (bool)*this; } |
125 | | |
126 | | bool IsArrayType(CompilerType *element_type = nullptr, |
127 | | uint64_t *size = nullptr, |
128 | | bool *is_incomplete = nullptr) const; |
129 | | |
130 | | bool IsVectorType(CompilerType *element_type = nullptr, |
131 | | uint64_t *size = nullptr) const; |
132 | | |
133 | | bool IsArrayOfScalarType() const; |
134 | | |
135 | | bool IsAggregateType() const; |
136 | | |
137 | | bool IsAnonymousType() const; |
138 | | |
139 | | bool IsScopedEnumerationType() const; |
140 | | |
141 | | bool IsBeingDefined() const; |
142 | | |
143 | | bool IsCharType() const; |
144 | | |
145 | | bool IsCompleteType() const; |
146 | | |
147 | | bool IsConst() const; |
148 | | |
149 | | bool IsCStringType(uint32_t &length) const; |
150 | | |
151 | | bool IsDefined() const; |
152 | | |
153 | | bool IsFloatingPointType(uint32_t &count, bool &is_complex) const; |
154 | | |
155 | | bool IsFunctionType() const; |
156 | | |
157 | | uint32_t IsHomogeneousAggregate(CompilerType *base_type_ptr) const; |
158 | | |
159 | | size_t GetNumberOfFunctionArguments() const; |
160 | | |
161 | | CompilerType GetFunctionArgumentAtIndex(const size_t index) const; |
162 | | |
163 | | bool IsVariadicFunctionType() const; |
164 | | |
165 | | bool IsFunctionPointerType() const; |
166 | | |
167 | | bool IsMemberFunctionPointerType() const; |
168 | | |
169 | | bool |
170 | | IsBlockPointerType(CompilerType *function_pointer_type_ptr = nullptr) const; |
171 | | |
172 | | bool IsIntegerType(bool &is_signed) const; |
173 | | |
174 | | bool IsEnumerationType(bool &is_signed) const; |
175 | | |
176 | | bool IsIntegerOrEnumerationType(bool &is_signed) const; |
177 | | |
178 | | bool IsPolymorphicClass() const; |
179 | | |
180 | | /// \param target_type Can pass nullptr. |
181 | | bool IsPossibleDynamicType(CompilerType *target_type, bool check_cplusplus, |
182 | | bool check_objc) const; |
183 | | |
184 | | bool IsPointerToScalarType() const; |
185 | | |
186 | | bool IsRuntimeGeneratedType() const; |
187 | | |
188 | | bool IsPointerType(CompilerType *pointee_type = nullptr) const; |
189 | | |
190 | | bool IsPointerOrReferenceType(CompilerType *pointee_type = nullptr) const; |
191 | | |
192 | | bool IsReferenceType(CompilerType *pointee_type = nullptr, |
193 | | bool *is_rvalue = nullptr) const; |
194 | | |
195 | | bool ShouldTreatScalarValueAsAddress() const; |
196 | | |
197 | | bool IsScalarType() const; |
198 | | |
199 | | bool IsTemplateType() const; |
200 | | |
201 | | bool IsTypedefType() const; |
202 | | |
203 | | bool IsVoidType() const; |
204 | | /// \} |
205 | | |
206 | | /// Type Completion. |
207 | | /// \{ |
208 | | bool GetCompleteType() const; |
209 | | /// \} |
210 | | |
211 | | bool IsForcefullyCompleted() const; |
212 | | |
213 | | /// AST related queries. |
214 | | /// \{ |
215 | | size_t GetPointerByteSize() const; |
216 | | /// \} |
217 | | |
218 | | /// Accessors. |
219 | | /// \{ |
220 | | |
221 | | /// Returns a shared pointer to the type system. The |
222 | | /// TypeSystem::TypeSystemSPWrapper can be compared for equality. |
223 | | TypeSystemSPWrapper GetTypeSystem() const; |
224 | | |
225 | | ConstString GetTypeName(bool BaseOnly = false) const; |
226 | | |
227 | | ConstString GetDisplayTypeName() const; |
228 | | |
229 | | uint32_t |
230 | | GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr) const; |
231 | | |
232 | | lldb::LanguageType GetMinimumLanguage(); |
233 | | |
234 | 1.95M | lldb::opaque_compiler_type_t GetOpaqueQualType() const { return m_type; } |
235 | | |
236 | | lldb::TypeClass GetTypeClass() const; |
237 | | |
238 | | void SetCompilerType(lldb::TypeSystemWP type_system, |
239 | | lldb::opaque_compiler_type_t type); |
240 | | void SetCompilerType(TypeSystemSPWrapper type_system, |
241 | | lldb::opaque_compiler_type_t type); |
242 | | |
243 | | unsigned GetTypeQualifiers() const; |
244 | | /// \} |
245 | | |
246 | | /// Creating related types. |
247 | | /// \{ |
248 | | CompilerType GetArrayElementType(ExecutionContextScope *exe_scope) const; |
249 | | |
250 | | CompilerType GetArrayType(uint64_t size) const; |
251 | | |
252 | | CompilerType GetCanonicalType() const; |
253 | | |
254 | | CompilerType GetFullyUnqualifiedType() const; |
255 | | |
256 | | CompilerType GetEnumerationIntegerType() const; |
257 | | |
258 | | /// Returns -1 if this isn't a function of if the function doesn't |
259 | | /// have a prototype Returns a value >= 0 if there is a prototype. |
260 | | int GetFunctionArgumentCount() const; |
261 | | |
262 | | CompilerType GetFunctionArgumentTypeAtIndex(size_t idx) const; |
263 | | |
264 | | CompilerType GetFunctionReturnType() const; |
265 | | |
266 | | size_t GetNumMemberFunctions() const; |
267 | | |
268 | | TypeMemberFunctionImpl GetMemberFunctionAtIndex(size_t idx); |
269 | | |
270 | | /// If this type is a reference to a type (L value or R value reference), |
271 | | /// return a new type with the reference removed, else return the current type |
272 | | /// itself. |
273 | | CompilerType GetNonReferenceType() const; |
274 | | |
275 | | /// If this type is a pointer type, return the type that the pointer points |
276 | | /// to, else return an invalid type. |
277 | | CompilerType GetPointeeType() const; |
278 | | |
279 | | /// Return a new CompilerType that is a pointer to this type |
280 | | CompilerType GetPointerType() const; |
281 | | |
282 | | /// Return a new CompilerType that is a L value reference to this type if this |
283 | | /// type is valid and the type system supports L value references, else return |
284 | | /// an invalid type. |
285 | | CompilerType GetLValueReferenceType() const; |
286 | | |
287 | | /// Return a new CompilerType that is a R value reference to this type if this |
288 | | /// type is valid and the type system supports R value references, else return |
289 | | /// an invalid type. |
290 | | CompilerType GetRValueReferenceType() const; |
291 | | |
292 | | /// Return a new CompilerType adds a const modifier to this type if this type |
293 | | /// is valid and the type system supports const modifiers, else return an |
294 | | /// invalid type. |
295 | | CompilerType AddConstModifier() const; |
296 | | |
297 | | /// Return a new CompilerType adds a volatile modifier to this type if this |
298 | | /// type is valid and the type system supports volatile modifiers, else return |
299 | | /// an invalid type. |
300 | | CompilerType AddVolatileModifier() const; |
301 | | |
302 | | /// Return a new CompilerType that is the atomic type of this type. If this |
303 | | /// type is not valid or the type system doesn't support atomic types, this |
304 | | /// returns an invalid type. |
305 | | CompilerType GetAtomicType() const; |
306 | | |
307 | | /// Return a new CompilerType adds a restrict modifier to this type if this |
308 | | /// type is valid and the type system supports restrict modifiers, else return |
309 | | /// an invalid type. |
310 | | CompilerType AddRestrictModifier() const; |
311 | | |
312 | | /// Create a typedef to this type using "name" as the name of the typedef this |
313 | | /// type is valid and the type system supports typedefs, else return an |
314 | | /// invalid type. |
315 | | /// \param payload The typesystem-specific \p lldb::Type payload. |
316 | | CompilerType CreateTypedef(const char *name, |
317 | | const CompilerDeclContext &decl_ctx, |
318 | | uint32_t payload) const; |
319 | | |
320 | | /// If the current object represents a typedef type, get the underlying type |
321 | | CompilerType GetTypedefedType() const; |
322 | | |
323 | | /// Create related types using the current type's AST |
324 | | CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) const; |
325 | | /// \} |
326 | | |
327 | | /// Exploring the type. |
328 | | /// \{ |
329 | | struct IntegralTemplateArgument; |
330 | | |
331 | | /// Return the size of the type in bytes. |
332 | | std::optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope) const; |
333 | | /// Return the size of the type in bits. |
334 | | std::optional<uint64_t> GetBitSize(ExecutionContextScope *exe_scope) const; |
335 | | |
336 | | lldb::Encoding GetEncoding(uint64_t &count) const; |
337 | | |
338 | | lldb::Format GetFormat() const; |
339 | | |
340 | | std::optional<size_t> GetTypeBitAlign(ExecutionContextScope *exe_scope) const; |
341 | | |
342 | | uint32_t GetNumChildren(bool omit_empty_base_classes, |
343 | | const ExecutionContext *exe_ctx) const; |
344 | | |
345 | | lldb::BasicType GetBasicTypeEnumeration() const; |
346 | | |
347 | | /// If this type is an enumeration, iterate through all of its enumerators |
348 | | /// using a callback. If the callback returns true, keep iterating, else abort |
349 | | /// the iteration. |
350 | | void ForEachEnumerator( |
351 | | std::function<bool(const CompilerType &integer_type, ConstString name, |
352 | | const llvm::APSInt &value)> const &callback) const; |
353 | | |
354 | | uint32_t GetNumFields() const; |
355 | | |
356 | | CompilerType GetFieldAtIndex(size_t idx, std::string &name, |
357 | | uint64_t *bit_offset_ptr, |
358 | | uint32_t *bitfield_bit_size_ptr, |
359 | | bool *is_bitfield_ptr) const; |
360 | | |
361 | | uint32_t GetNumDirectBaseClasses() const; |
362 | | |
363 | | uint32_t GetNumVirtualBaseClasses() const; |
364 | | |
365 | | CompilerType GetDirectBaseClassAtIndex(size_t idx, |
366 | | uint32_t *bit_offset_ptr) const; |
367 | | |
368 | | CompilerType GetVirtualBaseClassAtIndex(size_t idx, |
369 | | uint32_t *bit_offset_ptr) const; |
370 | | |
371 | | uint32_t GetIndexOfFieldWithName(const char *name, |
372 | | CompilerType *field_compiler_type = nullptr, |
373 | | uint64_t *bit_offset_ptr = nullptr, |
374 | | uint32_t *bitfield_bit_size_ptr = nullptr, |
375 | | bool *is_bitfield_ptr = nullptr) const; |
376 | | |
377 | | CompilerType GetChildCompilerTypeAtIndex( |
378 | | ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, |
379 | | bool omit_empty_base_classes, bool ignore_array_bounds, |
380 | | std::string &child_name, uint32_t &child_byte_size, |
381 | | int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, |
382 | | uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, |
383 | | bool &child_is_deref_of_parent, ValueObject *valobj, |
384 | | uint64_t &language_flags) const; |
385 | | |
386 | | /// Lookup a child given a name. This function will match base class names and |
387 | | /// member member names in "clang_type" only, not descendants. |
388 | | uint32_t GetIndexOfChildWithName(llvm::StringRef name, |
389 | | bool omit_empty_base_classes) const; |
390 | | |
391 | | /// Lookup a child member given a name. This function will match member names |
392 | | /// only and will descend into "clang_type" children in search for the first |
393 | | /// member in this class, or any base class that matches "name". |
394 | | /// TODO: Return all matches for a given name by returning a |
395 | | /// vector<vector<uint32_t>> |
396 | | /// so we catch all names that match a given child name, not just the first. |
397 | | size_t |
398 | | GetIndexOfChildMemberWithName(llvm::StringRef name, |
399 | | bool omit_empty_base_classes, |
400 | | std::vector<uint32_t> &child_indexes) const; |
401 | | |
402 | | /// Return the number of template arguments the type has. |
403 | | /// If expand_pack is true, then variadic argument packs are automatically |
404 | | /// expanded to their supplied arguments. If it is false an argument pack |
405 | | /// will only count as 1 argument. |
406 | | size_t GetNumTemplateArguments(bool expand_pack = false) const; |
407 | | |
408 | | // Return the TemplateArgumentKind of the template argument at index idx. |
409 | | // If expand_pack is true, then variadic argument packs are automatically |
410 | | // expanded to their supplied arguments. With expand_pack set to false, an |
411 | | // arguement pack will count as 1 argument and return a type of Pack. |
412 | | lldb::TemplateArgumentKind |
413 | | GetTemplateArgumentKind(size_t idx, bool expand_pack = false) const; |
414 | | CompilerType GetTypeTemplateArgument(size_t idx, |
415 | | bool expand_pack = false) const; |
416 | | |
417 | | /// Returns the value of the template argument and its type. |
418 | | /// If expand_pack is true, then variadic argument packs are automatically |
419 | | /// expanded to their supplied arguments. With expand_pack set to false, an |
420 | | /// arguement pack will count as 1 argument and it is invalid to call this |
421 | | /// method on the pack argument. |
422 | | std::optional<IntegralTemplateArgument> |
423 | | GetIntegralTemplateArgument(size_t idx, bool expand_pack = false) const; |
424 | | |
425 | | CompilerType GetTypeForFormatters() const; |
426 | | |
427 | | LazyBool ShouldPrintAsOneLiner(ValueObject *valobj) const; |
428 | | |
429 | | bool IsMeaninglessWithoutDynamicResolution() const; |
430 | | /// \} |
431 | | |
432 | | /// Dumping types. |
433 | | /// \{ |
434 | | #ifndef NDEBUG |
435 | | /// Convenience LLVM-style dump method for use in the debugger only. |
436 | | /// Don't call this function from actual code. |
437 | | LLVM_DUMP_METHOD void dump() const; |
438 | | #endif |
439 | | |
440 | | void DumpValue(ExecutionContext *exe_ctx, Stream *s, lldb::Format format, |
441 | | const DataExtractor &data, lldb::offset_t data_offset, |
442 | | size_t data_byte_size, uint32_t bitfield_bit_size, |
443 | | uint32_t bitfield_bit_offset, bool show_types, |
444 | | bool show_summary, bool verbose, uint32_t depth); |
445 | | |
446 | | bool DumpTypeValue(Stream *s, lldb::Format format, const DataExtractor &data, |
447 | | lldb::offset_t data_offset, size_t data_byte_size, |
448 | | uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, |
449 | | ExecutionContextScope *exe_scope); |
450 | | |
451 | | void DumpSummary(ExecutionContext *exe_ctx, Stream *s, |
452 | | const DataExtractor &data, lldb::offset_t data_offset, |
453 | | size_t data_byte_size); |
454 | | |
455 | | /// Dump to stdout. |
456 | | void DumpTypeDescription(lldb::DescriptionLevel level = |
457 | | lldb::eDescriptionLevelFull) const; |
458 | | |
459 | | /// Print a description of the type to a stream. The exact implementation |
460 | | /// varies, but the expectation is that eDescriptionLevelFull returns a |
461 | | /// source-like representation of the type, whereas eDescriptionLevelVerbose |
462 | | /// does a dump of the underlying AST if applicable. |
463 | | void DumpTypeDescription(Stream *s, lldb::DescriptionLevel level = |
464 | | lldb::eDescriptionLevelFull) const; |
465 | | /// \} |
466 | | |
467 | | bool GetValueAsScalar(const DataExtractor &data, lldb::offset_t data_offset, |
468 | | size_t data_byte_size, Scalar &value, |
469 | | ExecutionContextScope *exe_scope) const; |
470 | 23.4k | void Clear() { |
471 | 23.4k | m_type_system = {}; |
472 | 23.4k | m_type = nullptr; |
473 | 23.4k | } |
474 | | |
475 | | private: |
476 | | #ifndef NDEBUG |
477 | | /// If the type is valid, ask the TypeSystem to verify the integrity |
478 | | /// of the type to catch CompilerTypes that mix and match invalid |
479 | | /// TypeSystem/Opaque type pairs. |
480 | | bool Verify() const; |
481 | | #endif |
482 | | |
483 | | lldb::TypeSystemWP m_type_system; |
484 | | lldb::opaque_compiler_type_t m_type = nullptr; |
485 | | }; |
486 | | |
487 | | bool operator==(const CompilerType &lhs, const CompilerType &rhs); |
488 | | bool operator!=(const CompilerType &lhs, const CompilerType &rhs); |
489 | | |
490 | | struct CompilerType::IntegralTemplateArgument { |
491 | | llvm::APSInt value; |
492 | | CompilerType type; |
493 | | }; |
494 | | |
495 | | } // namespace lldb_private |
496 | | |
497 | | #endif // LLDB_SYMBOL_COMPILERTYPE_H |