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