Skip to content

Commit fa3c96b

Browse files
committed
[LLDB][NativePDB] Allow type lookup in namespaces
1 parent 5c7c855 commit fa3c96b

File tree

5 files changed

+196
-6
lines changed

5 files changed

+196
-6
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,6 +1630,53 @@ size_t SymbolFileNativePDB::ParseSymbolArrayInScope(
16301630
return count;
16311631
}
16321632

1633+
void SymbolFileNativePDB::CacheTypeNames() {
1634+
if (!m_type_base_names.IsEmpty())
1635+
return;
1636+
1637+
LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
1638+
for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
1639+
CVType cvt = types.getType(*ti);
1640+
llvm::StringRef name;
1641+
// We are only interested in records, unions, and enums.
1642+
// We aren't interested in forward references as we'll visit the actual
1643+
// type later anyway.
1644+
switch (cvt.kind()) {
1645+
case LF_STRUCTURE:
1646+
case LF_CLASS: {
1647+
ClassRecord cr;
1648+
llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
1649+
if (cr.isForwardRef())
1650+
continue;
1651+
name = cr.Name;
1652+
} break;
1653+
case LF_UNION: {
1654+
UnionRecord ur;
1655+
llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
1656+
if (ur.isForwardRef())
1657+
continue;
1658+
name = ur.Name;
1659+
} break;
1660+
case LF_ENUM: {
1661+
EnumRecord er;
1662+
llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
1663+
if (er.isForwardRef())
1664+
continue;
1665+
name = er.Name;
1666+
} break;
1667+
default:
1668+
continue;
1669+
}
1670+
if (name.empty())
1671+
continue;
1672+
1673+
auto base_name = MSVCUndecoratedNameParser::DropScope(name);
1674+
m_type_base_names.Append(ConstString(base_name), ti->getIndex());
1675+
}
1676+
1677+
m_type_base_names.Sort();
1678+
}
1679+
16331680
void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) {
16341681
auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
16351682
if (!ts_or_err)
@@ -1720,11 +1767,14 @@ void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
17201767

17211768
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
17221769

1723-
std::vector<TypeIndex> matches =
1724-
m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef());
1770+
// We can't query for the basename or full name because the type might reside
1771+
// in an anonymous namespace. Cache the basenames first.
1772+
CacheTypeNames();
1773+
std::vector<uint32_t> matches;
1774+
m_type_base_names.GetValues(query.GetTypeBasename(), matches);
17251775

