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
18using namespace lldb;
19using namespace lldb_private;
20using namespace lldb_private::dwarf;
21using namespace lldb_private::plugin::dwarf;
22
23namespace {
24static std::once_flag debugger_initialize_flag;
25
26class DWARFASTParserClangTests : public testing::Test {
27 void SetUp() override {
28 std::call_once(once&: debugger_initialize_flag,
29 f: []() { Debugger::Initialize(load_plugin_callback: nullptr); });
30 }
31};
32
33class DWARFASTParserClangStub : public DWARFASTParserClang {
34public:
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(x: 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.
49TEST_F(DWARFASTParserClangTests,
50 EnsureAllDIEsInDeclContextHaveBeenParsedParsesOnlyMatchingEntries) {
51
52 /// Auxiliary debug info.
53 const char *yamldata = R"(
54--- !ELF
55FileHeader:
56 Class: ELFCLASS64
57 Data: ELFDATA2LSB
58 Type: ET_EXEC
59 Machine: EM_386
60DWARF:
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>(args: "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_ctx: decl_ctxs[i], die: dies[i]);
125 ast_parser.EnsureAllDIEsInDeclContextHaveBeenParsed(
126 decl_context: CompilerDeclContext(nullptr, decl_ctxs[1]));
127
128 EXPECT_THAT(ast_parser.GetDeclContextToDIEMapKeys(),
129 testing::UnorderedElementsAre(decl_ctxs[0], decl_ctxs[3]));
130}
131
132TEST_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
139FileHeader:
140 Class: ELFCLASS32
141 Data: ELFDATA2LSB
142 Type: ET_EXEC
143 Machine: EM_386
144DWARF:
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>(args: "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, die: func, type_is_new_ptr: &new_type);
271 found_function_types.push_back(
272 x: 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
290TEST_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
301FileHeader:
302 Class: ELFCLASS64
303 Data: ELFDATA2LSB
304 Type: ET_EXEC
305 Machine: EM_AARCH64
306DWARF:
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>(args: "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(attr: 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, die: ptrauth_type, type_is_new_ptr: &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
425struct 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(int_type: ts.GetType(qt), form_value);
444 if (!result)
445 return result.takeError();
446 llvm::SmallString<16> result_str;
447 result->toStringUnsigned(Str&: 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(int_type: ts.GetType(qt), form_value);
458 if (!result)
459 return result.takeError();
460 llvm::SmallString<16> result_str;
461 result->toStringSigned(Str&: result_str);
462 return std::string(result_str.str());
463 }
464};
465
466TEST_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
476TEST_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
524TEST_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
552TEST_F(DWARFASTParserClangTests, TestDefaultTemplateParamParsing) {
553 // Tests parsing DW_AT_default_value for template parameters.
554 auto BufferOrError = llvm::MemoryBuffer::getFile(
555 Filename: GetInputFilePath(name: "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>(args: "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(Elt: ast_parser.ParseTypeFromDWARF(sc, die, type_is_new_ptr: &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: type_sp->GetFullCompilerType());
596 if (decl->getName() == "bar" || decl->getName() == "baz") {
597 check_decl(decl);
598 }
599 }
600}
601
602TEST_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
614FileHeader:
615 Class: ELFCLASS64
616 Data: ELFDATA2LSB
617 Type: ET_EXEC
618 Machine: EM_AARCH64
619DWARF:
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>(args: "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(attr: 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, die: decl_die, type_is_new_ptr: &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, die: def_die, type_is_new_ptr: &new_type);
740 ASSERT_NE(reparsed_type_sp, nullptr);
741
742 ASSERT_EQ(type_sp, reparsed_type_sp);
743}
744
745TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
746 // This tests the behaviour of DWARFASTParserClang
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
754FileHeader:
755 Class: ELFCLASS64
756 Data: ELFDATA2LSB
757 Type: ET_EXEC
758 Machine: EM_AARCH64
759DWARF:
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>(args: "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 {
893 auto decl_die = context_die.GetFirstChild();
894 ASSERT_TRUE(decl_die.IsValid());
895 ASSERT_EQ(decl_die.Tag(), DW_TAG_subprogram);
896 ASSERT_TRUE(decl_die.GetAttributeValueAsOptionalUnsigned(DW_AT_external));
897
898 auto param_die = decl_die.GetFirstChild();
899 ASSERT_TRUE(param_die.IsValid());
900
901 EXPECT_EQ(param_die, ast_parser.GetObjectParameter(decl_die, context_die));
902 }
903
904 {
905 auto subprogram_definition = context_die.GetSibling();
906 ASSERT_TRUE(subprogram_definition.IsValid());
907 ASSERT_EQ(subprogram_definition.Tag(), DW_TAG_subprogram);
908 ASSERT_FALSE(subprogram_definition.GetAttributeValueAsOptionalUnsigned(
909 DW_AT_external));
910
911 auto param_die = subprogram_definition.GetFirstChild();
912 ASSERT_TRUE(param_die.IsValid());
913
914 EXPECT_EQ(param_die, ast_parser.GetObjectParameter(subprogram_definition,
915 context_die));
916 }
917}
918
919TEST_F(DWARFASTParserClangTests,
920 TestObjectPointer_NoSpecificationOnDefinition) {
921 // This tests the behaviour of DWARFASTParserClang
922 // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
923 // but no DW_AT_specification that would link back to its declaration.
924 // This is how Objective-C class method definitions are emitted.
925
926 const char *yamldata = R"(
927--- !ELF
928FileHeader:
929 Class: ELFCLASS64
930 Data: ELFDATA2LSB
931 Type: ET_EXEC
932 Machine: EM_AARCH64
933DWARF:
934 debug_str:
935 - Context
936 - func
937 - this
938 debug_abbrev:
939 - ID: 0
940 Table:
941 - Code: 0x1
942 Tag: DW_TAG_compile_unit
943 Children: DW_CHILDREN_yes
944 Attributes:
945 - Attribute: DW_AT_language
946 Form: DW_FORM_data2
947 - Code: 0x2
948 Tag: DW_TAG_structure_type
949 Children: DW_CHILDREN_yes
950 Attributes:
951 - Attribute: DW_AT_name
952 Form: DW_FORM_strp
953 - Code: 0x3
954 Tag: DW_TAG_subprogram
955 Children: DW_CHILDREN_yes
956 Attributes:
957 - Attribute: DW_AT_name
958 Form: DW_FORM_strp
959 - Attribute: DW_AT_declaration
960 Form: DW_FORM_flag_present
961 - Attribute: DW_AT_object_pointer
962 Form: DW_FORM_ref4
963 - Attribute: DW_AT_artificial
964 Form: DW_FORM_flag_present
965 - Attribute: DW_AT_external
966 Form: DW_FORM_flag_present
967 - Code: 0x4
968 Tag: DW_TAG_formal_parameter
969 Children: DW_CHILDREN_no
970 Attributes:
971 - Attribute: DW_AT_artificial
972 Form: DW_FORM_flag_present
973 - Code: 0x5
974 Tag: DW_TAG_subprogram
975 Children: DW_CHILDREN_yes
976 Attributes:
977 - Attribute: DW_AT_object_pointer
978 Form: DW_FORM_ref4
979 - Code: 0x6
980 Tag: DW_TAG_formal_parameter
981 Children: DW_CHILDREN_no
982 Attributes:
983 - Attribute: DW_AT_name
984 Form: DW_FORM_strp
985 - Attribute: DW_AT_artificial
986 Form: DW_FORM_flag_present
987 debug_info:
988 - Version: 5
989 UnitType: DW_UT_compile
990 AddrSize: 8
991 Entries:
992
993# DW_TAG_compile_unit
994# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
995
996 - AbbrCode: 0x1
997 Values:
998 - Value: 0x04
999
1000# DW_TAG_structure_type
1001# DW_AT_name [DW_FORM_strp] ("Context")
1002
1003 - AbbrCode: 0x2
1004 Values:
1005 - Value: 0x0
1006
1007# DW_TAG_subprogram
1008# DW_AT_name [DW_FORM_strp] ("func")
1009# DW_AT_object_pointer [DW_FORM_ref4]
1010 - AbbrCode: 0x3
1011 Values:
1012 - Value: 0x8
1013 - Value: 0x1
1014 - Value: 0x1d
1015 - Value: 0x1
1016 - Value: 0x1
1017
1018# DW_TAG_formal_parameter
1019# DW_AT_artificial
1020 - AbbrCode: 0x4
1021 Values:
1022 - Value: 0x1
1023
1024 - AbbrCode: 0x0
1025 - AbbrCode: 0x0
1026
1027# DW_TAG_subprogram
1028# DW_AT_object_pointer [DW_FORM_ref4] ("this")
1029 - AbbrCode: 0x5
1030 Values:
1031 - Value: 0x25
1032
1033# DW_TAG_formal_parameter
1034# DW_AT_name [DW_FORM_strp] ("this")
1035# DW_AT_artificial
1036 - AbbrCode: 0x6
1037 Values:
1038 - Value: 0xd
1039 - Value: 0x1
1040
1041 - AbbrCode: 0x0
1042 - AbbrCode: 0x0
1043...
1044)";
1045 YAMLModuleTester t(yamldata);
1046
1047 DWARFUnit *unit = t.GetDwarfUnit();
1048 ASSERT_NE(unit, nullptr);
1049 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1050 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1051 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1052 DWARFDIE cu_die(unit, cu_entry);
1053
1054 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>(args: "ast");
1055 auto &ast_ctx = *holder->GetAST();
1056 DWARFASTParserClangStub ast_parser(ast_ctx);
1057
1058 auto context_die = cu_die.GetFirstChild();
1059 ASSERT_TRUE(context_die.IsValid());
1060 ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
1061
1062 auto subprogram_definition = context_die.GetSibling();
1063 ASSERT_TRUE(subprogram_definition.IsValid());
1064 ASSERT_EQ(subprogram_definition.Tag(), DW_TAG_subprogram);
1065 ASSERT_FALSE(subprogram_definition.GetAttributeValueAsOptionalUnsigned(
1066 DW_AT_external));
1067 ASSERT_FALSE(
1068 subprogram_definition.GetAttributeValueAsReferenceDIE(DW_AT_specification)
1069 .IsValid());
1070
1071 auto param_die = subprogram_definition.GetFirstChild();
1072 ASSERT_TRUE(param_die.IsValid());
1073 EXPECT_EQ(param_die,
1074 ast_parser.GetObjectParameter(subprogram_definition, {}));
1075}
1076
1077TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
1078 // Tests parsing of a C++ non-static member function with an explicit object
1079 // parameter that isn't called "this" and is not a pointer (but a CV-qualified
1080 // rvalue reference instead).
1081
1082 const char *yamldata = R"(
1083--- !ELF
1084FileHeader:
1085 Class: ELFCLASS64
1086 Data: ELFDATA2LSB
1087 Type: ET_EXEC
1088 Machine: EM_AARCH64
1089DWARF:
1090 debug_str:
1091 - Context
1092 - func
1093 - mySelf
1094 debug_abbrev:
1095 - ID: 0
1096 Table:
1097 - Code: 0x1
1098 Tag: DW_TAG_compile_unit
1099 Children: DW_CHILDREN_yes
1100 Attributes:
1101 - Attribute: DW_AT_language
1102 Form: DW_FORM_data2
1103 - Code: 0x2
1104 Tag: DW_TAG_structure_type
1105 Children: DW_CHILDREN_yes
1106 Attributes:
1107 - Attribute: DW_AT_name
1108 Form: DW_FORM_strp
1109 - Code: 0x3
1110 Tag: DW_TAG_subprogram
1111 Children: DW_CHILDREN_yes
1112 Attributes:
1113 - Attribute: DW_AT_name
1114 Form: DW_FORM_strp
1115 - Attribute: DW_AT_declaration
1116 Form: DW_FORM_flag_present
1117 - Attribute: DW_AT_object_pointer
1118 Form: DW_FORM_ref4
1119 - Attribute: DW_AT_external
1120 Form: DW_FORM_flag_present
1121 - Code: 0x4
1122 Tag: DW_TAG_formal_parameter
1123 Children: DW_CHILDREN_no
1124 Attributes:
1125 - Attribute: DW_AT_name
1126 Form: DW_FORM_strp
1127 - Attribute: DW_AT_type
1128 Form: DW_FORM_ref4
1129 - Code: 0x5
1130 Tag: DW_TAG_rvalue_reference_type
1131 Children: DW_CHILDREN_no
1132 Attributes:
1133 - Attribute: DW_AT_type
1134 Form: DW_FORM_ref4
1135 - Code: 0x6
1136 Tag: DW_TAG_const_type
1137 Children: DW_CHILDREN_no
1138 Attributes:
1139 - Attribute: DW_AT_type
1140 Form: DW_FORM_ref4
1141 - Code: 0x7
1142 Tag: DW_TAG_volatile_type
1143 Children: DW_CHILDREN_no
1144 Attributes:
1145 - Attribute: DW_AT_type
1146 Form: DW_FORM_ref4
1147 debug_info:
1148 - Version: 5
1149 UnitType: DW_UT_compile
1150 AddrSize: 8
1151 Entries:
1152
1153# DW_TAG_compile_unit
1154# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
1155
1156 - AbbrCode: 0x1
1157 Values:
1158 - Value: 0x04
1159
1160# DW_TAG_structure_type
1161# DW_AT_name [DW_FORM_strp] ("Context")
1162
1163 - AbbrCode: 0x2
1164 Values:
1165 - Value: 0x0
1166
1167# DW_TAG_subprogram
1168# DW_AT_name [DW_FORM_strp] ("func")
1169# DW_AT_object_pointer [DW_FORM_ref4]
1170 - AbbrCode: 0x3
1171 Values:
1172 - Value: 0x8
1173 - Value: 0x1
1174 - Value: 0x1d
1175 - Value: 0x1
1176
1177# DW_TAG_formal_parameter
1178# DW_AT_name [DW_FORM_strp] ("mySelf")
1179# DW_AT_type [DW_FORM_ref4] (const volatile Context &&)
1180 - AbbrCode: 0x4
1181 Values:
1182 - Value: 0xd
1183 - Value: 0x28
1184
1185 - AbbrCode: 0x0
1186 - AbbrCode: 0x0
1187
1188# DW_TAG_rvalue_reference_type
1189# DW_AT_type [DW_FORM_ref4] ("const volatile Context")
1190
1191 - AbbrCode: 0x5
1192 Values:
1193 - Value: 0x2d
1194
1195# DW_TAG_const_type
1196# DW_AT_type [DW_FORM_ref4] ("volatile Context")
1197
1198 - AbbrCode: 0x6
1199 Values:
1200 - Value: 0x32
1201
1202# DW_TAG_volatile_type
1203# DW_AT_type [DW_FORM_ref4] ("Context")
1204
1205 - AbbrCode: 0x7
1206 Values:
1207 - Value: 0xf
1208
1209 - AbbrCode: 0x0
1210...
1211)";
1212 YAMLModuleTester t(yamldata);
1213
1214 DWARFUnit *unit = t.GetDwarfUnit();
1215 ASSERT_NE(unit, nullptr);
1216 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1217 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1218 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1219 DWARFDIE cu_die(unit, cu_entry);
1220
1221 auto ts_or_err =
1222 cu_die.GetDWARF()->GetTypeSystemForLanguage(language: eLanguageTypeC_plus_plus);
1223 ASSERT_TRUE(static_cast<bool>(ts_or_err));
1224 llvm::consumeError(Err: ts_or_err.takeError());
1225 auto *parser =
1226 static_cast<DWARFASTParserClang *>((*ts_or_err)->GetDWARFParser());
1227
1228 auto context_die = cu_die.GetFirstChild();
1229 ASSERT_TRUE(context_die.IsValid());
1230 ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
1231
1232 SymbolContext sc;
1233 bool new_type;
1234 auto context_type_sp = parser->ParseTypeFromDWARF(sc, die: context_die, type_is_new_ptr: &new_type);
1235 ASSERT_NE(context_type_sp, nullptr);
1236
1237 ASSERT_TRUE(
1238 parser->CompleteTypeFromDWARF(context_die, context_type_sp.get(),
1239 context_type_sp->GetForwardCompilerType()));
1240
1241 auto *record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(
1242 Val: ClangUtil::GetAsTagDecl(type: context_type_sp->GetForwardCompilerType()));
1243 ASSERT_NE(record_decl, nullptr);
1244
1245 auto method_it = record_decl->method_begin();
1246 ASSERT_NE(method_it, record_decl->method_end());
1247
1248 // Check that we didn't parse the function as static.
1249 EXPECT_FALSE(method_it->isStatic());
1250
1251 // Check that method qualifiers were correctly set.
1252 EXPECT_EQ(method_it->getMethodQualifiers(),
1253 clang::Qualifiers::fromCVRMask(clang::Qualifiers::Const |
1254 clang::Qualifiers::Volatile));
1255}
1256
1257TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ParameterCreation) {
1258 // Tests parsing of a C++ free function will create clang::ParmVarDecls with
1259 // the correct clang::DeclContext.
1260 //
1261 // Also ensures we attach names to the ParmVarDecls (even when DWARF contains
1262 // a mix of named/unnamed parameters).
1263
1264 const char *yamldata = R"(
1265--- !ELF
1266FileHeader:
1267 Class: ELFCLASS64
1268 Data: ELFDATA2LSB
1269 Type: ET_EXEC
1270 Machine: EM_AARCH64
1271DWARF:
1272 debug_str:
1273 - func
1274 - int
1275 - short
1276 - namedParam
1277 debug_abbrev:
1278 - ID: 0
1279 Table:
1280 - Code: 0x1
1281 Tag: DW_TAG_compile_unit
1282 Children: DW_CHILDREN_yes
1283 Attributes:
1284 - Attribute: DW_AT_language
1285 Form: DW_FORM_data2
1286 - Code: 0x2
1287 Tag: DW_TAG_structure_type
1288 Children: DW_CHILDREN_yes
1289 Attributes:
1290 - Attribute: DW_AT_name
1291 Form: DW_FORM_strp
1292 - Code: 0x3
1293 Tag: DW_TAG_subprogram
1294 Children: DW_CHILDREN_yes
1295 Attributes:
1296 - Attribute: DW_AT_name
1297 Form: DW_FORM_strp
1298 - Attribute: DW_AT_declaration
1299 Form: DW_FORM_flag_present
1300 - Attribute: DW_AT_external
1301 Form: DW_FORM_flag_present
1302 - Code: 0x4
1303 Tag: DW_TAG_formal_parameter
1304 Children: DW_CHILDREN_no
1305 Attributes:
1306 - Attribute: DW_AT_type
1307 Form: DW_FORM_ref4
1308 - Code: 0x5
1309 Tag: DW_TAG_formal_parameter
1310 Children: DW_CHILDREN_no
1311 Attributes:
1312 - Attribute: DW_AT_type
1313 Form: DW_FORM_ref4
1314 - Attribute: DW_AT_name
1315 Form: DW_FORM_strp
1316 - Code: 0x6
1317 Tag: DW_TAG_base_type
1318 Children: DW_CHILDREN_no
1319 Attributes:
1320 - Attribute: DW_AT_name
1321 Form: DW_FORM_strp
1322 - Attribute: DW_AT_encoding
1323 Form: DW_FORM_data1
1324 - Attribute: DW_AT_byte_size
1325 Form: DW_FORM_data1
1326 debug_info:
1327 - Version: 5
1328 UnitType: DW_UT_compile
1329 AddrSize: 8
1330 Entries:
1331
1332# DW_TAG_compile_unit
1333# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
1334
1335 - AbbrCode: 0x1
1336 Values:
1337 - Value: 0x04
1338
1339# DW_TAG_subprogram
1340# DW_AT_name [DW_FORM_strp] ("func")
1341 - AbbrCode: 0x3
1342 Values:
1343 - Value: 0x0
1344 - Value: 0x1
1345 - Value: 0x1
1346
1347# DW_TAG_formal_parameter
1348# DW_AT_type [DW_FORM_ref4] (int)
1349 - AbbrCode: 0x4
1350 Values:
1351 - Value: 0x23
1352
1353# DW_TAG_formal_parameter
1354# DW_AT_type [DW_FORM_ref4] (short)
1355# DW_AT_name [DW_FORM_strp] ("namedParam")
1356 - AbbrCode: 0x5
1357 Values:
1358 - Value: 0x2a
1359 - Value: 0xf
1360
1361 - AbbrCode: 0x0
1362
1363# DW_TAG_base_type
1364# DW_AT_name [DW_FORM_strp] ("int")
1365# DW_AT_encoding [DW_FORM_data1]
1366# DW_AT_byte_size [DW_FORM_data1]
1367
1368 - AbbrCode: 0x6
1369 Values:
1370 - Value: 0x0000000000000005
1371 - Value: 0x0000000000000005 # DW_ATE_signed
1372 - Value: 0x0000000000000004
1373
1374# DW_TAG_base_type
1375# DW_AT_name [DW_FORM_strp] ("short")
1376# DW_AT_encoding [DW_FORM_data1]
1377# DW_AT_byte_size [DW_FORM_data1]
1378
1379 - AbbrCode: 0x6
1380 Values:
1381 - Value: 0x0000000000000009
1382 - Value: 0x0000000000000005 # DW_ATE_signed
1383 - Value: 0x0000000000000004
1384
1385 - AbbrCode: 0x0
1386...
1387)";
1388 YAMLModuleTester t(yamldata);
1389
1390 DWARFUnit *unit = t.GetDwarfUnit();
1391 ASSERT_NE(unit, nullptr);
1392 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1393 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1394 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1395 DWARFDIE cu_die(unit, cu_entry);
1396
1397 auto ts_or_err =
1398 cu_die.GetDWARF()->GetTypeSystemForLanguage(language: eLanguageTypeC_plus_plus);
1399 ASSERT_TRUE(static_cast<bool>(ts_or_err));
1400 llvm::consumeError(Err: ts_or_err.takeError());
1401
1402 auto *ts = static_cast<TypeSystemClang *>(ts_or_err->get());
1403 auto *parser = static_cast<DWARFASTParserClang *>(ts->GetDWARFParser());
1404
1405 auto subprogram = cu_die.GetFirstChild();
1406 ASSERT_TRUE(subprogram.IsValid());
1407 ASSERT_EQ(subprogram.Tag(), DW_TAG_subprogram);
1408
1409 SymbolContext sc;
1410 bool new_type;
1411 auto type_sp = parser->ParseTypeFromDWARF(sc, die: subprogram, type_is_new_ptr: &new_type);
1412 ASSERT_NE(type_sp, nullptr);
1413
1414 auto result = ts->GetTranslationUnitDecl()->lookup(
1415 Name: clang_utils::getDeclarationName(ast&: *ts, name: "func"));
1416 ASSERT_TRUE(result.isSingleResult());
1417
1418 auto const *func = llvm::cast<clang::FunctionDecl>(Val: result.front());
1419
1420 EXPECT_EQ(func->getNumParams(), 2U);
1421 EXPECT_EQ(func->getParamDecl(0)->getDeclContext(), func);
1422 EXPECT_TRUE(func->getParamDecl(0)->getName().empty());
1423 EXPECT_EQ(func->getParamDecl(1)->getDeclContext(), func);
1424 EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam");
1425}
1426
1427TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
1428 // This tests the behaviour of DWARFASTParserClang
1429 // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
1430 // that encodes a constant index (instead of a DIE reference).
1431
1432 const char *yamldata = R"(
1433--- !ELF
1434FileHeader:
1435 Class: ELFCLASS64
1436 Data: ELFDATA2LSB
1437 Type: ET_EXEC
1438 Machine: EM_AARCH64
1439DWARF:
1440 debug_str:
1441 - Context
1442 - func
1443 - this
1444 - self
1445 - arg
1446 debug_abbrev:
1447 - ID: 0
1448 Table:
1449 - Code: 0x1
1450 Tag: DW_TAG_compile_unit
1451 Children: DW_CHILDREN_yes
1452 Attributes:
1453 - Attribute: DW_AT_language
1454 Form: DW_FORM_data2
1455 - Code: 0x2
1456 Tag: DW_TAG_structure_type
1457 Children: DW_CHILDREN_yes
1458 Attributes:
1459 - Attribute: DW_AT_name
1460 Form: DW_FORM_strp
1461 - Code: 0x3
1462 Tag: DW_TAG_subprogram
1463 Children: DW_CHILDREN_yes
1464 Attributes:
1465 - Attribute: DW_AT_name
1466 Form: DW_FORM_strp
1467 - Attribute: DW_AT_declaration
1468 Form: DW_FORM_flag_present
1469 - Attribute: DW_AT_object_pointer
1470 Form: DW_FORM_implicit_const
1471 Value: 1
1472 - Attribute: DW_AT_external
1473 Form: DW_FORM_flag_present
1474 - Code: 0x4
1475 Tag: DW_TAG_subprogram
1476 Children: DW_CHILDREN_yes
1477 Attributes:
1478 - Attribute: DW_AT_name
1479 Form: DW_FORM_strp
1480 - Attribute: DW_AT_declaration
1481 Form: DW_FORM_flag_present
1482 - Attribute: DW_AT_object_pointer
1483 Form: DW_FORM_implicit_const
1484 Value: 0
1485 - Attribute: DW_AT_external
1486 Form: DW_FORM_flag_present
1487
1488 - Code: 0x5
1489 Tag: DW_TAG_formal_parameter
1490 Children: DW_CHILDREN_no
1491 Attributes:
1492 - Attribute: DW_AT_name
1493 Form: DW_FORM_strp
1494
1495 - Code: 0x6
1496 Tag: DW_TAG_formal_parameter
1497 Children: DW_CHILDREN_no
1498 Attributes:
1499 - Attribute: DW_AT_name
1500 Form: DW_FORM_strp
1501 - Attribute: DW_AT_artificial
1502 Form: DW_FORM_flag_present
1503
1504 debug_info:
1505 - Version: 5
1506 UnitType: DW_UT_compile
1507 AddrSize: 8
1508 Entries:
1509
1510# DW_TAG_compile_unit
1511# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
1512
1513 - AbbrCode: 0x1
1514 Values:
1515 - Value: 0x04
1516
1517# DW_TAG_structure_type
1518# DW_AT_name [DW_FORM_strp] ("Context")
1519
1520 - AbbrCode: 0x2
1521 Values:
1522 - Value: 0x0
1523
1524# DW_TAG_subprogram
1525# DW_AT_name [DW_FORM_strp] ("func")
1526# DW_AT_object_pointer [DW_FORM_implicit_const] (1)
1527 - AbbrCode: 0x3
1528 Values:
1529 - Value: 0x8
1530 - Value: 0x1
1531 - Value: 0x1
1532 - Value: 0x1
1533
1534# DW_TAG_formal_parameter
1535# DW_AT_name [DW_FORM_strp] ("arg")
1536 - AbbrCode: 0x5
1537 Values:
1538 - Value: 0x17
1539
1540# DW_TAG_formal_parameter
1541# DW_AT_name [DW_FORM_strp] ("self")
1542# DW_AT_artificial
1543 - AbbrCode: 0x6
1544 Values:
1545 - Value: 0x12
1546 - Value: 0x1
1547
1548 - AbbrCode: 0x0
1549
1550# DW_TAG_subprogram
1551# DW_AT_object_pointer [DW_FORM_implicit_const] (0)
1552# DW_AT_name [DW_FORM_strp] ("func")
1553 - AbbrCode: 0x4
1554 Values:
1555 - Value: 0x8
1556 - Value: 0x1
1557 - Value: 0x1
1558 - Value: 0x1
1559
1560# DW_TAG_formal_parameter
1561# DW_AT_name [DW_FORM_strp] ("this")
1562# DW_AT_artificial
1563 - AbbrCode: 0x6
1564 Values:
1565 - Value: 0xd
1566 - Value: 0x1
1567
1568# DW_TAG_formal_parameter
1569# DW_AT_name [DW_FORM_strp] ("arg")
1570 - AbbrCode: 0x5
1571 Values:
1572 - Value: 0x17
1573
1574 - AbbrCode: 0x0
1575 - AbbrCode: 0x0
1576...
1577)";
1578
1579 YAMLModuleTester t(yamldata);
1580
1581 DWARFUnit *unit = t.GetDwarfUnit();
1582 ASSERT_NE(unit, nullptr);
1583 const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1584 ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1585 ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1586 DWARFDIE cu_die(unit, cu_entry);
1587
1588 auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>(args: "ast");
1589 auto &ast_ctx = *holder->GetAST();
1590 DWARFASTParserClangStub ast_parser(ast_ctx);
1591
1592 auto context_die = cu_die.GetFirstChild();
1593 ASSERT_TRUE(context_die.IsValid());
1594 ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
1595
1596 auto sub1 = context_die.GetFirstChild();
1597 ASSERT_TRUE(sub1.IsValid());
1598 ASSERT_EQ(sub1.Tag(), DW_TAG_subprogram);
1599
1600 auto sub2 = sub1.GetSibling();
1601 ASSERT_TRUE(sub2.IsValid());
1602 ASSERT_EQ(sub2.Tag(), DW_TAG_subprogram);
1603
1604 // Object parameter is at constant index 1
1605 {
1606 auto param_die = sub1.GetFirstChild().GetSibling();
1607 ASSERT_TRUE(param_die.IsValid());
1608
1609 EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub1, context_die));
1610 }
1611
1612 // Object parameter is at constant index 0
1613 {
1614 auto param_die = sub2.GetFirstChild();
1615 ASSERT_TRUE(param_die.IsValid());
1616
1617 EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub2, context_die));
1618 }
1619}
1620

source code of lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp