Skip to content

Commit e692d08

Browse files
authored
[LLDB] Add more helper functions to CompilerType class (second try). (#73472)
This adds 23 new helper functions to LLDB's CompilerType class, things like IsSmartPtrType, IsPromotableIntegerType, GetNumberofNonEmptyBaseClasses, and GetTemplateArgumentType (to name a few). It also has run clang-format on the files CompilerType.{h,cpp}. These helper functions are needed as part of the implementation for the Data Inspection Language, (see https://discourse.llvm.org/t/rfc-data-inspection-language/69893).
1 parent b1cc6f7 commit e692d08

File tree

2 files changed

+240
-0
lines changed

2 files changed

+240
-0
lines changed

lldb/include/lldb/Symbol/CompilerType.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,60 @@ class CompilerType {
194194
bool IsTypedefType() const;
195195

196196
bool IsVoidType() const;
197+
198+
/// This is used when you don't care about the signedness of the integer.
199+
bool IsInteger() const;
200+
201+
bool IsFloat() const;
202+
203+
/// This is used when you don't care about the signedness of the enum.
204+
bool IsEnumerationType() const;
205+
206+
bool IsUnscopedEnumerationType() const;
207+
208+
bool IsIntegerOrUnscopedEnumerationType() const;
209+
210+
bool IsSigned() const;
211+
212+
bool IsNullPtrType() const;
213+
214+
bool IsBoolean() const;
215+
216+
bool IsEnumerationIntegerTypeSigned() const;
217+
218+
bool IsScalarOrUnscopedEnumerationType() const;
219+
220+
bool IsPromotableIntegerType() const;
221+
222+
bool IsPointerToVoid() const;
223+
224+
bool IsRecordType() const;
225+
226+
//// Checks whether `target_base` is a virtual base of `type` (direct or
227+
/// indirect). If it is, stores the first virtual base type on the path from
228+
/// `type` to `target_type`. Parameter "virtual_base" is where the first
229+
/// virtual base type gets stored. Parameter "carry_virtual" is used to
230+
/// denote that we're in a recursive check of virtual base classes and we
231+
/// have already seen a virtual base class (so should only check direct
232+
/// base classes).
233+
/// Note: This may only be defined in TypeSystemClang.
234+
bool IsVirtualBase(CompilerType target_base, CompilerType *virtual_base,
235+
bool carry_virtual = false) const;
236+
237+
/// This may only be defined in TypeSystemClang.
238+
bool IsContextuallyConvertibleToBool() const;
239+
240+
bool IsBasicType() const;
241+
242+
std::string TypeDescription();
243+
244+
bool CompareTypes(CompilerType rhs) const;
245+
246+
const char *GetTypeTag();
247+
248+
/// Go through the base classes and count non-empty ones.
249+
uint32_t GetNumberOfNonEmptyBaseClasses();
250+
197251
/// \}
198252

199253
/// Type Completion.

lldb/source/Symbol/CompilerType.cpp

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,192 @@ bool CompilerType::IsBeingDefined() const {
302302
return false;
303303
}
304304

305+
bool CompilerType::IsInteger() const {
306+
bool is_signed = false; // May be reset by the call below.
307+
return IsIntegerType(is_signed);
308+
}
309+
310+
bool CompilerType::IsFloat() const {
311+
uint32_t count = 0;
312+
bool is_complex = false;
313+
return IsFloatingPointType(count, is_complex);
314+
}
315+
316+
bool CompilerType::IsEnumerationType() const {
317+
bool is_signed = false; // May be reset by the call below.
318+
return IsEnumerationType(is_signed);
319+
}
320+
321+
bool CompilerType::IsUnscopedEnumerationType() const {
322+
return IsEnumerationType() && !IsScopedEnumerationType();
323+
}
324+
325+
bool CompilerType::IsIntegerOrUnscopedEnumerationType() const {
326+
return IsInteger() || IsUnscopedEnumerationType();
327+
}
328+
329+
bool CompilerType::IsSigned() const {
330+
return GetTypeInfo() & lldb::eTypeIsSigned;
331+
}
332+
333+
bool CompilerType::IsNullPtrType() const {
334+
return GetCanonicalType().GetBasicTypeEnumeration() ==
335+
lldb::eBasicTypeNullPtr;
336+
}
337+
338+
bool CompilerType::IsBoolean() const {
339+
return GetCanonicalType().GetBasicTypeEnumeration() == lldb::eBasicTypeBool;
340+
}
341+
342+
bool CompilerType::IsEnumerationIntegerTypeSigned() const {
343+
if (IsValid())
344+
return GetEnumerationIntegerType().GetTypeInfo() & lldb::eTypeIsSigned;
345+
346+
return false;
347+
}
348+
349+
bool CompilerType::IsScalarOrUnscopedEnumerationType() const {
350+
return IsScalarType() || IsUnscopedEnumerationType();
351+
}
352+
353+
bool CompilerType::IsPromotableIntegerType() const {
354+
// Unscoped enums are always considered as promotable, even if their
355+
// underlying type does not need to be promoted (e.g. "int").
356+
if (IsUnscopedEnumerationType())
357+
return true;
358+
359+
switch (GetCanonicalType().GetBasicTypeEnumeration()) {
360+
case lldb::eBasicTypeBool:
361+
case lldb::eBasicTypeChar:
362+
case lldb::eBasicTypeSignedChar:
363+
case lldb::eBasicTypeUnsignedChar:
364+
case lldb::eBasicTypeShort:
365+
case lldb::eBasicTypeUnsignedShort:
366+
case lldb::eBasicTypeWChar:
367+
case lldb::eBasicTypeSignedWChar:
368+
case lldb::eBasicTypeUnsignedWChar:
369+
case lldb::eBasicTypeChar16:
370+
case lldb::eBasicTypeChar32:
371+
return true;
372+
373+
default:
374+
return false;
375+
}
376+
377+
llvm_unreachable("All cases handled above.");
378+
}
379+
380+
bool CompilerType::IsPointerToVoid() const {
381+
if (!IsValid())
382+
return false;
383+
384+
return IsPointerType() &&
385+
GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid;
386+
}
387+
388+
bool CompilerType::IsRecordType() const {
389+
if (!IsValid())
390+
return false;
391+
392+
return GetCanonicalType().GetTypeClass() &
393+
(lldb::eTypeClassClass | lldb::eTypeClassStruct |
394+
lldb::eTypeClassUnion);
395+
}
396+
397+
bool CompilerType::IsVirtualBase(CompilerType target_base,
398+
CompilerType *virtual_base,
399+
bool carry_virtual) const {
400+
if (CompareTypes(target_base))
401+
return carry_virtual;
402+
403+
if (!carry_virtual) {
404+
uint32_t num_virtual_bases = GetNumVirtualBaseClasses();
405+
for (uint32_t i = 0; i < num_virtual_bases; ++i) {
406+
uint32_t bit_offset;
407+
auto base = GetVirtualBaseClassAtIndex(i, &bit_offset);
408+
if (base.IsVirtualBase(target_base, virtual_base,
409+
/*carry_virtual*/ true)) {
410+
if (virtual_base)
411+
*virtual_base = base;
412+
413+
return true;
414+
}
415+
}
416+
}
417+
418+
uint32_t num_direct_bases = GetNumDirectBaseClasses();
419+
for (uint32_t i = 0; i < num_direct_bases; ++i) {
420+
uint32_t bit_offset;
421+
auto base = GetDirectBaseClassAtIndex(i, &bit_offset);
422+
if (base.IsVirtualBase(target_base, virtual_base, carry_virtual))
423+
return true;
424+
}
425+
426+
return false;
427+
}
428+
429+
bool CompilerType::IsContextuallyConvertibleToBool() const {
430+
return IsScalarType() || IsUnscopedEnumerationType() || IsPointerType() ||
431+
IsNullPtrType() || IsArrayType();
432+
}
433+
434+
bool CompilerType::IsBasicType() const {
435+
return GetCanonicalType().GetBasicTypeEnumeration() !=
436+
lldb::eBasicTypeInvalid;
437+
}
438+
439+
std::string CompilerType::TypeDescription() {
440+
auto name = GetTypeName();
441+
auto canonical_name = GetCanonicalType().GetTypeName();
442+
if (name.IsEmpty() || canonical_name.IsEmpty())
443+
return "''"; // Should not happen, unless the input is broken somehow.
444+
445+
if (name == canonical_name)
446+
return llvm::formatv("'{0}'", name);
447+
448+
return llvm::formatv("'{0}' (canonically referred to as '{1}')", name,
449+
canonical_name);
450+
}
451+
452+
bool CompilerType::CompareTypes(CompilerType rhs) const {
453+
if (*this == rhs)
454+
return true;
455+
456+
const ConstString name = GetFullyUnqualifiedType().GetTypeName();
457+
const ConstString rhs_name = rhs.GetFullyUnqualifiedType().GetTypeName();
458+
return name == rhs_name;
459+
}
460+
461+
const char *CompilerType::GetTypeTag() {
462+
switch (GetTypeClass()) {
463+
case lldb::eTypeClassClass:
464+
return "class";
465+
case lldb::eTypeClassEnumeration:
466+
return "enum";
467+
case lldb::eTypeClassStruct:
468+
return "struct";
469+
case lldb::eTypeClassUnion:
470+
return "union";
471+
default:
472+
return "unknown";
473+
}
474+
llvm_unreachable("All cases are covered by code above.");
475+
}
476+
477+
uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() {
478+
uint32_t ret = 0;
479+
uint32_t num_direct_bases = GetNumDirectBaseClasses();
480+
481+
for (uint32_t i = 0; i < num_direct_bases; ++i) {
482+
uint32_t bit_offset;
483+
CompilerType base_type = GetDirectBaseClassAtIndex(i, &bit_offset);
484+
if (base_type.GetNumFields() > 0 ||
485+
base_type.GetNumberOfNonEmptyBaseClasses() > 0)
486+
ret += 1;
487+
}
488+
return ret;
489+
}
490+
305491
// Type Completion
306492

307493
bool CompilerType::GetCompleteType() const {

0 commit comments

Comments
 (0)