1726-
for (TypeIndex type_idx : matches) {
1727-
TypeSP type_sp = GetOrCreateType(type_idx);
1776+
for (uint32_t match_idx : matches) {
1777+
TypeSP type_sp = GetOrCreateType(TypeIndex(match_idx));
17281778
if (!type_sp)
17291779
continue;
17301780

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ class SymbolFileNativePDB : public SymbolFileCommon {
258258

259259
void ParseInlineSite(PdbCompilandSymId inline_site_id, Address func_addr);
260260

261+
void CacheTypeNames();
262+
261263
llvm::BumpPtrAllocator m_allocator;
262264

263265
lldb::addr_t m_obj_load_address = 0;
@@ -278,6 +280,8 @@ class SymbolFileNativePDB : public SymbolFileCommon {
278280
llvm::DenseMap<lldb::user_id_t, std::shared_ptr<InlineSite>> m_inline_sites;
279281
llvm::DenseMap<llvm::codeview::TypeIndex, llvm::codeview::TypeIndex>
280282
m_parent_types;
283+
284+
lldb_private::UniqueCStringMap<uint32_t> m_type_base_names;
281285
};
282286

283287
} // namespace npdb

lldb/source/Symbol/Type.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ bool TypeQuery::ContextMatches(
134134
if (ctx == ctx_end)
135135
return false; // Pattern too long.
136136

137-
if (ctx->kind == CompilerContextKind::Namespace && ctx->name.IsEmpty()) {
137+
if ((ctx->kind & CompilerContextKind::Namespace) ==
138+
CompilerContextKind::Namespace &&
139+
ctx->name.IsEmpty()) {
138140
// We're matching an anonymous namespace. These are optional, so we check
139141
// if the pattern expects an anonymous namespace.
140142
if (pat->name.IsEmpty() && (pat->kind & CompilerContextKind::Namespace) ==
@@ -164,7 +166,9 @@ bool TypeQuery::ContextMatches(
164166
auto should_skip = [this](const CompilerContext &ctx) {
165167
if (ctx.kind == CompilerContextKind::Module)
166168
return GetIgnoreModules();
167-
if (ctx.kind == CompilerContextKind::Namespace && ctx.name.IsEmpty())
169+
if ((ctx.kind & CompilerContextKind::Namespace) ==
170+
CompilerContextKind::Namespace &&
171+
ctx.name.IsEmpty())
168172
return !GetStrictNamespaces();
169173
return false;
170174
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
b main
2+
r
3+
4+
type lookup S
5+
type lookup ::S
6+
type lookup Outer::S
7+
type lookup Outer::Inner1::S
8+
type lookup Inner1::S
9+
type lookup Outer::Inner1::Inner2::S
10+
type lookup Inner2::S
11+
type lookup Outer::Inner2::S
12+
type lookup Outer::A
13+
type lookup A
14+
type lookup ::A
15+
expr sizeof(S)
16+
expr sizeof(A)
17+
18+
quit
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// clang-format off
2+
// REQUIRES: target-windows
3+
4+
// Test namespace lookup.
5+
// RUN: %build --nodefaultlib -o %t.exe -- %s
6+
// RUN: %lldb -f %t.exe -s \
7+
// RUN: %p/Inputs/namespace-access.lldbinit 2>&1 | FileCheck %s
8+
9+
struct S {
10+
char a[1];
11+
};
12+
13+
namespace Outer {
14+
15+
struct S {
16+
char a[2];
17+
};
18+
19+
namespace Inner1 {
20+
struct S {
21+
char a[3];
22+
};
23+
24+
namespace Inner2 {
25+
struct S {
26+
char a[4];
27+
};
28+
} // namespace Inner2
29+
} // namespace Inner1
30+
31+
namespace Inner2 {
32+
struct S {
33+
char a[5];
34+
};
35+
} // namespace Inner2
36+
37+
namespace {
38+
struct A {
39+
char a[6];
40+
};
41+
} // namespace
42+
43+
} // namespace Outer
44+
45+
namespace {
46+
struct A {
47+
char a[7];
48+
};
49+
} // namespace
50+
51+
int main(int argc, char **argv) {
52+
S s;
53+
Outer::S os;
54+
Outer::Inner1::S oi1s;
55+
Outer::Inner1::Inner2::S oi1i2s;
56+
Outer::Inner2::S oi2s;
57+
A a1;
58+
Outer::A a2;
59+
return sizeof(s) + sizeof(os) + sizeof(oi1s) + sizeof(oi1i2s) + sizeof(oi2s) + sizeof(a1) + sizeof(a2);
60+
}
61+
62+
63+
64+
// CHECK: (lldb) type lookup S
65+
// CHECK: struct S {
66+
// CHECK: struct S {
67+
// CHECK: struct S {
68+
// CHECK: struct S {
69+
// CHECK: struct S {
70+
// CHECK: }
71+
// CHECK-NEXT: (lldb) type lookup ::S
72+
// CHECK-NEXT: struct S {
73+
// CHECK-NEXT: char a[1];
74+
// CHECK-NEXT: }
75+
// CHECK-NEXT: (lldb) type lookup Outer::S
76+
// CHECK-NEXT: struct S {
77+
// CHECK-NEXT: char a[2];
78+
// CHECK-NEXT: }
79+
// CHECK-NEXT: (lldb) type lookup Outer::Inner1::S
80+
// CHECK-NEXT: struct S {
81+
// CHECK-NEXT: char a[3];
82+
// CHECK-NEXT: }
83+
// CHECK-NEXT: (lldb) type lookup Inner1::S
84+
// CHECK-NEXT: struct S {
85+
// CHECK-NEXT: char a[3];
86+
// CHECK-NEXT: }
87+
// CHECK-NEXT: (lldb) type lookup Outer::Inner1::Inner2::S
88+
// CHECK-NEXT: struct S {
89+
// CHECK-NEXT: char a[4];
90+
// CHECK-NEXT: }
91+
// CHECK-NEXT: (lldb) type lookup Inner2::S
92+
// CHECK-NEXT: struct S {
93+
// CHECK: struct S {
94+
// CHECK: }
95+
// CHECK-NEXT: (lldb) type lookup Outer::Inner2::S
96+
// CHECK-NEXT: struct S {
97+
// CHECK-NEXT: char a[5];
98+
// CHECK-NEXT: }
99+
// CHECK-NEXT: (lldb) type lookup Outer::A
100+
// CHECK-NEXT: struct A {
101+
// CHECK-NEXT: char a[6];
102+
// CHECK-NEXT: }
103+
// CHECK-NEXT: (lldb) type lookup A
104+
// CHECK-NEXT: struct A {
105+
// CHECK: struct A {
106+
// CHECK: }
107+
// CHECK-NEXT: (lldb) type lookup ::A
108+
// CHECK-NEXT: struct A {
109+
// CHECK-NEXT: char a[7];
110+
// CHECK-NEXT: }
111+
// CHECK-NEXT: (lldb) expr sizeof(S)
112+
// CHECK-NEXT: (__size_t) $0 = 1
113+
// CHECK-NEXT: (lldb) expr sizeof(A)
114+
// CHECK-NEXT: (__size_t) $1 = 7

0 commit comments

Comments
 (0)