Author: cmtice Date: 2023-12-14T14:10:19-08:00 New Revision: e692d0836003dead19070e5f7d199a48fa082f72
URL: https://github.com/llvm/llvm-project/commit/e692d0836003dead19070e5f7d199a48fa082f72 DIFF: https://github.com/llvm/llvm-project/commit/e692d0836003dead19070e5f7d199a48fa082f72.diff LOG: [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). Added: Modified: lldb/include/lldb/Symbol/CompilerType.h lldb/source/Symbol/CompilerType.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 0a9533a1ac0efc..414c44275aaafc 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -194,6 +194,60 @@ class CompilerType { bool IsTypedefType() const; bool IsVoidType() const; + + /// This is used when you don't care about the signedness of the integer. + bool IsInteger() const; + + bool IsFloat() const; + + /// This is used when you don't care about the signedness of the enum. + bool IsEnumerationType() const; + + bool IsUnscopedEnumerationType() const; + + bool IsIntegerOrUnscopedEnumerationType() const; + + bool IsSigned() const; + + bool IsNullPtrType() const; + + bool IsBoolean() const; + + bool IsEnumerationIntegerTypeSigned() const; + + bool IsScalarOrUnscopedEnumerationType() const; + + bool IsPromotableIntegerType() const; + + bool IsPointerToVoid() const; + + bool IsRecordType() const; + + //// Checks whether `target_base` is a virtual base of `type` (direct or + /// indirect). If it is, stores the first virtual base type on the path from + /// `type` to `target_type`. Parameter "virtual_base" is where the first + /// virtual base type gets stored. Parameter "carry_virtual" is used to + /// denote that we're in a recursive check of virtual base classes and we + /// have already seen a virtual base class (so should only check direct + /// base classes). + /// Note: This may only be defined in TypeSystemClang. + bool IsVirtualBase(CompilerType target_base, CompilerType *virtual_base, + bool carry_virtual = false) const; + + /// This may only be defined in TypeSystemClang. + bool IsContextuallyConvertibleToBool() const; + + bool IsBasicType() const; + + std::string TypeDescription(); + + bool CompareTypes(CompilerType rhs) const; + + const char *GetTypeTag(); + + /// Go through the base classes and count non-empty ones. + uint32_t GetNumberOfNonEmptyBaseClasses(); + /// \} /// Type Completion. diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 78cc8dad94a9c5..76b79daa6ac154 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -302,6 +302,192 @@ bool CompilerType::IsBeingDefined() const { return false; } +bool CompilerType::IsInteger() const { + bool is_signed = false; // May be reset by the call below. + return IsIntegerType(is_signed); +} + +bool CompilerType::IsFloat() const { + uint32_t count = 0; + bool is_complex = false; + return IsFloatingPointType(count, is_complex); +} + +bool CompilerType::IsEnumerationType() const { + bool is_signed = false; // May be reset by the call below. + return IsEnumerationType(is_signed); +} + +bool CompilerType::IsUnscopedEnumerationType() const { + return IsEnumerationType() && !IsScopedEnumerationType(); +} + +bool CompilerType::IsIntegerOrUnscopedEnumerationType() const { + return IsInteger() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsSigned() const { + return GetTypeInfo() & lldb::eTypeIsSigned; +} + +bool CompilerType::IsNullPtrType() const { + return GetCanonicalType().GetBasicTypeEnumeration() == + lldb::eBasicTypeNullPtr; +} + +bool CompilerType::IsBoolean() const { + return GetCanonicalType().GetBasicTypeEnumeration() == lldb::eBasicTypeBool; +} + +bool CompilerType::IsEnumerationIntegerTypeSigned() const { + if (IsValid()) + return GetEnumerationIntegerType().GetTypeInfo() & lldb::eTypeIsSigned; + + return false; +} + +bool CompilerType::IsScalarOrUnscopedEnumerationType() const { + return IsScalarType() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsPromotableIntegerType() const { + // Unscoped enums are always considered as promotable, even if their + // underlying type does not need to be promoted (e.g. "int"). + if (IsUnscopedEnumerationType()) + return true; + + switch (GetCanonicalType().GetBasicTypeEnumeration()) { + case lldb::eBasicTypeBool: + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + case lldb::eBasicTypeWChar: + case lldb::eBasicTypeSignedWChar: + case lldb::eBasicTypeUnsignedWChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; + + default: + return false; + } + + llvm_unreachable("All cases handled above."); +} + +bool CompilerType::IsPointerToVoid() const { + if (!IsValid()) + return false; + + return IsPointerType() && + GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid; +} + +bool CompilerType::IsRecordType() const { + if (!IsValid()) + return false; + + return GetCanonicalType().GetTypeClass() & + (lldb::eTypeClassClass | lldb::eTypeClassStruct | + lldb::eTypeClassUnion); +} + +bool CompilerType::IsVirtualBase(CompilerType target_base, + CompilerType *virtual_base, + bool carry_virtual) const { + if (CompareTypes(target_base)) + return carry_virtual; + + if (!carry_virtual) { + uint32_t num_virtual_bases = GetNumVirtualBaseClasses(); + for (uint32_t i = 0; i < num_virtual_bases; ++i) { + uint32_t bit_offset; + auto base = GetVirtualBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, + /*carry_virtual*/ true)) { + if (virtual_base) + *virtual_base = base; + + return true; + } + } + } + + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + auto base = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, carry_virtual)) + return true; + } + + return false; +} + +bool CompilerType::IsContextuallyConvertibleToBool() const { + return IsScalarType() || IsUnscopedEnumerationType() || IsPointerType() || + IsNullPtrType() || IsArrayType(); +} + +bool CompilerType::IsBasicType() const { + return GetCanonicalType().GetBasicTypeEnumeration() != + lldb::eBasicTypeInvalid; +} + +std::string CompilerType::TypeDescription() { + auto name = GetTypeName(); + auto canonical_name = GetCanonicalType().GetTypeName(); + if (name.IsEmpty() || canonical_name.IsEmpty()) + return "''"; // Should not happen, unless the input is broken somehow. + + if (name == canonical_name) + return llvm::formatv("'{0}'", name); + + return llvm::formatv("'{0}' (canonically referred to as '{1}')", name, + canonical_name); +} + +bool CompilerType::CompareTypes(CompilerType rhs) const { + if (*this == rhs) + return true; + + const ConstString name = GetFullyUnqualifiedType().GetTypeName(); + const ConstString rhs_name = rhs.GetFullyUnqualifiedType().GetTypeName(); + return name == rhs_name; +} + +const char *CompilerType::GetTypeTag() { + switch (GetTypeClass()) { + case lldb::eTypeClassClass: + return "class"; + case lldb::eTypeClassEnumeration: + return "enum"; + case lldb::eTypeClassStruct: + return "struct"; + case lldb::eTypeClassUnion: + return "union"; + default: + return "unknown"; + } + llvm_unreachable("All cases are covered by code above."); +} + +uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() { + uint32_t ret = 0; + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + CompilerType base_type = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base_type.GetNumFields() > 0 || + base_type.GetNumberOfNonEmptyBaseClasses() > 0) + ret += 1; + } + return ret; +} + // Type Completion bool CompilerType::GetCompleteType() const { _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits