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, 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
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 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
906TEST_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
913FileHeader:
914 Class: ELFCLASS64
915 Data: ELFDATA2LSB
916 Type: ET_EXEC
917 Machine: EM_AARCH64
918DWARF:
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(language: eLanguageTypeC_plus_plus);
1052 ASSERT_TRUE(static_cast<bool>(ts_or_err));
1053 llvm::consumeError(Err: 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, die: context_die, type_is_new_ptr: &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 Val: ClangUtil::GetAsTagDecl(type: 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
1086TEST_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
1095FileHeader:
1096 Class: ELFCLASS64
1097 Data: ELFDATA2LSB
1098 Type: ET_EXEC
1099 Machine: EM_AARCH64
1100DWARF:
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(language: eLanguageTypeC_plus_plus);
1228 ASSERT_TRUE(static_cast<bool>(ts_or_err));
1229 llvm::consumeError(Err: 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, die: subprogram, type_is_new_ptr: &new_type);
1241 ASSERT_NE(type_sp, nullptr);
1242
1243 auto result = ts->GetTranslationUnitDecl()->lookup(
1244 clang_utils::getDeclarationName(ast&: *ts, name: "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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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