1 //===-- DWARFASTParserClangTests.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 "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" 10 #include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" 12 #include "TestingSupport/Symbol/ClangTestUtils.h" 13 #include "TestingSupport/Symbol/YAMLModuleTester.h" 14 #include "lldb/Core/Debugger.h" 15 #include "gmock/gmock.h" 16 #include "gtest/gtest.h" 17 18 using namespace lldb; 19 using namespace lldb_private; 20 using namespace lldb_private::dwarf; 21 using namespace lldb_private::plugin::dwarf; 22 23 namespace { 24 static std::once_flag debugger_initialize_flag; 25 26 class DWARFASTParserClangTests : public testing::Test { 27 void SetUp() override { 28 std::call_once(debugger_initialize_flag, 29 []() { Debugger::Initialize(nullptr); }); 30 } 31 }; 32 33 class DWARFASTParserClangStub : public DWARFASTParserClang { 34 public: 35 using DWARFASTParserClang::DWARFASTParserClang; 36 using DWARFASTParserClang::LinkDeclContextToDIE; 37 38 std::vector<const clang::DeclContext *> GetDeclContextToDIEMapKeys() { 39 std::vector<const clang::DeclContext *> keys; 40 for (const auto &it : m_decl_ctx_to_die) 41 keys.push_back(it.first); 42 return keys; 43 } 44 }; 45 } // namespace 46 47 // If your implementation needs to dereference the dummy pointers we are 48 // defining here, causing this test to fail, feel free to delete it. 49 TEST_F(DWARFASTParserClangTests, 50 EnsureAllDIEsInDeclContextHaveBeenParsedParsesOnlyMatchingEntries) { 51 52 /// Auxiliary debug info. 53 const char *yamldata = R"( 54 --- !ELF 55 FileHeader: 56 Class: ELFCLASS64 57 Data: ELFDATA2LSB 58 Type: ET_EXEC 59 Machine: EM_386 60 DWARF: 61 debug_abbrev: 62 - Table: 63 - Code: 0x00000001 64 Tag: DW_TAG_compile_unit 65 Children: DW_CHILDREN_yes 66 Attributes: 67 - Attribute: DW_AT_language 68 Form: DW_FORM_data2 69 - Code: 0x00000002 70 Tag: DW_TAG_base_type 71 Children: DW_CHILDREN_no 72 Attributes: 73 - Attribute: DW_AT_encoding 74 Form: DW_FORM_data1 75 - Attribute: DW_AT_byte_size 76 Form: DW_FORM_data1 77 debug_info: 78 - Version: 4 79 AddrSize: 8 80 Entries: 81 - AbbrCode: 0x00000001 82 Values: 83 - Value: 0x000000000000000C 84 - AbbrCode: 0x00000002 85 Values: 86 - Value: 0x0000000000000007 # DW_ATE_unsigned 87 - Value: 0x0000000000000004 88 - AbbrCode: 0x00000002 89 Values: 90 - Value: 0x0000000000000007 # DW_ATE_unsigned 91 - Value: 0x0000000000000008 92 - AbbrCode: 0x00000002 93 Values: 94 - Value: 0x0000000000000005 # DW_ATE_signed 95 - Value: 0x0000000000000008 96 - AbbrCode: 0x00000002 97 Values: 98 - Value: 0x0000000000000008 # DW_ATE_unsigned_char 99 - Value: 0x0000000000000001 100 - AbbrCode: 0x00000000 101 )"; 102 103 YAMLModuleTester t(yamldata); 104 ASSERT_TRUE((bool)t.GetDwarfUnit()); 105 106 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 107 auto &ast_ctx = *holder->GetAST(); 108 109 DWARFASTParserClangStub ast_parser(ast_ctx); 110 111 DWARFUnit *unit = t.GetDwarfUnit(); 112 const DWARFDebugInfoEntry *die_first = unit->DIE().GetDIE(); 113 const DWARFDebugInfoEntry *die_child0 = die_first->GetFirstChild(); 114 const DWARFDebugInfoEntry *die_child1 = die_child0->GetSibling(); 115 const DWARFDebugInfoEntry *die_child2 = die_child1->GetSibling(); 116 const DWARFDebugInfoEntry *die_child3 = die_child2->GetSibling(); 117 std::vector<DWARFDIE> dies = { 118 DWARFDIE(unit, die_child0), DWARFDIE(unit, die_child1), 119 DWARFDIE(unit, die_child2), DWARFDIE(unit, die_child3)}; 120 std::vector<clang::DeclContext *> decl_ctxs = { 121 (clang::DeclContext *)1LL, (clang::DeclContext *)2LL, 122 (clang::DeclContext *)2LL, (clang::DeclContext *)3LL}; 123 for (int i = 0; i < 4; ++i) 124 ast_parser.LinkDeclContextToDIE(decl_ctxs[i], dies[i]); 125 ast_parser.EnsureAllDIEsInDeclContextHaveBeenParsed( 126 CompilerDeclContext(nullptr, decl_ctxs[1])); 127 128 EXPECT_THAT(ast_parser.GetDeclContextToDIEMapKeys(), 129 testing::UnorderedElementsAre(decl_ctxs[0], decl_ctxs[3])); 130 } 131 132 TEST_F(DWARFASTParserClangTests, TestCallingConventionParsing) { 133 // Tests parsing DW_AT_calling_convention values. 134 135 // The DWARF below just declares a list of function types with 136 // DW_AT_calling_convention on them. 137 const char *yamldata = R"( 138 --- !ELF 139 FileHeader: 140 Class: ELFCLASS32 141 Data: ELFDATA2LSB 142 Type: ET_EXEC 143 Machine: EM_386 144 DWARF: 145 debug_str: 146 - func1 147 - func2 148 - func3 149 - func4 150 - func5 151 - func6 152 - func7 153 - func8 154 - func9 155 debug_abbrev: 156 - ID: 0 157 Table: 158 - Code: 0x1 159 Tag: DW_TAG_compile_unit 160 Children: DW_CHILDREN_yes 161 Attributes: 162 - Attribute: DW_AT_language 163 Form: DW_FORM_data2 164 - Code: 0x2 165 Tag: DW_TAG_subprogram 166 Children: DW_CHILDREN_no 167 Attributes: 168 - Attribute: DW_AT_low_pc 169 Form: DW_FORM_addr 170 - Attribute: DW_AT_high_pc 171 Form: DW_FORM_data4 172 - Attribute: DW_AT_name 173 Form: DW_FORM_strp 174 - Attribute: DW_AT_calling_convention 175 Form: DW_FORM_data1 176 - Attribute: DW_AT_external 177 Form: DW_FORM_flag_present 178 debug_info: 179 - Version: 4 180 AddrSize: 4 181 Entries: 182 - AbbrCode: 0x1 183 Values: 184 - Value: 0xC 185 - AbbrCode: 0x2 186 Values: 187 - Value: 0x0 188 - Value: 0x5 189 - Value: 0x00 190 - Value: 0xCB 191 - Value: 0x1 192 - AbbrCode: 0x2 193 Values: 194 - Value: 0x10 195 - Value: 0x5 196 - Value: 0x06 197 - Value: 0xB3 198 - Value: 0x1 199 - AbbrCode: 0x2 200 Values: 201 - Value: 0x20 202 - Value: 0x5 203 - Value: 0x0C 204 - Value: 0xB1 205 - Value: 0x1 206 - AbbrCode: 0x2 207 Values: 208 - Value: 0x30 209 - Value: 0x5 210 - Value: 0x12 211 - Value: 0xC0 212 - Value: 0x1 213 - AbbrCode: 0x2 214 Values: 215 - Value: 0x40 216 - Value: 0x5 217 - Value: 0x18 218 - Value: 0xB2 219 - Value: 0x1 220 - AbbrCode: 0x2 221 Values: 222 - Value: 0x50 223 - Value: 0x5 224 - Value: 0x1E 225 - Value: 0xC1 226 - Value: 0x1 227 - AbbrCode: 0x2 228 Values: 229 - Value: 0x60 230 - Value: 0x5 231 - Value: 0x24 232 - Value: 0xC2 233 - Value: 0x1 234 - AbbrCode: 0x2 235 Values: 236 - Value: 0x70 237 - Value: 0x5 238 - Value: 0x2a 239 - Value: 0xEE 240 - Value: 0x1 241 - AbbrCode: 0x2 242 Values: 243 - Value: 0x80 244 - Value: 0x5 245 - Value: 0x30 246 - Value: 0x01 247 - Value: 0x1 248 - AbbrCode: 0x0 249 ... 250 )"; 251 YAMLModuleTester t(yamldata); 252 253 DWARFUnit *unit = t.GetDwarfUnit(); 254 ASSERT_NE(unit, nullptr); 255 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 256 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 257 DWARFDIE cu_die(unit, cu_entry); 258 259 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 260 auto &ast_ctx = *holder->GetAST(); 261 DWARFASTParserClangStub ast_parser(ast_ctx); 262 263 std::vector<std::string> found_function_types; 264 // The DWARF above is just a list of functions. Parse all of them to 265 // extract the function types and their calling convention values. 266 for (DWARFDIE func : cu_die.children()) { 267 ASSERT_EQ(func.Tag(), DW_TAG_subprogram); 268 SymbolContext sc; 269 bool new_type = false; 270 lldb::TypeSP type = ast_parser.ParseTypeFromDWARF(sc, func, &new_type); 271 found_function_types.push_back( 272 type->GetForwardCompilerType().GetTypeName().AsCString()); 273 } 274 275 // Compare the parsed function types against the expected list of types. 276 const std::vector<std::string> expected_function_types = { 277 "void () __attribute__((regcall))", 278 "void () __attribute__((fastcall))", 279 "void () __attribute__((stdcall))", 280 "void () __attribute__((vectorcall))", 281 "void () __attribute__((pascal))", 282 "void () __attribute__((ms_abi))", 283 "void () __attribute__((sysv_abi))", 284 "void ()", // invalid calling convention. 285 "void ()", // DW_CC_normal -> no attribute 286 }; 287 ASSERT_EQ(found_function_types, expected_function_types); 288 } 289 290 TEST_F(DWARFASTParserClangTests, TestPtrAuthParsing) { 291 // Tests parsing values with type DW_TAG_LLVM_ptrauth_type corresponding to 292 // explicitly signed raw function pointers 293 294 // This is Dwarf for the following C code: 295 // ``` 296 // void (*__ptrauth(0, 0, 42) a)(); 297 // ``` 298 299 const char *yamldata = R"( 300 --- !ELF 301 FileHeader: 302 Class: ELFCLASS64 303 Data: ELFDATA2LSB 304 Type: ET_EXEC 305 Machine: EM_AARCH64 306 DWARF: 307 debug_str: 308 - a 309 debug_abbrev: 310 - ID: 0 311 Table: 312 - Code: 0x01 313 Tag: DW_TAG_compile_unit 314 Children: DW_CHILDREN_yes 315 Attributes: 316 - Attribute: DW_AT_language 317 Form: DW_FORM_data2 318 - Code: 0x02 319 Tag: DW_TAG_variable 320 Children: DW_CHILDREN_no 321 Attributes: 322 - Attribute: DW_AT_name 323 Form: DW_FORM_strp 324 - Attribute: DW_AT_type 325 Form: DW_FORM_ref4 326 - Attribute: DW_AT_external 327 Form: DW_FORM_flag_present 328 - Code: 0x03 329 Tag: DW_TAG_LLVM_ptrauth_type 330 Children: DW_CHILDREN_no 331 Attributes: 332 - Attribute: DW_AT_type 333 Form: DW_FORM_ref4 334 - Attribute: DW_AT_LLVM_ptrauth_key 335 Form: DW_FORM_data1 336 - Attribute: DW_AT_LLVM_ptrauth_extra_discriminator 337 Form: DW_FORM_data2 338 - Code: 0x04 339 Tag: DW_TAG_pointer_type 340 Children: DW_CHILDREN_no 341 Attributes: 342 - Attribute: DW_AT_type 343 Form: DW_FORM_ref4 344 - Code: 0x05 345 Tag: DW_TAG_subroutine_type 346 Children: DW_CHILDREN_yes 347 - Code: 0x06 348 Tag: DW_TAG_unspecified_parameters 349 Children: DW_CHILDREN_no 350 351 debug_info: 352 - Version: 5 353 UnitType: DW_UT_compile 354 AddrSize: 8 355 Entries: 356 # 0x0c: DW_TAG_compile_unit 357 # DW_AT_language [DW_FORM_data2] (DW_LANG_C99) 358 - AbbrCode: 0x01 359 Values: 360 - Value: 0x0c 361 362 # 0x0f: DW_TAG_variable 363 # DW_AT_name [DW_FORM_strp] (\"a\") 364 # DW_AT_type [DW_FORM_ref4] (0x00000018 \"void (*__ptrauth(0, 0, 0x02a)\") 365 # DW_AT_external [DW_FORM_flag_present] (true) 366 - AbbrCode: 0x02 367 Values: 368 - Value: 0x00 369 - Value: 0x18 370 371 # 0x18: DW_TAG_LLVM_ptrauth_type 372 # DW_AT_type [DW_FORM_ref4] (0x00000020 \"void (*)(...)\") 373 # DW_AT_LLVM_ptrauth_key [DW_FORM_data1] (0x00) 374 # DW_AT_LLVM_ptrauth_extra_discriminator [DW_FORM_data2] (0x002a) 375 - AbbrCode: 0x03 376 Values: 377 - Value: 0x20 378 - Value: 0x00 379 - Value: 0x2a 380 381 # 0x20: DW_TAG_pointer_type 382 # DW_AT_type [DW_AT_type [DW_FORM_ref4] (0x00000025 \"void (...)\") 383 - AbbrCode: 0x04 384 Values: 385 - Value: 0x25 386 387 # 0x25: DW_TAG_subroutine_type 388 - AbbrCode: 0x05 389 390 # 0x26: DW_TAG_unspecified_parameters 391 - AbbrCode: 0x06 392 393 - AbbrCode: 0x00 # end of child tags of 0x25 394 - AbbrCode: 0x00 # end of child tags of 0x0c 395 ... 396 )"; 397 YAMLModuleTester t(yamldata); 398 399 DWARFUnit *unit = t.GetDwarfUnit(); 400 ASSERT_NE(unit, nullptr); 401 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 402 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 403 DWARFDIE cu_die(unit, cu_entry); 404 405 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 406 auto &ast_ctx = *holder->GetAST(); 407 DWARFASTParserClangStub ast_parser(ast_ctx); 408 409 DWARFDIE ptrauth_variable = cu_die.GetFirstChild(); 410 ASSERT_EQ(ptrauth_variable.Tag(), DW_TAG_variable); 411 DWARFDIE ptrauth_type = 412 ptrauth_variable.GetAttributeValueAsReferenceDIE(DW_AT_type); 413 ASSERT_EQ(ptrauth_type.Tag(), DW_TAG_LLVM_ptrauth_type); 414 415 SymbolContext sc; 416 bool new_type = false; 417 lldb::TypeSP type_sp = 418 ast_parser.ParseTypeFromDWARF(sc, ptrauth_type, &new_type); 419 CompilerType compiler_type = type_sp->GetForwardCompilerType(); 420 ASSERT_EQ(compiler_type.GetPtrAuthKey(), 0U); 421 ASSERT_EQ(compiler_type.GetPtrAuthAddressDiversity(), false); 422 ASSERT_EQ(compiler_type.GetPtrAuthDiscriminator(), 42U); 423 } 424 425 struct ExtractIntFromFormValueTest : public testing::Test { 426 SubsystemRAII<FileSystem, HostInfo> subsystems; 427 clang_utils::TypeSystemClangHolder holder; 428 TypeSystemClang &ts; 429 430 DWARFASTParserClang parser; 431 ExtractIntFromFormValueTest() 432 : holder("dummy ASTContext"), ts(*holder.GetAST()), parser(ts) {} 433 434 /// Takes the given integer value, stores it in a DWARFFormValue and then 435 /// tries to extract the value back via 436 /// DWARFASTParserClang::ExtractIntFromFormValue. 437 /// Returns the string representation of the extracted value or the error 438 /// that was returned from ExtractIntFromFormValue. 439 llvm::Expected<std::string> Extract(clang::QualType qt, uint64_t value) { 440 DWARFFormValue form_value; 441 form_value.SetUnsigned(value); 442 llvm::Expected<llvm::APInt> result = 443 parser.ExtractIntFromFormValue(ts.GetType(qt), form_value); 444 if (!result) 445 return result.takeError(); 446 llvm::SmallString<16> result_str; 447 result->toStringUnsigned(result_str); 448 return std::string(result_str.str()); 449 } 450 451 /// Same as ExtractIntFromFormValueTest::Extract but takes a signed integer 452 /// and treats the result as a signed integer. 453 llvm::Expected<std::string> ExtractS(clang::QualType qt, int64_t value) { 454 DWARFFormValue form_value; 455 form_value.SetSigned(value); 456 llvm::Expected<llvm::APInt> result = 457 parser.ExtractIntFromFormValue(ts.GetType(qt), form_value); 458 if (!result) 459 return result.takeError(); 460 llvm::SmallString<16> result_str; 461 result->toStringSigned(result_str); 462 return std::string(result_str.str()); 463 } 464 }; 465 466 TEST_F(ExtractIntFromFormValueTest, TestBool) { 467 using namespace llvm; 468 clang::ASTContext &ast = ts.getASTContext(); 469 470 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 0), HasValue("0")); 471 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 1), HasValue("1")); 472 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 2), Failed()); 473 EXPECT_THAT_EXPECTED(Extract(ast.BoolTy, 3), Failed()); 474 } 475 476 TEST_F(ExtractIntFromFormValueTest, TestInt) { 477 using namespace llvm; 478 479 clang::ASTContext &ast = ts.getASTContext(); 480 481 // Find the min/max values for 'int' on the current host target. 482 constexpr int64_t int_max = std::numeric_limits<int>::max(); 483 constexpr int64_t int_min = std::numeric_limits<int>::min(); 484 485 // Check that the bit width of int matches the int width in our type system. 486 ASSERT_EQ(sizeof(int) * 8, ast.getIntWidth(ast.IntTy)); 487 488 // Check values around int_min. 489 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 2), llvm::Failed()); 490 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min - 1), llvm::Failed()); 491 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min), 492 HasValue(std::to_string(int_min))); 493 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 1), 494 HasValue(std::to_string(int_min + 1))); 495 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min + 2), 496 HasValue(std::to_string(int_min + 2))); 497 498 // Check values around 0. 499 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -128), HasValue("-128")); 500 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -10), HasValue("-10")); 501 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, -1), HasValue("-1")); 502 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 0), HasValue("0")); 503 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 1), HasValue("1")); 504 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 10), HasValue("10")); 505 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, 128), HasValue("128")); 506 507 // Check values around int_max. 508 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 2), 509 HasValue(std::to_string(int_max - 2))); 510 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max - 1), 511 HasValue(std::to_string(int_max - 1))); 512 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max), 513 HasValue(std::to_string(int_max))); 514 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 1), llvm::Failed()); 515 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max + 5), llvm::Failed()); 516 517 // Check some values not near an edge case. 518 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_max / 2), 519 HasValue(std::to_string(int_max / 2))); 520 EXPECT_THAT_EXPECTED(ExtractS(ast.IntTy, int_min / 2), 521 HasValue(std::to_string(int_min / 2))); 522 } 523 524 TEST_F(ExtractIntFromFormValueTest, TestUnsignedInt) { 525 using namespace llvm; 526 527 clang::ASTContext &ast = ts.getASTContext(); 528 constexpr uint64_t uint_max = std::numeric_limits<uint32_t>::max(); 529 530 // Check values around 0. 531 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 0), HasValue("0")); 532 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1), HasValue("1")); 533 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, 1234), HasValue("1234")); 534 535 // Check some values not near an edge case. 536 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max / 2), 537 HasValue(std::to_string(uint_max / 2))); 538 539 // Check values around uint_max. 540 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max - 2), 541 HasValue(std::to_string(uint_max - 2))); 542 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max - 1), 543 HasValue(std::to_string(uint_max - 1))); 544 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max), 545 HasValue(std::to_string(uint_max))); 546 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max + 1), 547 llvm::Failed()); 548 EXPECT_THAT_EXPECTED(Extract(ast.UnsignedIntTy, uint_max + 2), 549 llvm::Failed()); 550 } 551 552 TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) { 553 // Tests parsing DW_AT_default_value for template parameters. 554 auto BufferOrError = llvm::MemoryBuffer::getFile( 555 GetInputFilePath("DW_AT_default_value-test.yaml"), /*IsText=*/true); 556 ASSERT_TRUE(BufferOrError); 557 YAMLModuleTester t(BufferOrError.get()->getBuffer()); 558 559 DWARFUnit *unit = t.GetDwarfUnit(); 560 ASSERT_NE(unit, nullptr); 561 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 562 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 563 DWARFDIE cu_die(unit, cu_entry); 564 565 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 566 auto &ast_ctx = *holder->GetAST(); 567 DWARFASTParserClangStub ast_parser(ast_ctx); 568 569 llvm::SmallVector<lldb::TypeSP, 2> types; 570 for (DWARFDIE die : cu_die.children()) { 571 if (die.Tag() == DW_TAG_class_type) { 572 SymbolContext sc; 573 bool new_type = false; 574 types.push_back(ast_parser.ParseTypeFromDWARF(sc, die, &new_type)); 575 } 576 } 577 578 ASSERT_EQ(types.size(), 3U); 579 580 auto check_decl = [](auto const *decl) { 581 clang::ClassTemplateSpecializationDecl const *ctsd = 582 llvm::dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(decl); 583 ASSERT_NE(ctsd, nullptr); 584 585 auto const &args = ctsd->getTemplateArgs(); 586 ASSERT_GT(args.size(), 0U); 587 588 for (auto const &arg : args.asArray()) { 589 EXPECT_TRUE(arg.getIsDefaulted()); 590 } 591 }; 592 593 for (auto const &type_sp : types) { 594 ASSERT_NE(type_sp, nullptr); 595 auto const *decl = ClangUtil::GetAsTagDecl(type_sp->GetFullCompilerType()); 596 if (decl->getName() == "bar" || decl->getName() == "baz") { 597 check_decl(decl); 598 } 599 } 600 } 601 602 TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) { 603 // This tests the behaviour of UniqueDWARFASTTypeMap under 604 // following scenario: 605 // 1. DWARFASTParserClang parses a forward declaration and 606 // inserts it into the UniqueDWARFASTTypeMap. 607 // 2. We then MapDeclDIEToDefDIE which updates the map 608 // entry with the line number/file information of the definition. 609 // 3. Parse the definition DIE, which should return the previously 610 // parsed type from the UniqueDWARFASTTypeMap. 611 612 const char *yamldata = R"( 613 --- !ELF 614 FileHeader: 615 Class: ELFCLASS64 616 Data: ELFDATA2LSB 617 Type: ET_EXEC 618 Machine: EM_AARCH64 619 DWARF: 620 debug_str: 621 - Foo 622 623 debug_line: 624 - Version: 4 625 MinInstLength: 1 626 MaxOpsPerInst: 1 627 DefaultIsStmt: 1 628 LineBase: 0 629 LineRange: 0 630 Files: 631 - Name: main.cpp 632 DirIdx: 0 633 ModTime: 0 634 Length: 0 635 636 debug_abbrev: 637 - ID: 0 638 Table: 639 - Code: 0x01 640 Tag: DW_TAG_compile_unit 641 Children: DW_CHILDREN_yes 642 Attributes: 643 - Attribute: DW_AT_language 644 Form: DW_FORM_data2 645 - Attribute: DW_AT_stmt_list 646 Form: DW_FORM_sec_offset 647 - Code: 0x02 648 Tag: DW_TAG_structure_type 649 Children: DW_CHILDREN_no 650 Attributes: 651 - Attribute: DW_AT_name 652 Form: DW_FORM_strp 653 - Attribute: DW_AT_declaration 654 Form: DW_FORM_flag_present 655 - Code: 0x03 656 Tag: DW_TAG_structure_type 657 Children: DW_CHILDREN_no 658 Attributes: 659 - Attribute: DW_AT_name 660 Form: DW_FORM_strp 661 - Attribute: DW_AT_decl_file 662 Form: DW_FORM_data1 663 - Attribute: DW_AT_decl_line 664 Form: DW_FORM_data1 665 666 debug_info: 667 - Version: 5 668 UnitType: DW_UT_compile 669 AddrSize: 8 670 Entries: 671 # 0x0c: DW_TAG_compile_unit 672 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 673 # DW_AT_stmt_list [DW_FORM_sec_offset] 674 - AbbrCode: 0x01 675 Values: 676 - Value: 0x04 677 - Value: 0x0000000000000000 678 679 # 0x0d: DW_TAG_structure_type 680 # DW_AT_name [DW_FORM_strp] (\"Foo\") 681 # DW_AT_declaration [DW_FORM_flag_present] (true) 682 - AbbrCode: 0x02 683 Values: 684 - Value: 0x00 685 686 # 0x0f: DW_TAG_structure_type 687 # DW_AT_name [DW_FORM_strp] (\"Foo\") 688 # DW_AT_decl_file [DW_FORM_data1] (main.cpp) 689 # DW_AT_decl_line [DW_FORM_data1] (3) 690 - AbbrCode: 0x03 691 Values: 692 - Value: 0x00 693 - Value: 0x01 694 - Value: 0x03 695 696 - AbbrCode: 0x00 # end of child tags of 0x0c 697 ... 698 )"; 699 YAMLModuleTester t(yamldata); 700 701 DWARFUnit *unit = t.GetDwarfUnit(); 702 ASSERT_NE(unit, nullptr); 703 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 704 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 705 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 706 DWARFDIE cu_die(unit, cu_entry); 707 708 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 709 auto &ast_ctx = *holder->GetAST(); 710 DWARFASTParserClangStub ast_parser(ast_ctx); 711 712 DWARFDIE decl_die; 713 DWARFDIE def_die; 714 for (auto const &die : cu_die.children()) { 715 if (die.Tag() != DW_TAG_structure_type) 716 continue; 717 718 if (die.GetAttributeValueAsOptionalUnsigned(llvm::dwarf::DW_AT_declaration)) 719 decl_die = die; 720 else 721 def_die = die; 722 } 723 724 ASSERT_TRUE(decl_die.IsValid()); 725 ASSERT_TRUE(def_die.IsValid()); 726 ASSERT_NE(decl_die, def_die); 727 728 ParsedDWARFTypeAttributes attrs(def_die); 729 ASSERT_TRUE(attrs.decl.IsValid()); 730 731 SymbolContext sc; 732 bool new_type = false; 733 lldb::TypeSP type_sp = ast_parser.ParseTypeFromDWARF(sc, decl_die, &new_type); 734 ASSERT_NE(type_sp, nullptr); 735 736 ast_parser.MapDeclDIEToDefDIE(decl_die, def_die); 737 738 lldb::TypeSP reparsed_type_sp = 739 ast_parser.ParseTypeFromDWARF(sc, def_die, &new_type); 740 ASSERT_NE(reparsed_type_sp, nullptr); 741 742 ASSERT_EQ(type_sp, reparsed_type_sp); 743 } 744 745 TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointer) { 746 // This tests the behaviour of ParsedDWARFTypeAttributes 747 // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer 748 // *and* a DW_AT_specification that also has a DW_AT_object_pointer. 749 // We don't want the declaration DW_AT_object_pointer to overwrite the 750 // one from the more specific definition's. 751 752 const char *yamldata = R"( 753 --- !ELF 754 FileHeader: 755 Class: ELFCLASS64 756 Data: ELFDATA2LSB 757 Type: ET_EXEC 758 Machine: EM_AARCH64 759 DWARF: 760 debug_str: 761 - Context 762 - func 763 - this 764 debug_abbrev: 765 - ID: 0 766 Table: 767 - Code: 0x1 768 Tag: DW_TAG_compile_unit 769 Children: DW_CHILDREN_yes 770 Attributes: 771 - Attribute: DW_AT_language 772 Form: DW_FORM_data2 773 - Code: 0x2 774 Tag: DW_TAG_structure_type 775 Children: DW_CHILDREN_yes 776 Attributes: 777 - Attribute: DW_AT_name 778 Form: DW_FORM_strp 779 - Code: 0x3 780 Tag: DW_TAG_subprogram 781 Children: DW_CHILDREN_yes 782 Attributes: 783 - Attribute: DW_AT_name 784 Form: DW_FORM_strp 785 - Attribute: DW_AT_declaration 786 Form: DW_FORM_flag_present 787 - Attribute: DW_AT_object_pointer 788 Form: DW_FORM_ref4 789 - Attribute: DW_AT_artificial 790 Form: DW_FORM_flag_present 791 - Attribute: DW_AT_external 792 Form: DW_FORM_flag_present 793 - Code: 0x4 794 Tag: DW_TAG_formal_parameter 795 Children: DW_CHILDREN_no 796 Attributes: 797 - Attribute: DW_AT_artificial 798 Form: DW_FORM_flag_present 799 - Code: 0x5 800 Tag: DW_TAG_subprogram 801 Children: DW_CHILDREN_yes 802 Attributes: 803 - Attribute: DW_AT_object_pointer 804 Form: DW_FORM_ref4 805 - Attribute: DW_AT_specification 806 Form: DW_FORM_ref4 807 - Code: 0x6 808 Tag: DW_TAG_formal_parameter 809 Children: DW_CHILDREN_no 810 Attributes: 811 - Attribute: DW_AT_name 812 Form: DW_FORM_strp 813 - Attribute: DW_AT_artificial 814 Form: DW_FORM_flag_present 815 debug_info: 816 - Version: 5 817 UnitType: DW_UT_compile 818 AddrSize: 8 819 Entries: 820 821 # DW_TAG_compile_unit 822 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 823 824 - AbbrCode: 0x1 825 Values: 826 - Value: 0x04 827 828 # DW_TAG_structure_type 829 # DW_AT_name [DW_FORM_strp] ("Context") 830 831 - AbbrCode: 0x2 832 Values: 833 - Value: 0x0 834 835 # DW_TAG_subprogram 836 # DW_AT_name [DW_FORM_strp] ("func") 837 # DW_AT_object_pointer [DW_FORM_ref4] 838 - AbbrCode: 0x3 839 Values: 840 - Value: 0x8 841 - Value: 0x1 842 - Value: 0x1d 843 - Value: 0x1 844 - Value: 0x1 845 846 # DW_TAG_formal_parameter 847 # DW_AT_artificial 848 - AbbrCode: 0x4 849 Values: 850 - Value: 0x1 851 852 - AbbrCode: 0x0 853 - AbbrCode: 0x0 854 855 # DW_TAG_subprogram 856 # DW_AT_object_pointer [DW_FORM_ref4] ("this") 857 # DW_AT_specification [DW_FORM_ref4] ("func") 858 - AbbrCode: 0x5 859 Values: 860 - Value: 0x29 861 - Value: 0x14 862 863 # DW_TAG_formal_parameter 864 # DW_AT_name [DW_FORM_strp] ("this") 865 # DW_AT_artificial 866 - AbbrCode: 0x6 867 Values: 868 - Value: 0xd 869 - Value: 0x1 870 871 - AbbrCode: 0x0 872 - AbbrCode: 0x0 873 ... 874 )"; 875 YAMLModuleTester t(yamldata); 876 877 DWARFUnit *unit = t.GetDwarfUnit(); 878 ASSERT_NE(unit, nullptr); 879 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 880 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 881 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 882 DWARFDIE cu_die(unit, cu_entry); 883 884 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast"); 885 auto &ast_ctx = *holder->GetAST(); 886 DWARFASTParserClangStub ast_parser(ast_ctx); 887 888 auto context_die = cu_die.GetFirstChild(); 889 ASSERT_TRUE(context_die.IsValid()); 890 ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type); 891 892 auto subprogram_definition = context_die.GetSibling(); 893 ASSERT_TRUE(subprogram_definition.IsValid()); 894 ASSERT_EQ(subprogram_definition.Tag(), DW_TAG_subprogram); 895 ASSERT_FALSE(subprogram_definition.GetAttributeValueAsOptionalUnsigned( 896 DW_AT_external)); 897 898 auto param_die = subprogram_definition.GetFirstChild(); 899 ASSERT_TRUE(param_die.IsValid()); 900 901 ParsedDWARFTypeAttributes attrs(subprogram_definition); 902 EXPECT_TRUE(attrs.object_pointer.IsValid()); 903 EXPECT_EQ(attrs.object_pointer, param_die); 904 } 905 906 TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) { 907 // Tests parsing of a C++ non-static member function with an explicit object 908 // parameter that isn't called "this" and is not a pointer (but a CV-qualified 909 // rvalue reference instead). 910 911 const char *yamldata = R"( 912 --- !ELF 913 FileHeader: 914 Class: ELFCLASS64 915 Data: ELFDATA2LSB 916 Type: ET_EXEC 917 Machine: EM_AARCH64 918 DWARF: 919 debug_str: 920 - Context 921 - func 922 - mySelf 923 debug_abbrev: 924 - ID: 0 925 Table: 926 - Code: 0x1 927 Tag: DW_TAG_compile_unit 928 Children: DW_CHILDREN_yes 929 Attributes: 930 - Attribute: DW_AT_language 931 Form: DW_FORM_data2 932 - Code: 0x2 933 Tag: DW_TAG_structure_type 934 Children: DW_CHILDREN_yes 935 Attributes: 936 - Attribute: DW_AT_name 937 Form: DW_FORM_strp 938 - Code: 0x3 939 Tag: DW_TAG_subprogram 940 Children: DW_CHILDREN_yes 941 Attributes: 942 - Attribute: DW_AT_name 943 Form: DW_FORM_strp 944 - Attribute: DW_AT_declaration 945 Form: DW_FORM_flag_present 946 - Attribute: DW_AT_object_pointer 947 Form: DW_FORM_ref4 948 - Attribute: DW_AT_external 949 Form: DW_FORM_flag_present 950 - Code: 0x4 951 Tag: DW_TAG_formal_parameter 952 Children: DW_CHILDREN_no 953 Attributes: 954 - Attribute: DW_AT_name 955 Form: DW_FORM_strp 956 - Attribute: DW_AT_type 957 Form: DW_FORM_ref4 958 - Code: 0x5 959 Tag: DW_TAG_rvalue_reference_type 960 Children: DW_CHILDREN_no 961 Attributes: 962 - Attribute: DW_AT_type 963 Form: DW_FORM_ref4 964 - Code: 0x6 965 Tag: DW_TAG_const_type 966 Children: DW_CHILDREN_no 967 Attributes: 968 - Attribute: DW_AT_type 969 Form: DW_FORM_ref4 970 - Code: 0x7 971 Tag: DW_TAG_volatile_type 972 Children: DW_CHILDREN_no 973 Attributes: 974 - Attribute: DW_AT_type 975 Form: DW_FORM_ref4 976 debug_info: 977 - Version: 5 978 UnitType: DW_UT_compile 979 AddrSize: 8 980 Entries: 981 982 # DW_TAG_compile_unit 983 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 984 985 - AbbrCode: 0x1 986 Values: 987 - Value: 0x04 988 989 # DW_TAG_structure_type 990 # DW_AT_name [DW_FORM_strp] ("Context") 991 992 - AbbrCode: 0x2 993 Values: 994 - Value: 0x0 995 996 # DW_TAG_subprogram 997 # DW_AT_name [DW_FORM_strp] ("func") 998 # DW_AT_object_pointer [DW_FORM_ref4] 999 - AbbrCode: 0x3 1000 Values: 1001 - Value: 0x8 1002 - Value: 0x1 1003 - Value: 0x1d 1004 - Value: 0x1 1005 1006 # DW_TAG_formal_parameter 1007 # DW_AT_name [DW_FORM_strp] ("mySelf") 1008 # DW_AT_type [DW_FORM_ref4] (const volatile Context &&) 1009 - AbbrCode: 0x4 1010 Values: 1011 - Value: 0xd 1012 - Value: 0x28 1013 1014 - AbbrCode: 0x0 1015 - AbbrCode: 0x0 1016 1017 # DW_TAG_rvalue_reference_type 1018 # DW_AT_type [DW_FORM_ref4] ("const volatile Context") 1019 1020 - AbbrCode: 0x5 1021 Values: 1022 - Value: 0x2d 1023 1024 # DW_TAG_const_type 1025 # DW_AT_type [DW_FORM_ref4] ("volatile Context") 1026 1027 - AbbrCode: 0x6 1028 Values: 1029 - Value: 0x32 1030 1031 # DW_TAG_volatile_type 1032 # DW_AT_type [DW_FORM_ref4] ("Context") 1033 1034 - AbbrCode: 0x7 1035 Values: 1036 - Value: 0xf 1037 1038 - AbbrCode: 0x0 1039 ... 1040 )"; 1041 YAMLModuleTester t(yamldata); 1042 1043 DWARFUnit *unit = t.GetDwarfUnit(); 1044 ASSERT_NE(unit, nullptr); 1045 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 1046 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 1047 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 1048 DWARFDIE cu_die(unit, cu_entry); 1049 1050 auto ts_or_err = 1051 cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 1052 ASSERT_TRUE(static_cast<bool>(ts_or_err)); 1053 llvm::consumeError(ts_or_err.takeError()); 1054 auto *parser = 1055 static_cast<DWARFASTParserClang *>((*ts_or_err)->GetDWARFParser()); 1056 1057 auto context_die = cu_die.GetFirstChild(); 1058 ASSERT_TRUE(context_die.IsValid()); 1059 ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type); 1060 1061 SymbolContext sc; 1062 bool new_type; 1063 auto context_type_sp = parser->ParseTypeFromDWARF(sc, context_die, &new_type); 1064 ASSERT_NE(context_type_sp, nullptr); 1065 1066 ASSERT_TRUE( 1067 parser->CompleteTypeFromDWARF(context_die, context_type_sp.get(), 1068 context_type_sp->GetForwardCompilerType())); 1069 1070 auto *record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>( 1071 ClangUtil::GetAsTagDecl(context_type_sp->GetForwardCompilerType())); 1072 ASSERT_NE(record_decl, nullptr); 1073 1074 auto method_it = record_decl->method_begin(); 1075 ASSERT_NE(method_it, record_decl->method_end()); 1076 1077 // Check that we didn't parse the function as static. 1078 EXPECT_FALSE(method_it->isStatic()); 1079 1080 // Check that method qualifiers were correctly set. 1081 EXPECT_EQ(method_it->getMethodQualifiers(), 1082 clang::Qualifiers::fromCVRMask(clang::Qualifiers::Const | 1083 clang::Qualifiers::Volatile)); 1084 } 1085 1086 TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) { 1087 // Tests parsing of a C++ free function will create clang::ParmVarDecls with 1088 // the correct clang::DeclContext. 1089 // 1090 // Also ensures we attach names to the ParmVarDecls (even when DWARF contains 1091 // a mix of named/unnamed parameters). 1092 1093 const char *yamldata = R"( 1094 --- !ELF 1095 FileHeader: 1096 Class: ELFCLASS64 1097 Data: ELFDATA2LSB 1098 Type: ET_EXEC 1099 Machine: EM_AARCH64 1100 DWARF: 1101 debug_str: 1102 - func 1103 - int 1104 - short 1105 - namedParam 1106 debug_abbrev: 1107 - ID: 0 1108 Table: 1109 - Code: 0x1 1110 Tag: DW_TAG_compile_unit 1111 Children: DW_CHILDREN_yes 1112 Attributes: 1113 - Attribute: DW_AT_language 1114 Form: DW_FORM_data2 1115 - Code: 0x2 1116 Tag: DW_TAG_structure_type 1117 Children: DW_CHILDREN_yes 1118 Attributes: 1119 - Attribute: DW_AT_name 1120 Form: DW_FORM_strp 1121 - Code: 0x3 1122 Tag: DW_TAG_subprogram 1123 Children: DW_CHILDREN_yes 1124 Attributes: 1125 - Attribute: DW_AT_name 1126 Form: DW_FORM_strp 1127 - Attribute: DW_AT_declaration 1128 Form: DW_FORM_flag_present 1129 - Attribute: DW_AT_external 1130 Form: DW_FORM_flag_present 1131 - Code: 0x4 1132 Tag: DW_TAG_formal_parameter 1133 Children: DW_CHILDREN_no 1134 Attributes: 1135 - Attribute: DW_AT_type 1136 Form: DW_FORM_ref4 1137 - Code: 0x5 1138 Tag: DW_TAG_formal_parameter 1139 Children: DW_CHILDREN_no 1140 Attributes: 1141 - Attribute: DW_AT_type 1142 Form: DW_FORM_ref4 1143 - Attribute: DW_AT_name 1144 Form: DW_FORM_strp 1145 - Code: 0x6 1146 Tag: DW_TAG_base_type 1147 Children: DW_CHILDREN_no 1148 Attributes: 1149 - Attribute: DW_AT_name 1150 Form: DW_FORM_strp 1151 - Attribute: DW_AT_encoding 1152 Form: DW_FORM_data1 1153 - Attribute: DW_AT_byte_size 1154 Form: DW_FORM_data1 1155 debug_info: 1156 - Version: 5 1157 UnitType: DW_UT_compile 1158 AddrSize: 8 1159 Entries: 1160 1161 # DW_TAG_compile_unit 1162 # DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus) 1163 1164 - AbbrCode: 0x1 1165 Values: 1166 - Value: 0x04 1167 1168 # DW_TAG_subprogram 1169 # DW_AT_name [DW_FORM_strp] ("func") 1170 - AbbrCode: 0x3 1171 Values: 1172 - Value: 0x0 1173 - Value: 0x1 1174 - Value: 0x1 1175 1176 # DW_TAG_formal_parameter 1177 # DW_AT_type [DW_FORM_ref4] (int) 1178 - AbbrCode: 0x4 1179 Values: 1180 - Value: 0x23 1181 1182 # DW_TAG_formal_parameter 1183 # DW_AT_type [DW_FORM_ref4] (short) 1184 # DW_AT_name [DW_FORM_strp] ("namedParam") 1185 - AbbrCode: 0x5 1186 Values: 1187 - Value: 0x2a 1188 - Value: 0xf 1189 1190 - AbbrCode: 0x0 1191 1192 # DW_TAG_base_type 1193 # DW_AT_name [DW_FORM_strp] ("int") 1194 # DW_AT_encoding [DW_FORM_data1] 1195 # DW_AT_byte_size [DW_FORM_data1] 1196 1197 - AbbrCode: 0x6 1198 Values: 1199 - Value: 0x0000000000000005 1200 - Value: 0x0000000000000005 # DW_ATE_signed 1201 - Value: 0x0000000000000004 1202 1203 # DW_TAG_base_type 1204 # DW_AT_name [DW_FORM_strp] ("short") 1205 # DW_AT_encoding [DW_FORM_data1] 1206 # DW_AT_byte_size [DW_FORM_data1] 1207 1208 - AbbrCode: 0x6 1209 Values: 1210 - Value: 0x0000000000000009 1211 - Value: 0x0000000000000005 # DW_ATE_signed 1212 - Value: 0x0000000000000004 1213 1214 - AbbrCode: 0x0 1215 ... 1216 )"; 1217 YAMLModuleTester t(yamldata); 1218 1219 DWARFUnit *unit = t.GetDwarfUnit(); 1220 ASSERT_NE(unit, nullptr); 1221 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE(); 1222 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit); 1223 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus); 1224 DWARFDIE cu_die(unit, cu_entry); 1225 1226 auto ts_or_err = 1227 cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 1228 ASSERT_TRUE(static_cast<bool>(ts_or_err)); 1229 llvm::consumeError(ts_or_err.takeError()); 1230 1231 auto *ts = static_cast<TypeSystemClang *>(ts_or_err->get()); 1232 auto *parser = static_cast<DWARFASTParserClang *>(ts->GetDWARFParser()); 1233 1234 auto subprogram = cu_die.GetFirstChild(); 1235 ASSERT_TRUE(subprogram.IsValid()); 1236 ASSERT_EQ(subprogram.Tag(), DW_TAG_subprogram); 1237 1238 SymbolContext sc; 1239 bool new_type; 1240 auto type_sp = parser->ParseTypeFromDWARF(sc, subprogram, &new_type); 1241 ASSERT_NE(type_sp, nullptr); 1242 1243 auto result = ts->GetTranslationUnitDecl()->lookup( 1244 clang_utils::getDeclarationName(*ts, "func")); 1245 ASSERT_TRUE(result.isSingleResult()); 1246 1247 auto const *func = llvm::cast<clang::FunctionDecl>(result.front()); 1248 1249 EXPECT_EQ(func->getNumParams(), 2U); 1250 EXPECT_EQ(func->getParamDecl(0)->getDeclContext(), func); 1251 EXPECT_TRUE(func->getParamDecl(0)->getName().empty()); 1252 EXPECT_EQ(func->getParamDecl(1)->getDeclContext(), func); 1253 EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam"); 1254 } 1255