[Lldb-commits] [lldb] [LLDB] Add more helper functions to CompilerType class (second try). (PR #73472)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Dec 6 10:04:07 PST 2023
https://github.com/cmtice updated https://github.com/llvm/llvm-project/pull/73472
>From a063ebd8ee8bbd491fff3449bc20d663d2e501ea Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Sun, 26 Nov 2023 17:24:39 -0800
Subject: [PATCH 1/4] [LLDB] Add more helper functions to CompilerType class
(second try).
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).
---
lldb/include/lldb/Symbol/CompilerType.h | 56 ++++-
lldb/source/Symbol/CompilerType.cpp | 285 ++++++++++++++++++++++--
2 files changed, 320 insertions(+), 21 deletions(-)
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 0a9533a1ac0ef..a3331ad3269c0 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -112,9 +112,7 @@ class CompilerType {
/// Tests.
/// \{
- explicit operator bool() const {
- return m_type_system.lock() && m_type;
- }
+ explicit operator bool() const { return m_type_system.lock() && m_type; }
bool IsValid() const { return (bool)*this; }
@@ -194,6 +192,54 @@ class CompilerType {
bool IsTypedefType() const;
bool IsVoidType() const;
+
+ bool IsSmartPtrType() const;
+
+ bool IsInteger() const;
+
+ bool IsFloat() const;
+
+ 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;
+
+ bool IsVirtualBase(CompilerType target_base, CompilerType *virtual_base,
+ bool carry_virtual = false) const;
+
+ bool IsContextuallyConvertibleToBool() const;
+
+ bool IsBasicType() const;
+
+ std::string TypeDescription();
+
+ bool CompareTypes(CompilerType rhs) const;
+
+ const char *GetTypeTag();
+
+ uint32_t GetNumberOfNonEmptyBaseClasses();
+
+ CompilerType GetTemplateArgumentType(uint32_t idx);
+
+ CompilerType GetSmartPtrPointeeType();
+
/// \}
/// Type Completion.
@@ -436,8 +482,8 @@ class CompilerType {
ExecutionContextScope *exe_scope);
/// Dump to stdout.
- void DumpTypeDescription(lldb::DescriptionLevel level =
- lldb::eDescriptionLevelFull) const;
+ void DumpTypeDescription(
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) const;
/// Print a description of the type to a stream. The exact implementation
/// varies, but the expectation is that eDescriptionLevelFull returns a
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 78cc8dad94a9c..854d6cab01b50 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -54,7 +54,7 @@ bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->IsArrayType(m_type, element_type_ptr, size,
- is_incomplete);
+ is_incomplete);
if (element_type_ptr)
element_type_ptr->Clear();
@@ -157,7 +157,8 @@ bool CompilerType::IsBlockPointerType(
CompilerType *function_pointer_type_ptr) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->IsBlockPointerType(m_type, function_pointer_type_ptr);
+ return type_system_sp->IsBlockPointerType(m_type,
+ function_pointer_type_ptr);
return false;
}
@@ -249,7 +250,7 @@ bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->IsPossibleDynamicType(m_type, dynamic_pointee_type,
- check_cplusplus, check_objc);
+ check_cplusplus, check_objc);
return false;
}
@@ -302,6 +303,256 @@ bool CompilerType::IsBeingDefined() const {
return false;
}
+bool CompilerType::IsSmartPtrType() const {
+ // These regular expressions cover shared, unique and weak pointers both from
+ // stdlibc++ and libc+++.
+
+ static llvm::Regex k_libcxx_std_unique_ptr_regex(
+ "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
+ static llvm::Regex k_libcxx_std_shared_ptr_regex(
+ "^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$");
+ static llvm::Regex k_libcxx_std_weak_ptr_regex(
+ "^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$");
+ //
+ static llvm::Regex k_libcxx_std_unique_ptr_regex_2(
+ "^std::unique_ptr<.+>(( )?&)?$");
+ static llvm::Regex k_libcxx_std_shared_ptr_regex_2(
+ "^std::shared_ptr<.+>(( )?&)?$");
+ static llvm::Regex k_libcxx_std_weak_ptr_regex_2(
+ "^std::weak_ptr<.+>(( )?&)?$");
+ //
+ llvm::StringRef name = GetTypeName();
+ return k_libcxx_std_unique_ptr_regex.match(name) ||
+ k_libcxx_std_shared_ptr_regex.match(name) ||
+ k_libcxx_std_weak_ptr_regex.match(name) ||
+ k_libcxx_std_unique_ptr_regex_2.match(name) ||
+ k_libcxx_std_shared_ptr_regex_2.match(name) ||
+ k_libcxx_std_weak_ptr_regex_2.match(name);
+}
+
+bool CompilerType::IsInteger() const {
+ // This is used when you don't care about the signedness of the integer.
+ bool is_signed;
+ 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 {
+ // This is used when you don't care about the signedness of the enum.
+ bool is_signed;
+ return IsEnumerationType(is_signed);
+}
+
+bool CompilerType::IsUnscopedEnumerationType() const {
+ return IsEnumerationType() && !IsScopedEnumerationType();
+}
+
+bool CompilerType::IsIntegerOrUnscopedEnumerationType() const {
+ return IsInteger() || IsUnscopedEnumerationType();
+}
+
+bool CompilerType::IsSigned() const {
+ if (IsEnumerationType()) {
+ return IsEnumerationIntegerTypeSigned();
+ }
+ 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;
+ }
+}
+
+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);
+}
+
+// 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`.
+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
+ }
+ if (name == canonical_name) {
+ return llvm::formatv("'{0}'", name);
+ }
+ return llvm::formatv("'{0}' (aka '{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()) {
+ // clang-format off
+ case lldb::eTypeClassClass: return "class";
+ case lldb::eTypeClassEnumeration: return "enum";
+ case lldb::eTypeClassStruct: return "struct";
+ case lldb::eTypeClassUnion: return "union";
+ // clang-format on
+ default:
+ return "unknown";
+ }
+}
+
+uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() {
+ // Go through the base classes and count non-empty ones.
+ 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;
+}
+
+CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) {
+ CompilerType empty_type;
+ if (!IsValid())
+ return empty_type;
+
+ CompilerType type;
+ const bool expand_pack = true;
+ switch (GetTemplateArgumentKind(idx, true)) {
+ case lldb::eTemplateArgumentKindType:
+ type = GetTypeTemplateArgument(idx, expand_pack);
+ break;
+ case lldb::eTemplateArgumentKindIntegral:
+ type = GetIntegralTemplateArgument(idx, expand_pack)->type;
+ break;
+ default:
+ break;
+ }
+ if (type.IsValid())
+ return type;
+ return empty_type;
+}
+
+CompilerType CompilerType::GetSmartPtrPointeeType() {
+ assert(IsSmartPtrType() &&
+ "the type should be a smart pointer (std::unique_ptr, std::shared_ptr "
+ "or std::weak_ptr");
+
+ return GetTemplateArgumentType(0);
+}
+
// Type Completion
bool CompilerType::GetCompleteType() const {
@@ -336,9 +587,9 @@ ConstString CompilerType::GetDisplayTypeName() const {
uint32_t CompilerType::GetTypeInfo(
CompilerType *pointee_or_element_compiler_type) const {
if (IsValid())
- if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->GetTypeInfo(m_type,
- pointee_or_element_compiler_type);
+ if (auto type_system_sp = GetTypeSystem())
+ return type_system_sp->GetTypeInfo(m_type,
+ pointee_or_element_compiler_type);
return 0;
}
@@ -362,8 +613,9 @@ void CompilerType::SetCompilerType(lldb::TypeSystemWP type_system,
m_type = type;
}
-void CompilerType::SetCompilerType(CompilerType::TypeSystemSPWrapper type_system,
- lldb::opaque_compiler_type_t type) {
+void CompilerType::SetCompilerType(
+ CompilerType::TypeSystemSPWrapper type_system,
+ lldb::opaque_compiler_type_t type) {
m_type_system = type_system.GetSharedPointer();
m_type = type;
}
@@ -589,7 +841,7 @@ uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes,
- exe_ctx);
+ exe_ctx);
return 0;
}
@@ -601,8 +853,7 @@ lldb::BasicType CompilerType::GetBasicTypeEnumeration() const {
}
void CompilerType::ForEachEnumerator(
- std::function<bool(const CompilerType &integer_type,
- ConstString name,
+ std::function<bool(const CompilerType &integer_type, ConstString name,
const llvm::APSInt &value)> const &callback) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
@@ -623,7 +874,8 @@ CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr,
- bitfield_bit_size_ptr, is_bitfield_ptr);
+ bitfield_bit_size_ptr,
+ is_bitfield_ptr);
return CompilerType();
}
@@ -647,7 +899,7 @@ CompilerType::GetDirectBaseClassAtIndex(size_t idx,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetDirectBaseClassAtIndex(m_type, idx,
- bit_offset_ptr);
+ bit_offset_ptr);
return CompilerType();
}
@@ -657,7 +909,7 @@ CompilerType::GetVirtualBaseClassAtIndex(size_t idx,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetVirtualBaseClassAtIndex(m_type, idx,
- bit_offset_ptr);
+ bit_offset_ptr);
return CompilerType();
}
@@ -738,7 +990,7 @@ size_t CompilerType::GetIndexOfChildMemberWithName(
if (IsValid() && !name.empty()) {
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetIndexOfChildMemberWithName(
- m_type, name, omit_empty_base_classes, child_indexes);
+ m_type, name, omit_empty_base_classes, child_indexes);
}
return 0;
}
@@ -772,7 +1024,8 @@ std::optional<CompilerType::IntegralTemplateArgument>
CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->GetIntegralTemplateArgument(m_type, idx, expand_pack);
+ return type_system_sp->GetIntegralTemplateArgument(m_type, idx,
+ expand_pack);
return std::nullopt;
}
>From 29cd28dc39af596a0a126dbf9cf3d1b233fc78be Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Wed, 29 Nov 2023 12:35:47 -0800
Subject: [PATCH 2/4] [LLDB] Add more helper functions to CompilerType class
(second try).
Address most of the reviewer comments:
- Fix formatting issues
- Add/Move Doxygen function comments in header file.
- Undo clang-format changes to code that I didn't touch.
- Other requested fixes.
---
lldb/include/lldb/Symbol/CompilerType.h | 19 +++-
lldb/source/Symbol/CompilerType.cpp | 131 +++++++++++-------------
2 files changed, 78 insertions(+), 72 deletions(-)
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index a3331ad3269c0..274b1a60a5c6a 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -112,7 +112,9 @@ class CompilerType {
/// Tests.
/// \{
- explicit operator bool() const { return m_type_system.lock() && m_type; }
+ explicit operator bool() const {
+ return m_type_system.lock() && m_type;
+ }
bool IsValid() const { return (bool)*this; }
@@ -193,12 +195,16 @@ class CompilerType {
bool IsVoidType() const;
+ /// This determines if the type is a shared, unique or weak pointer, either
+ /// from stdlibc++ or libc+++.
bool IsSmartPtrType() 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;
@@ -221,9 +227,15 @@ class CompilerType {
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. 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;
@@ -234,6 +246,7 @@ class CompilerType {
const char *GetTypeTag();
+ /// Go through the base classes and count non-empty ones.
uint32_t GetNumberOfNonEmptyBaseClasses();
CompilerType GetTemplateArgumentType(uint32_t idx);
@@ -482,8 +495,8 @@ class CompilerType {
ExecutionContextScope *exe_scope);
/// Dump to stdout.
- void DumpTypeDescription(
- lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) const;
+ void DumpTypeDescription(lldb::DescriptionLevel level =
+ lldb::eDescriptionLevelFull) const;
/// Print a description of the type to a stream. The exact implementation
/// varies, but the expectation is that eDescriptionLevelFull returns a
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 854d6cab01b50..089199ae5310d 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -54,7 +54,7 @@ bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->IsArrayType(m_type, element_type_ptr, size,
- is_incomplete);
+ is_incomplete);
if (element_type_ptr)
element_type_ptr->Clear();
@@ -157,8 +157,7 @@ bool CompilerType::IsBlockPointerType(
CompilerType *function_pointer_type_ptr) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->IsBlockPointerType(m_type,
- function_pointer_type_ptr);
+ return type_system_sp->IsBlockPointerType(m_type, function_pointer_type_ptr);
return false;
}
@@ -250,7 +249,7 @@ bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->IsPossibleDynamicType(m_type, dynamic_pointee_type,
- check_cplusplus, check_objc);
+ check_cplusplus, check_objc);
return false;
}
@@ -304,35 +303,34 @@ bool CompilerType::IsBeingDefined() const {
}
bool CompilerType::IsSmartPtrType() const {
- // These regular expressions cover shared, unique and weak pointers both from
- // stdlibc++ and libc+++.
- static llvm::Regex k_libcxx_std_unique_ptr_regex(
+ // libc++ smart pointers
+ static const llvm::Regex k_libcxx_std_unique_ptr_regex(
"^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
- static llvm::Regex k_libcxx_std_shared_ptr_regex(
+ static const llvm::Regex k_libcxx_std_shared_ptr_regex(
"^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$");
- static llvm::Regex k_libcxx_std_weak_ptr_regex(
+ static const llvm::Regex k_libcxx_std_weak_ptr_regex(
"^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$");
- //
- static llvm::Regex k_libcxx_std_unique_ptr_regex_2(
+
+ // libstdc++ smart pointers
+ static const llvm::Regex k_libstdcxx_std_unique_ptr_regex(
"^std::unique_ptr<.+>(( )?&)?$");
- static llvm::Regex k_libcxx_std_shared_ptr_regex_2(
+ static const llvm::Regex k_libstdcxx_std_shared_ptr_regex(
"^std::shared_ptr<.+>(( )?&)?$");
- static llvm::Regex k_libcxx_std_weak_ptr_regex_2(
+ static const llvm::Regex k_libstdcxx_std_weak_ptr_regex(
"^std::weak_ptr<.+>(( )?&)?$");
- //
+
llvm::StringRef name = GetTypeName();
return k_libcxx_std_unique_ptr_regex.match(name) ||
k_libcxx_std_shared_ptr_regex.match(name) ||
k_libcxx_std_weak_ptr_regex.match(name) ||
- k_libcxx_std_unique_ptr_regex_2.match(name) ||
- k_libcxx_std_shared_ptr_regex_2.match(name) ||
- k_libcxx_std_weak_ptr_regex_2.match(name);
+ k_libstdcxx_std_unique_ptr_regex.match(name) ||
+ k_libstdcxx_std_shared_ptr_regex.match(name) ||
+ k_libstdcxx_std_weak_ptr_regex.match(name);
}
bool CompilerType::IsInteger() const {
- // This is used when you don't care about the signedness of the integer.
- bool is_signed;
+ bool is_signed = false; // May be reset by the call below.
return IsIntegerType(is_signed);
}
@@ -343,8 +341,7 @@ bool CompilerType::IsFloat() const {
}
bool CompilerType::IsEnumerationType() const {
- // This is used when you don't care about the signedness of the enum.
- bool is_signed;
+ bool is_signed = false; // May be reset by the call below.
return IsEnumerationType(is_signed);
}
@@ -357,9 +354,9 @@ bool CompilerType::IsIntegerOrUnscopedEnumerationType() const {
}
bool CompilerType::IsSigned() const {
- if (IsEnumerationType()) {
+ if (IsEnumerationType())
return IsEnumerationIntegerTypeSigned();
- }
+
return GetTypeInfo() & lldb::eTypeIsSigned;
}
@@ -373,9 +370,9 @@ bool CompilerType::IsBoolean() const {
}
bool CompilerType::IsEnumerationIntegerTypeSigned() const {
- if (IsValid()) {
+ if (IsValid())
return GetEnumerationIntegerType().GetTypeInfo() & lldb::eTypeIsSigned;
- }
+
return false;
}
@@ -386,9 +383,8 @@ bool CompilerType::IsScalarOrUnscopedEnumerationType() const {
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()) {
+ if (IsUnscopedEnumerationType())
return true;
- }
switch (GetCanonicalType().GetBasicTypeEnumeration()) {
case lldb::eBasicTypeBool:
@@ -407,6 +403,8 @@ bool CompilerType::IsPromotableIntegerType() const {
default:
return false;
}
+
+ llvm_unreachable("All cases handled above.");
}
bool CompilerType::IsPointerToVoid() const {
@@ -426,15 +424,11 @@ bool CompilerType::IsRecordType() const {
lldb::eTypeClassUnion);
}
-// 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`.
bool CompilerType::IsVirtualBase(CompilerType target_base,
CompilerType *virtual_base,
bool carry_virtual) const {
- if (CompareTypes(target_base)) {
+ if (CompareTypes(target_base))
return carry_virtual;
- }
if (!carry_virtual) {
uint32_t num_virtual_bases = GetNumVirtualBaseClasses();
@@ -443,9 +437,9 @@ bool CompilerType::IsVirtualBase(CompilerType target_base,
auto base = GetVirtualBaseClassAtIndex(i, &bit_offset);
if (base.IsVirtualBase(target_base, virtual_base,
/*carry_virtual*/ true)) {
- if (virtual_base) {
+ if (virtual_base)
*virtual_base = base;
- }
+
return true;
}
}
@@ -455,9 +449,8 @@ bool CompilerType::IsVirtualBase(CompilerType target_base,
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)) {
+ if (base.IsVirtualBase(target_base, virtual_base, carry_virtual))
return true;
- }
}
return false;
@@ -476,13 +469,14 @@ bool CompilerType::IsBasicType() const {
std::string CompilerType::TypeDescription() {
auto name = GetTypeName();
auto canonical_name = GetCanonicalType().GetTypeName();
- if (name.IsEmpty() || canonical_name.IsEmpty()) {
- return "''"; // should not happen
- }
- if (name == canonical_name) {
+ 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}' (aka '{1}')", name, canonical_name);
+
+ return llvm::formatv("'{0}' (canonically referred to as '{1}')", name,
+ canonical_name);
}
bool CompilerType::CompareTypes(CompilerType rhs) const {
@@ -496,19 +490,21 @@ bool CompilerType::CompareTypes(CompilerType rhs) const {
const char *CompilerType::GetTypeTag() {
switch (GetTypeClass()) {
- // clang-format off
- case lldb::eTypeClassClass: return "class";
- case lldb::eTypeClassEnumeration: return "enum";
- case lldb::eTypeClassStruct: return "struct";
- case lldb::eTypeClassUnion: return "union";
- // clang-format on
+ 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() {
- // Go through the base classes and count non-empty ones.
uint32_t ret = 0;
uint32_t num_direct_bases = GetNumDirectBaseClasses();
@@ -516,9 +512,8 @@ uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() {
uint32_t bit_offset;
CompilerType base_type = GetDirectBaseClassAtIndex(i, &bit_offset);
if (base_type.GetNumFields() > 0 ||
- base_type.GetNumberOfNonEmptyBaseClasses() > 0) {
+ base_type.GetNumberOfNonEmptyBaseClasses() > 0)
ret += 1;
- }
}
return ret;
}
@@ -546,9 +541,9 @@ CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) {
}
CompilerType CompilerType::GetSmartPtrPointeeType() {
- assert(IsSmartPtrType() &&
- "the type should be a smart pointer (std::unique_ptr, std::shared_ptr "
- "or std::weak_ptr");
+ if (!IsSmartPtrType())
+ // TODO: Should consider issuing a warning here.
+ return GetPointeeType();
return GetTemplateArgumentType(0);
}
@@ -587,9 +582,9 @@ ConstString CompilerType::GetDisplayTypeName() const {
uint32_t CompilerType::GetTypeInfo(
CompilerType *pointee_or_element_compiler_type) const {
if (IsValid())
- if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->GetTypeInfo(m_type,
- pointee_or_element_compiler_type);
+ if (auto type_system_sp = GetTypeSystem())
+ return type_system_sp->GetTypeInfo(m_type,
+ pointee_or_element_compiler_type);
return 0;
}
@@ -613,9 +608,8 @@ void CompilerType::SetCompilerType(lldb::TypeSystemWP type_system,
m_type = type;
}
-void CompilerType::SetCompilerType(
- CompilerType::TypeSystemSPWrapper type_system,
- lldb::opaque_compiler_type_t type) {
+void CompilerType::SetCompilerType(CompilerType::TypeSystemSPWrapper type_system,
+ lldb::opaque_compiler_type_t type) {
m_type_system = type_system.GetSharedPointer();
m_type = type;
}
@@ -841,7 +835,7 @@ uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes,
- exe_ctx);
+ exe_ctx);
return 0;
}
@@ -853,7 +847,8 @@ lldb::BasicType CompilerType::GetBasicTypeEnumeration() const {
}
void CompilerType::ForEachEnumerator(
- std::function<bool(const CompilerType &integer_type, ConstString name,
+ std::function<bool(const CompilerType &integer_type,
+ ConstString name,
const llvm::APSInt &value)> const &callback) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
@@ -874,8 +869,7 @@ CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr,
- bitfield_bit_size_ptr,
- is_bitfield_ptr);
+ bitfield_bit_size_ptr, is_bitfield_ptr);
return CompilerType();
}
@@ -899,7 +893,7 @@ CompilerType::GetDirectBaseClassAtIndex(size_t idx,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetDirectBaseClassAtIndex(m_type, idx,
- bit_offset_ptr);
+ bit_offset_ptr);
return CompilerType();
}
@@ -909,7 +903,7 @@ CompilerType::GetVirtualBaseClassAtIndex(size_t idx,
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetVirtualBaseClassAtIndex(m_type, idx,
- bit_offset_ptr);
+ bit_offset_ptr);
return CompilerType();
}
@@ -990,7 +984,7 @@ size_t CompilerType::GetIndexOfChildMemberWithName(
if (IsValid() && !name.empty()) {
if (auto type_system_sp = GetTypeSystem())
return type_system_sp->GetIndexOfChildMemberWithName(
- m_type, name, omit_empty_base_classes, child_indexes);
+ m_type, name, omit_empty_base_classes, child_indexes);
}
return 0;
}
@@ -1024,8 +1018,7 @@ std::optional<CompilerType::IntegralTemplateArgument>
CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const {
if (IsValid())
if (auto type_system_sp = GetTypeSystem())
- return type_system_sp->GetIntegralTemplateArgument(m_type, idx,
- expand_pack);
+ return type_system_sp->GetIntegralTemplateArgument(m_type, idx, expand_pack);
return std::nullopt;
}
>From 6ea102eb67e3a8723e3b1e2356df548328571ec5 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Tue, 5 Dec 2023 07:11:40 -0800
Subject: [PATCH 3/4] [LLDB] Add more helper functions to CompilerType class
(second try).
Update comment for "IsVirtualBase" member function as requested.
---
lldb/include/lldb/Symbol/CompilerType.h | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 274b1a60a5c6a..6f275b454ccd0 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -230,8 +230,11 @@ class CompilerType {
//// 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. Note: This may only be defined in
- /// TypeSystemClang.
+ /// 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;
>From 11a10240c32d24aa2b49e50c3476a5d6f16921b1 Mon Sep 17 00:00:00 2001
From: Caroline Tice <cmtice at google.com>
Date: Wed, 6 Dec 2023 10:01:44 -0800
Subject: [PATCH 4/4] [LLDB] Add more helper functions to CompilerType class
(second try).
Remove smart pointer functions from the new helper functions for
CompilerType class.
---
lldb/include/lldb/Symbol/CompilerType.h | 6 -----
lldb/source/Symbol/CompilerType.cpp | 35 -------------------------
2 files changed, 41 deletions(-)
diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 6f275b454ccd0..559146aa6ae94 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -195,10 +195,6 @@ class CompilerType {
bool IsVoidType() const;
- /// This determines if the type is a shared, unique or weak pointer, either
- /// from stdlibc++ or libc+++.
- bool IsSmartPtrType() const;
-
/// This is used when you don't care about the signedness of the integer.
bool IsInteger() const;
@@ -254,8 +250,6 @@ class CompilerType {
CompilerType GetTemplateArgumentType(uint32_t idx);
- CompilerType GetSmartPtrPointeeType();
-
/// \}
/// Type Completion.
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 089199ae5310d..d8d1537d0bed6 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -302,33 +302,6 @@ bool CompilerType::IsBeingDefined() const {
return false;
}
-bool CompilerType::IsSmartPtrType() const {
-
- // libc++ smart pointers
- static const llvm::Regex k_libcxx_std_unique_ptr_regex(
- "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$");
- static const llvm::Regex k_libcxx_std_shared_ptr_regex(
- "^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$");
- static const llvm::Regex k_libcxx_std_weak_ptr_regex(
- "^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$");
-
- // libstdc++ smart pointers
- static const llvm::Regex k_libstdcxx_std_unique_ptr_regex(
- "^std::unique_ptr<.+>(( )?&)?$");
- static const llvm::Regex k_libstdcxx_std_shared_ptr_regex(
- "^std::shared_ptr<.+>(( )?&)?$");
- static const llvm::Regex k_libstdcxx_std_weak_ptr_regex(
- "^std::weak_ptr<.+>(( )?&)?$");
-
- llvm::StringRef name = GetTypeName();
- return k_libcxx_std_unique_ptr_regex.match(name) ||
- k_libcxx_std_shared_ptr_regex.match(name) ||
- k_libcxx_std_weak_ptr_regex.match(name) ||
- k_libstdcxx_std_unique_ptr_regex.match(name) ||
- k_libstdcxx_std_shared_ptr_regex.match(name) ||
- k_libstdcxx_std_weak_ptr_regex.match(name);
-}
-
bool CompilerType::IsInteger() const {
bool is_signed = false; // May be reset by the call below.
return IsIntegerType(is_signed);
@@ -540,14 +513,6 @@ CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) {
return empty_type;
}
-CompilerType CompilerType::GetSmartPtrPointeeType() {
- if (!IsSmartPtrType())
- // TODO: Should consider issuing a warning here.
- return GetPointeeType();
-
- return GetTemplateArgumentType(0);
-}
-
// Type Completion
bool CompilerType::GetCompleteType() const {
More information about the lldb-commits
mailing list