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