1 //===-- PythonDataObjectsTests.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "gtest/gtest.h"
11 
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/Config/config.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 
19 #include "lldb/Core/Address.h"
20 #include "lldb/Core/ArchSpec.h"
21 #include "lldb/Core/Module.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Host/FileSpec.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Symbol/ClangASTContext.h"
26 #include "lldb/Symbol/CompileUnit.h"
27 #include "lldb/Symbol/LineTable.h"
28 #include "lldb/Symbol/SymbolVendor.h"
29 
30 #include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
31 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
32 #include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
33 
34 #if defined(_MSC_VER)
35 #include "lldb/Host/windows/windows.h"
36 #include <objbase.h>
37 #endif
38 
39 #include <algorithm>
40 
41 extern const char *TestMainArgv0;
42 
43 using namespace lldb_private;
44 
45 class SymbolFilePDBTests : public testing::Test
46 {
47 public:
48     void
49     SetUp() override
50     {
51 // Initialize and TearDown the plugin every time, so we get a brand new
52 // AST every time so that modifications to the AST from each test don't
53 // leak into the next test.
54 #if defined(_MSC_VER)
55         ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
56 #endif
57 
58         HostInfo::Initialize();
59         ObjectFilePECOFF::Initialize();
60         SymbolFileDWARF::Initialize();
61         ClangASTContext::Initialize();
62         SymbolFilePDB::Initialize();
63 
64         llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
65         llvm::SmallString<128> inputs_folder = exe_folder;
66         llvm::sys::path::append(inputs_folder, "Inputs");
67 
68         m_pdb_test_exe = inputs_folder;
69         m_dwarf_test_exe = inputs_folder;
70         m_types_test_exe = inputs_folder;
71         llvm::sys::path::append(m_pdb_test_exe, "test-pdb.exe");
72         llvm::sys::path::append(m_dwarf_test_exe, "test-dwarf.exe");
73         llvm::sys::path::append(m_types_test_exe, "test-pdb-types.exe");
74     }
75 
76     void
77     TearDown() override
78     {
79         SymbolFilePDB::Terminate();
80         ClangASTContext::Initialize();
81         SymbolFileDWARF::Terminate();
82         ObjectFilePECOFF::Terminate();
83         HostInfo::Terminate();
84 
85 #if defined(_MSC_VER)
86         ::CoUninitialize();
87 #endif
88     }
89 
90 protected:
91     llvm::SmallString<128> m_pdb_test_exe;
92     llvm::SmallString<128> m_dwarf_test_exe;
93     llvm::SmallString<128> m_types_test_exe;
94 
95     bool
96     FileSpecMatchesAsBaseOrFull(const FileSpec &left, const FileSpec &right) const
97     {
98         // If the filenames don't match, the paths can't be equal
99         if (!left.FileEquals(right))
100             return false;
101         // If BOTH have a directory, also compare the directories.
102         if (left.GetDirectory() && right.GetDirectory())
103             return left.DirectoryEquals(right);
104 
105         // If one has a directory but not the other, they match.
106         return true;
107     }
108 
109     void
110     VerifyLineEntry(lldb::ModuleSP module, const SymbolContext &sc, const FileSpec &spec, LineTable &lt, uint32_t line,
111                     lldb::addr_t addr)
112     {
113         LineEntry entry;
114         Address address;
115         EXPECT_TRUE(module->ResolveFileAddress(addr, address));
116 
117         EXPECT_TRUE(lt.FindLineEntryByAddress(address, entry));
118         EXPECT_EQ(line, entry.line);
119         EXPECT_EQ(address, entry.range.GetBaseAddress());
120 
121         EXPECT_TRUE(FileSpecMatchesAsBaseOrFull(spec, entry.file));
122     }
123 
124     bool
125     ContainsCompileUnit(const SymbolContextList &sc_list, const FileSpec &spec) const
126     {
127         for (size_t i = 0; i < sc_list.GetSize(); ++i)
128         {
129             const SymbolContext &sc = sc_list[i];
130             if (FileSpecMatchesAsBaseOrFull(*sc.comp_unit, spec))
131                 return true;
132         }
133         return false;
134     }
135 
136     int
137     GetGlobalConstantInteger(const llvm::IPDBSession &session, llvm::StringRef var) const
138     {
139         auto global = session.getGlobalScope();
140         auto results = global->findChildren(llvm::PDB_SymType::Data, var, llvm::PDB_NameSearchFlags::NS_Default);
141         uint32_t count = results->getChildCount();
142         if (count == 0)
143             return -1;
144 
145         auto item = results->getChildAtIndex(0);
146         auto symbol = llvm::dyn_cast<llvm::PDBSymbolData>(item.get());
147         if (!symbol)
148             return -1;
149         llvm::Variant value = symbol->getValue();
150         switch (value.Type)
151         {
152             case llvm::PDB_VariantType::Int16:
153                 return value.Value.Int16;
154             case llvm::PDB_VariantType::Int32:
155                 return value.Value.Int32;
156             case llvm::PDB_VariantType::UInt16:
157                 return value.Value.UInt16;
158             case llvm::PDB_VariantType::UInt32:
159                 return value.Value.UInt32;
160             default:
161                 return 0;
162         }
163     }
164 };
165 
166 #if defined(HAVE_DIA_SDK)
167 #define REQUIRES_DIA_SDK(TestName) TestName
168 #else
169 #define REQUIRES_DIA_SDK(TestName) DISABLED_##TestName
170 #endif
171 
172 TEST_F(SymbolFilePDBTests, TestAbilitiesForDWARF)
173 {
174     // Test that when we have Dwarf debug info, SymbolFileDWARF is used.
175     FileSpec fspec(m_dwarf_test_exe.c_str(), false);
176     ArchSpec aspec("i686-pc-windows");
177     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
178 
179     SymbolVendor *plugin = module->GetSymbolVendor();
180     EXPECT_NE(nullptr, plugin);
181     SymbolFile *symfile = plugin->GetSymbolFile();
182     EXPECT_NE(nullptr, symfile);
183     EXPECT_EQ(symfile->GetPluginName(), SymbolFileDWARF::GetPluginNameStatic());
184 
185     uint32_t expected_abilities = SymbolFile::kAllAbilities;
186     EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
187 }
188 
189 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestAbilitiesForPDB))
190 {
191     // Test that when we have PDB debug info, SymbolFilePDB is used.
192     FileSpec fspec(m_pdb_test_exe.c_str(), false);
193     ArchSpec aspec("i686-pc-windows");
194     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
195 
196     SymbolVendor *plugin = module->GetSymbolVendor();
197     EXPECT_NE(nullptr, plugin);
198     SymbolFile *symfile = plugin->GetSymbolFile();
199     EXPECT_NE(nullptr, symfile);
200     EXPECT_EQ(symfile->GetPluginName(), SymbolFilePDB::GetPluginNameStatic());
201 
202     uint32_t expected_abilities = SymbolFile::CompileUnits | SymbolFile::LineTables;
203     EXPECT_EQ(expected_abilities, symfile->CalculateAbilities());
204 }
205 
206 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextBasename))
207 {
208     // Test that attempting to call ResolveSymbolContext with only a basename finds all full paths
209     // with the same basename
210     FileSpec fspec(m_pdb_test_exe.c_str(), false);
211     ArchSpec aspec("i686-pc-windows");
212     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
213 
214     SymbolVendor *plugin = module->GetSymbolVendor();
215     EXPECT_NE(nullptr, plugin);
216     SymbolFile *symfile = plugin->GetSymbolFile();
217 
218     FileSpec header_spec("test-pdb.cpp", false);
219     SymbolContextList sc_list;
220     uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
221     EXPECT_EQ(1u, result_count);
222     EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
223 }
224 
225 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestResolveSymbolContextFullPath))
226 {
227     // Test that attempting to call ResolveSymbolContext with a full path only finds the one source
228     // file that matches the full path.
229     FileSpec fspec(m_pdb_test_exe.c_str(), false);
230     ArchSpec aspec("i686-pc-windows");
231     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
232 
233     SymbolVendor *plugin = module->GetSymbolVendor();
234     EXPECT_NE(nullptr, plugin);
235     SymbolFile *symfile = plugin->GetSymbolFile();
236 
237     FileSpec header_spec(R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec", false);
238     SymbolContextList sc_list;
239     uint32_t result_count = symfile->ResolveSymbolContext(header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
240     EXPECT_GE(1u, result_count);
241     EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
242 }
243 
244 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithInlines))
245 {
246     // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself
247     // compiled, but only contributes to the combined code of other source files), a SymbolContext is returned
248     // for each compiland which has line contributions from the requested header.
249     FileSpec fspec(m_pdb_test_exe.c_str(), false);
250     ArchSpec aspec("i686-pc-windows");
251     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
252 
253     SymbolVendor *plugin = module->GetSymbolVendor();
254     EXPECT_NE(nullptr, plugin);
255     SymbolFile *symfile = plugin->GetSymbolFile();
256 
257     FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)};
258     FileSpec main_cpp_spec("test-pdb.cpp", false);
259     FileSpec alt_cpp_spec("test-pdb-alt.cpp", false);
260     for (const auto &hspec : header_specs)
261     {
262         SymbolContextList sc_list;
263         uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, true, lldb::eSymbolContextCompUnit, sc_list);
264         EXPECT_EQ(2u, result_count);
265         EXPECT_TRUE(ContainsCompileUnit(sc_list, main_cpp_spec));
266         EXPECT_TRUE(ContainsCompileUnit(sc_list, alt_cpp_spec));
267     }
268 }
269 
270 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLookupOfHeaderFileWithNoInlines))
271 {
272     // Test that when looking up a header file via ResolveSymbolContext (i.e. a file that was not by itself
273     // compiled, but only contributes to the combined code of other source files), that if check_inlines
274     // is false, no SymbolContexts are returned.
275     FileSpec fspec(m_pdb_test_exe.c_str(), false);
276     ArchSpec aspec("i686-pc-windows");
277     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
278 
279     SymbolVendor *plugin = module->GetSymbolVendor();
280     EXPECT_NE(nullptr, plugin);
281     SymbolFile *symfile = plugin->GetSymbolFile();
282 
283     FileSpec header_specs[] = {FileSpec("test-pdb.h", false), FileSpec("test-pdb-nested.h", false)};
284     for (const auto &hspec : header_specs)
285     {
286         SymbolContextList sc_list;
287         uint32_t result_count = symfile->ResolveSymbolContext(hspec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
288         EXPECT_EQ(0u, result_count);
289     }
290 }
291 
292 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchAll))
293 {
294     // Test that when calling ResolveSymbolContext with a line number of 0, all line entries from
295     // the specified files are returned.
296     FileSpec fspec(m_pdb_test_exe.c_str(), false);
297     ArchSpec aspec("i686-pc-windows");
298     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
299 
300     SymbolVendor *plugin = module->GetSymbolVendor();
301     SymbolFile *symfile = plugin->GetSymbolFile();
302 
303     FileSpec source_file("test-pdb.cpp", false);
304     FileSpec header1("test-pdb.h", false);
305     FileSpec header2("test-pdb-nested.h", false);
306     uint32_t cus = symfile->GetNumCompileUnits();
307     EXPECT_EQ(2u, cus);
308 
309     SymbolContextList sc_list;
310     uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
311 
312     uint32_t count = symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);
313     EXPECT_EQ(1u, count);
314     SymbolContext sc;
315     EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
316 
317     LineTable *lt = sc.comp_unit->GetLineTable();
318     EXPECT_NE(nullptr, lt);
319     count = lt->GetSize();
320     // We expect one extra entry for termination (per function)
321     EXPECT_EQ(16u, count);
322 
323     VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
324     VerifyLineEntry(module, sc, source_file, *lt, 8, 0x401043);
325     VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
326 
327     VerifyLineEntry(module, sc, source_file, *lt, 13, 0x401050);
328     VerifyLineEntry(module, sc, source_file, *lt, 14, 0x401054);
329     VerifyLineEntry(module, sc, source_file, *lt, 15, 0x401070);
330 
331     VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
332     VerifyLineEntry(module, sc, header1, *lt, 10, 0x401093);
333     VerifyLineEntry(module, sc, header1, *lt, 11, 0x4010a2);
334 
335     VerifyLineEntry(module, sc, header2, *lt, 5, 0x401080);
336     VerifyLineEntry(module, sc, header2, *lt, 6, 0x401083);
337     VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
338 }
339 
340 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestLineTablesMatchSpecific))
341 {
342     // Test that when calling ResolveSymbolContext with a specific line number, only line entries
343     // which match the requested line are returned.
344     FileSpec fspec(m_pdb_test_exe.c_str(), false);
345     ArchSpec aspec("i686-pc-windows");
346     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
347 
348     SymbolVendor *plugin = module->GetSymbolVendor();
349     SymbolFile *symfile = plugin->GetSymbolFile();
350 
351     FileSpec source_file("test-pdb.cpp", false);
352     FileSpec header1("test-pdb.h", false);
353     FileSpec header2("test-pdb-nested.h", false);
354     uint32_t cus = symfile->GetNumCompileUnits();
355     EXPECT_EQ(2u, cus);
356 
357     SymbolContextList sc_list;
358     uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
359 
360     // First test with line 7, and verify that only line 7 entries are added.
361     uint32_t count = symfile->ResolveSymbolContext(source_file, 7, true, scope, sc_list);
362     EXPECT_EQ(1u, count);
363     SymbolContext sc;
364     EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
365 
366     LineTable *lt = sc.comp_unit->GetLineTable();
367     EXPECT_NE(nullptr, lt);
368     count = lt->GetSize();
369     // We expect one extra entry for termination
370     EXPECT_EQ(3u, count);
371 
372     VerifyLineEntry(module, sc, source_file, *lt, 7, 0x401040);
373     VerifyLineEntry(module, sc, header2, *lt, 7, 0x401089);
374 
375     sc_list.Clear();
376     // Then test with line 9, and verify that only line 9 entries are added.
377     count = symfile->ResolveSymbolContext(source_file, 9, true, scope, sc_list);
378     EXPECT_EQ(1u, count);
379     EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
380 
381     lt = sc.comp_unit->GetLineTable();
382     EXPECT_NE(nullptr, lt);
383     count = lt->GetSize();
384     // We expect one extra entry for termination
385     EXPECT_EQ(3u, count);
386 
387     VerifyLineEntry(module, sc, source_file, *lt, 9, 0x401045);
388     VerifyLineEntry(module, sc, header1, *lt, 9, 0x401090);
389 }
390 
391 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestSimpleClassTypes))
392 {
393     FileSpec fspec(m_types_test_exe.c_str(), false);
394     ArchSpec aspec("i686-pc-windows");
395     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
396 
397     SymbolVendor *plugin = module->GetSymbolVendor();
398     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
399     const llvm::IPDBSession &session = symfile->GetPDBSession();
400     SymbolContext sc;
401     llvm::DenseSet<SymbolFile *> searched_files;
402     TypeMap results;
403     EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0, searched_files, results));
404     EXPECT_EQ(1, results.GetSize());
405     lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
406     EXPECT_EQ(ConstString("Class"), udt_type->GetName());
407     CompilerType compiler_type = udt_type->GetForwardCompilerType();
408     EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
409     EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_Class"), udt_type->GetByteSize());
410 }
411 
412 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNestedClassTypes))
413 {
414     FileSpec fspec(m_types_test_exe.c_str(), false);
415     ArchSpec aspec("i686-pc-windows");
416     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
417 
418     SymbolVendor *plugin = module->GetSymbolVendor();
419     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
420     const llvm::IPDBSession &session = symfile->GetPDBSession();
421     SymbolContext sc;
422     llvm::DenseSet<SymbolFile *> searched_files;
423     TypeMap results;
424     EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("Class::NestedClass"), nullptr, false, 0, searched_files, results));
425     EXPECT_EQ(1, results.GetSize());
426     lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
427     EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
428     CompilerType compiler_type = udt_type->GetForwardCompilerType();
429     EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
430     EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"), udt_type->GetByteSize());
431 }
432 
433 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestClassInNamespace))
434 {
435     FileSpec fspec(m_types_test_exe.c_str(), false);
436     ArchSpec aspec("i686-pc-windows");
437     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
438 
439     SymbolVendor *plugin = module->GetSymbolVendor();
440     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
441     const llvm::IPDBSession &session = symfile->GetPDBSession();
442     SymbolContext sc;
443     llvm::DenseSet<SymbolFile *> searched_files;
444     TypeMap results;
445     EXPECT_EQ(1, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr, false, 0, searched_files, results));
446     EXPECT_EQ(1, results.GetSize());
447     lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
448     EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
449     CompilerType compiler_type = udt_type->GetForwardCompilerType();
450     EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
451     EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"), udt_type->GetByteSize());
452 }
453 
454 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestEnumTypes))
455 {
456     FileSpec fspec(m_types_test_exe.c_str(), false);
457     ArchSpec aspec("i686-pc-windows");
458     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
459 
460     SymbolVendor *plugin = module->GetSymbolVendor();
461     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
462     const llvm::IPDBSession &session = symfile->GetPDBSession();
463     SymbolContext sc;
464     llvm::DenseSet<SymbolFile *> searched_files;
465     const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
466     for (auto Enum : EnumsToCheck)
467     {
468         TypeMap results;
469         EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0, searched_files, results));
470         EXPECT_EQ(1, results.GetSize());
471         lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
472         EXPECT_EQ(ConstString(Enum), enum_type->GetName());
473         CompilerType compiler_type = enum_type->GetFullCompilerType();
474         EXPECT_TRUE(ClangASTContext::IsEnumType(compiler_type.GetOpaqueQualType()));
475         clang::EnumDecl *enum_decl = ClangASTContext::GetAsEnumDecl(compiler_type);
476         EXPECT_NE(nullptr, enum_decl);
477         EXPECT_EQ(2, std::distance(enum_decl->enumerator_begin(), enum_decl->enumerator_end()));
478 
479         std::string sizeof_var = "sizeof_";
480         sizeof_var.append(Enum);
481         EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), enum_type->GetByteSize());
482     }
483 }
484 
485 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestArrayTypes))
486 {
487     // In order to get this test working, we need to support lookup by symbol name.  Because array
488     // types themselves do not have names, only the symbols have names (i.e. the name of the array).
489 }
490 
491 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestFunctionTypes))
492 {
493     // In order to get this test working, we need to support lookup by symbol name.  Because array
494     // types themselves do not have names, only the symbols have names (i.e. the name of the array).
495 }
496 
497 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestTypedefs))
498 {
499     FileSpec fspec(m_types_test_exe.c_str(), false);
500     ArchSpec aspec("i686-pc-windows");
501     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
502 
503     SymbolVendor *plugin = module->GetSymbolVendor();
504     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
505     const llvm::IPDBSession &session = symfile->GetPDBSession();
506     SymbolContext sc;
507     llvm::DenseSet<SymbolFile *> searched_files;
508     TypeMap results;
509 
510     const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
511     for (auto Typedef : TypedefsToCheck)
512     {
513         TypeMap results;
514         EXPECT_EQ(1, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false, 0, searched_files, results));
515         EXPECT_EQ(1, results.GetSize());
516         lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
517         EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
518         CompilerType compiler_type = typedef_type->GetFullCompilerType();
519         ClangASTContext *clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
520         EXPECT_TRUE(clang_type_system->IsTypedefType(compiler_type.GetOpaqueQualType()));
521 
522         std::string sizeof_var = "sizeof_";
523         sizeof_var.append(Typedef);
524         EXPECT_EQ(GetGlobalConstantInteger(session, sizeof_var.c_str()), typedef_type->GetByteSize());
525     }
526 }
527 
528 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestRegexNameMatch))
529 {
530     FileSpec fspec(m_types_test_exe.c_str(), false);
531     ArchSpec aspec("i686-pc-windows");
532     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
533 
534     SymbolVendor *plugin = module->GetSymbolVendor();
535     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
536     SymbolContext sc;
537     llvm::DenseSet<SymbolFile *> searched_files;
538     TypeMap results;
539     int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
540     EXPECT_GT(num_results, 1);
541     EXPECT_EQ(num_results, results.GetSize());
542 }
543 
544 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestMaxMatches))
545 {
546     FileSpec fspec(m_types_test_exe.c_str(), false);
547     ArchSpec aspec("i686-pc-windows");
548     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
549 
550     SymbolVendor *plugin = module->GetSymbolVendor();
551     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
552     SymbolContext sc;
553     llvm::DenseSet<SymbolFile *> searched_files;
554     TypeMap results;
555     int num_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, 0, searched_files, results);
556     // Try to limit ourselves from 1 to 10 results, otherwise we could be doing this thousands of times.
557     // The idea is just to make sure that for a variety of values, the number of limited results always
558     // comes out to the number we are expecting.
559     int iterations = std::min(num_results, 10);
560     for (int i = 1; i <= iterations; ++i)
561     {
562         int num_limited_results = symfile->FindTypes(sc, ConstString(".*"), nullptr, false, i, searched_files, results);
563         EXPECT_EQ(i, num_limited_results);
564         EXPECT_EQ(num_limited_results, results.GetSize());
565     }
566 }
567 
568 TEST_F(SymbolFilePDBTests, REQUIRES_DIA_SDK(TestNullName))
569 {
570     FileSpec fspec(m_types_test_exe.c_str(), false);
571     ArchSpec aspec("i686-pc-windows");
572     lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
573 
574     SymbolVendor *plugin = module->GetSymbolVendor();
575     SymbolFilePDB *symfile = static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
576     SymbolContext sc;
577     llvm::DenseSet<SymbolFile *> searched_files;
578     TypeMap results;
579     int num_results = symfile->FindTypes(sc, ConstString(), nullptr, false, 0, searched_files, results);
580     EXPECT_EQ(0, num_results);
581     EXPECT_EQ(0, results.GetSize());
582 }
583