Skip to content

Commit 95e8fab

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

File tree

5 files changed

+197
-6
lines changed

5 files changed

+197
-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: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// clang-format off
2+
// REQUIRES: lld, x86
3+
4+
// Test namespace lookup.
5+
// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -GS- -c /Fo%t.obj -- %s
6+
// RUN: lld-link -debug:full -nodefaultlib -entry:main %t.obj -out:%t.exe -pdb:%t.pdb
7+
// RUN: %lldb -f %t.exe -s \
8+
// RUN: %p/Inputs/namespace-access.lldbinit 2>&1 | FileCheck %s
9+
10+
struct S {
11+
char a[1];
12+
};
13+
14+
namespace Outer {
15+
16+
struct S {
17+
char a[2];
18+
};
19+
20+
namespace Inner1 {
21+
struct S {
22+
char a[3];
23+
};
24+
25+
namespace Inner2 {
26+
struct S {
27+
char a[4];
28+
};
29+
} // namespace Inner2
30+
} // namespace Inner1
31+
32+
namespace Inner2 {
33+
struct S {
34+
char a[5];
35+
};
36+
} // namespace Inner2
37+
38+
namespace {
39+
struct A {
40+
char a[6];
41+
};
42+
} // namespace
43+
44+
} // namespace Outer
45+
46+
namespace {
47+
struct A {
48+
char a[7];
49+
};
50+
} // namespace
51+
52+
int main(int argc, char **argv) {
53+
S s;
54+
Outer::S os;
55+
Outer::Inner1::S oi1s;
56+
Outer::Inner1::Inner2::S oi1i2s;
57+
Outer::Inner2::S oi2s;
58+
A a1;
59+
Outer::A a2;
60+
return sizeof(s) + sizeof(os) + sizeof(oi1s) + sizeof(oi1i2s) + sizeof(oi2s) + sizeof(a1) + sizeof(a2);
61+
}
62+
63+
64+
65+
// CHECK: (lldb) type lookup S
66+
// CHECK: struct S {
67+
// CHECK: struct S {
68+
// CHECK: struct S {
69+
// CHECK: struct S {
70+
// CHECK: struct S {
71+
// CHECK: }
72+
// CHECK-NEXT: (lldb) type lookup ::S
73+
// CHECK-NEXT: struct S {
74+
// CHECK-NEXT: char a[1];
75+
// CHECK-NEXT: }
76+
// CHECK-NEXT: (lldb) type lookup Outer::S
77+
// CHECK-NEXT: struct S {
78+
// CHECK-NEXT: char a[2];
79+
// CHECK-NEXT: }
80+
// CHECK-NEXT: (lldb) type lookup Outer::Inner1::S
81+
// CHECK-NEXT: struct S {
82+
// CHECK-NEXT: char a[3];
83+
// CHECK-NEXT: }
84+
// CHECK-NEXT: (lldb) type lookup Inner1::S
85+
// CHECK-NEXT: struct S {
86+
// CHECK-NEXT: char a[3];
87+
// CHECK-NEXT: }
88+
// CHECK-NEXT: (lldb) type lookup Outer::Inner1::Inner2::S
89+
// CHECK-NEXT: struct S {
90+
// CHECK-NEXT: char a[4];
91+
// CHECK-NEXT: }
92+
// CHECK-NEXT: (lldb) type lookup Inner2::S
93+
// CHECK-NEXT: struct S {
94+
// CHECK: struct S {
95+
// CHECK: }
96+
// CHECK-NEXT: (lldb) type lookup Outer::Inner2::S
97+
// CHECK-NEXT: struct S {
98+
// CHECK-NEXT: char a[5];
99+
// CHECK-NEXT: }
100+
// CHECK-NEXT: (lldb) type lookup Outer::A
101+
// CHECK-NEXT: struct A {
102+
// CHECK-NEXT: char a[6];
103+
// CHECK-NEXT: }
104+
// CHECK-NEXT: (lldb) type lookup A
105+
// CHECK-NEXT: struct A {
106+
// CHECK: struct A {
107+
// CHECK: }
108+
// CHECK-NEXT: (lldb) type lookup ::A
109+
// CHECK-NEXT: struct A {
110+
// CHECK-NEXT: char a[7];
111+
// CHECK-NEXT: }
112+
// CHECK-NEXT: (lldb) expr sizeof(S)
113+
// CHECK-NEXT: (__size_t) $0 = 1
114+
// CHECK-NEXT: (lldb) expr sizeof(A)
115+
// CHECK-NEXT: (__size_t) $1 = 7

0 commit comments

Comments
 (0)