Skip to content

Commit 93229c7

Browse files
authored
[lldb] Add SBType::FindDirectNestedType() function (#68705)
This patch adds a `SBType::FindDirectNestedType(name)` function which performs a non-recursive search in given class for a type with specified name. The intent is to perform a fast search in debug info, so that it can be used in formatters, and let them remain responsive. This is driven by my work on formatters for Clang and LLVM types. In particular, by [`PointerIntPairInfo::MaskAndShiftConstants`](https://github.com/llvm/llvm-project/blob/cde9f9df79805a0850310870d6dcc64004292727/llvm/include/llvm/ADT/PointerIntPair.h#L174C16-L174C16), which is required to extract pointer and integer from `PointerIntPair`. Related Discourse thread: https://discourse.llvm.org/t/traversing-member-types-of-a-type/72452
1 parent 02f67c0 commit 93229c7

File tree

12 files changed

+96
-0
lines changed

12 files changed

+96
-0
lines changed

lldb/bindings/interface/SBTypeDocstrings.i

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,14 @@ SBType supports the eq/ne operator. For example,::
720720
"
721721
) lldb::SBType::GetTypeFlags;
722722

723+
%feature("docstring",
724+
"Searches for a directly nested type that has the provided name.
725+
726+
Returns the type if it was found.
727+
Returns invalid type if nothing was found.
728+
"
729+
) lldb::SBType::FindDirectNestedType;
730+
723731
%feature("docstring",
724732
"Represents a list of :py:class:`SBType` s.
725733

lldb/include/lldb/API/SBType.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ class SBType {
215215
bool GetDescription(lldb::SBStream &description,
216216
lldb::DescriptionLevel description_level);
217217

218+
lldb::SBType FindDirectNestedType(const char *name);
219+
218220
lldb::SBType &operator=(const lldb::SBType &rhs);
219221

220222
bool operator==(lldb::SBType &rhs);

lldb/include/lldb/Symbol/Type.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ class TypeImpl {
304304
bool GetDescription(lldb_private::Stream &strm,
305305
lldb::DescriptionLevel description_level);
306306

307+
CompilerType FindDirectNestedType(llvm::StringRef name);
308+
307309
private:
308310
bool CheckModule(lldb::ModuleSP &module_sp) const;
309311
bool CheckExeModule(lldb::ModuleSP &module_sp) const;

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ class TypeSystem : public PluginInterface,
142142

143143
virtual lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) = 0;
144144

145+
/// Returns the direct parent context of specified type
146+
virtual CompilerDeclContext
147+
GetCompilerDeclContextForType(const CompilerType &type);
148+
145149
// Tests
146150
#ifndef NDEBUG
147151
/// Verify the integrity of the type to catch CompilerTypes that mix

lldb/source/API/SBType.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,14 @@ lldb::TemplateArgumentKind SBType::GetTemplateArgumentKind(uint32_t idx) {
586586
return eTemplateArgumentKindNull;
587587
}
588588

589+
SBType SBType::FindDirectNestedType(const char *name) {
590+
LLDB_INSTRUMENT_VA(this, name);
591+
592+
if (!IsValid())
593+
return SBType();
594+
return SBType(m_opaque_sp->FindDirectNestedType(name));
595+
}
596+
589597
SBTypeList::SBTypeList() : m_opaque_up(new TypeListImpl()) {
590598
LLDB_INSTRUMENT_VA(this);
591599
}

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,13 @@ TypeSystemClang::GetDeclContextForType(const CompilerType &type) {
26372637
return GetDeclContextForType(ClangUtil::GetQualType(type));
26382638
}
26392639

2640+
CompilerDeclContext
2641+
TypeSystemClang::GetCompilerDeclContextForType(const CompilerType &type) {
2642+
if (auto *decl_context = GetDeclContextForType(type))
2643+
return CreateDeclContext(decl_context);
2644+
return CompilerDeclContext();
2645+
}
2646+
26402647
/// Aggressively desugar the provided type, skipping past various kinds of
26412648
/// syntactic sugar and other constructs one typically wants to ignore.
26422649
/// The \p mask argument allows one to skip certain kinds of simplifications,

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ class TypeSystemClang : public TypeSystem {
219219

220220
static clang::DeclContext *GetDeclContextForType(const CompilerType &type);
221221

222+
CompilerDeclContext
223+
GetCompilerDeclContextForType(const CompilerType &type) override;
224+
222225
uint32_t GetPointerByteSize() override;
223226

224227
clang::TranslationUnitDecl *GetTranslationUnitDecl() {

lldb/source/Symbol/Type.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,23 @@ bool TypeImpl::GetDescription(lldb_private::Stream &strm,
10401040
return true;
10411041
}
10421042

1043+
CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) {
1044+
if (name.empty())
1045+
return CompilerType();
1046+
auto type_system = GetTypeSystem(/*prefer_dynamic*/ false);
1047+
auto *symbol_file = type_system->GetSymbolFile();
1048+
auto decl_context = type_system->GetCompilerDeclContextForType(m_static_type);
1049+
if (!decl_context.IsValid())
1050+
return CompilerType();
1051+
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
1052+
TypeMap search_result;
1053+
symbol_file->FindTypes(ConstString(name), decl_context, /*max_matches*/ 1,
1054+
searched_symbol_files, search_result);
1055+
if (search_result.Empty())
1056+
return CompilerType();
1057+
return search_result.GetTypeAtIndex(0)->GetFullCompilerType();
1058+
}
1059+
10431060
bool TypeMemberFunctionImpl::IsValid() {
10441061
return m_type.IsValid() && m_kind != lldb::eMemberFunctionKindUnknown;
10451062
}

lldb/source/Symbol/TypeSystem.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,11 @@ std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {
186186
return std::nullopt;
187187
}
188188

189+
CompilerDeclContext
190+
TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {
191+
return CompilerDeclContext();
192+
}
193+
189194
#pragma mark TypeSystemMap
190195

191196
TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}

lldb/test/API/python_api/type/TestTypeList.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,37 @@ def test(self):
119119

120120
self.assertEqual(task_type, task_head_pointee_type)
121121

122+
# Check whether we can find a directly nested type by name
123+
name_type = task_type.FindDirectNestedType("name")
124+
self.assertTrue(name_type)
125+
self.DebugSBType(name_type)
126+
127+
enum_type = task_type.FindDirectNestedType("E")
128+
self.assertTrue(enum_type)
129+
self.DebugSBType(enum_type)
130+
131+
union_type = task_type.FindDirectNestedType("U")
132+
self.assertTrue(union_type)
133+
self.DebugSBType(union_type)
134+
135+
# Check that we don't find indirectly nested types
136+
self.assertTrue(enum_type.size == 1)
137+
138+
invalid_type = task_type.FindDirectNestedType("E2")
139+
self.assertFalse(invalid_type)
140+
141+
# Check that FindDirectNestedType handles types without DeclContext
142+
# and other errorneous inputs
143+
task_ptr_type = task_type.GetPointerType()
144+
invalid_type = task_ptr_type.FindDirectNestedType("name")
145+
self.assertFalse(invalid_type)
146+
147+
invalid_type = task_type.FindDirectNestedType("")
148+
self.assertFalse(invalid_type)
149+
150+
invalid_type = task_type.FindDirectNestedType(None)
151+
self.assertFalse(invalid_type)
152+
122153
# We'll now get the child member 'id' from 'task_head'.
123154
id = task_head.GetChildMemberWithName("id")
124155
self.DebugSBValue(id)

lldb/test/API/python_api/type/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ class Task {
2121
} my_type_is_nameless;
2222
struct name {
2323
int x;
24+
enum E : int {} e;
25+
enum E2 {} e2;
2426
} my_type_is_named;
27+
enum E : unsigned char {} e;
28+
union U {
29+
} u;
2530
Task(int i, Task *n):
2631
id(i),
2732
next(n),

llvm/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ Changes to LLDB
191191

192192
* Methods in SBHostOS related to threads have had their implementations
193193
removed. These methods will return a value indicating failure.
194+
* ``SBType::FindDirectNestedType`` function is added. It's useful
195+
for formatters to quickly find directly nested type when it's known
196+
where to search for it, avoiding more expensive global search via
197+
``SBTarget::FindFirstType``.
194198

195199
Changes to Sanitizers
196200
---------------------

0 commit comments

Comments
 (0)