Skip to content

Commit cd5412d

Browse files
committed
fixup! fix objective-c case; add unit-test; adjust test docs
1 parent d70e6d1 commit cd5412d

File tree

2 files changed

+165
-5
lines changed

2 files changed

+165
-5
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,17 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE &subprogram,
167167
subprogram.Tag() == DW_TAG_inlined_subroutine ||
168168
subprogram.Tag() == DW_TAG_subroutine_type);
169169

170-
if (!decl_ctx_die.IsStructUnionOrClass())
171-
return {};
172-
173170
if (DWARFDIE object_parameter =
174171
subprogram.GetAttributeValueAsReferenceDIE(DW_AT_object_pointer))
175172
return object_parameter;
176173

177174
// If no DW_AT_object_pointer was specified, assume the implicit object
178175
// parameter is the first parameter to the function, is called "this" and is
179176
// artificial (which is what most compilers would generate).
177+
178+
if (!decl_ctx_die.IsStructUnionOrClass())
179+
return {};
180+
180181
auto children = subprogram.children();
181182
auto it = llvm::find_if(children, [](const DWARFDIE &child) {
182183
return child.Tag() == DW_TAG_formal_parameter;

lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,8 @@ TEST_F(DWARFASTParserClangTests, TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
742742
ASSERT_EQ(type_sp, reparsed_type_sp);
743743
}
744744

745-
TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointer) {
746-
// This tests the behaviour of ParsedDWARFTypeAttributes
745+
TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
746+
// This tests the behaviour of DWARFASTParserClang
747747
// for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
748748
// *and* a DW_AT_specification that also has a DW_AT_object_pointer.
749749
// We don't want the declaration DW_AT_object_pointer to overwrite the
@@ -916,6 +916,165 @@ TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointer) {
916916
}
917917
}
918918

919+
TEST_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
928+
FileHeader:
929+
Class: ELFCLASS64
930+
Data: ELFDATA2LSB
931+
Type: ET_EXEC
932+
Machine: EM_AARCH64
933+
DWARF:
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+
# DW_AT_specification [DW_FORM_ref4] ("func")
1030+
- AbbrCode: 0x5
1031+
Values:
1032+
- Value: 0x29
1033+
1034+
# DW_TAG_formal_parameter
1035+
# DW_AT_name [DW_FORM_strp] ("this")
1036+
# DW_AT_artificial
1037+
- AbbrCode: 0x6
1038+
Values:
1039+
- Value: 0xd
1040+
- Value: 0x1
1041+
1042+
- AbbrCode: 0x0
1043+
- AbbrCode: 0x0
1044+
...
1045+
)";
1046+
YAMLModuleTester t(yamldata);
1047+
1048+
DWARFUnit *unit = t.GetDwarfUnit();
1049+
ASSERT_NE(unit, nullptr);
1050+
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1051+
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1052+
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1053+
DWARFDIE cu_die(unit, cu_entry);
1054+
1055+
auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
1056+
auto &ast_ctx = *holder->GetAST();
1057+
DWARFASTParserClangStub ast_parser(ast_ctx);
1058+
1059+
auto context_die = cu_die.GetFirstChild();
1060+
ASSERT_TRUE(context_die.IsValid());
1061+
ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
1062+
1063+
auto subprogram_definition = context_die.GetSibling();
1064+
ASSERT_TRUE(subprogram_definition.IsValid());
1065+
ASSERT_EQ(subprogram_definition.Tag(), DW_TAG_subprogram);
1066+
ASSERT_FALSE(subprogram_definition.GetAttributeValueAsOptionalUnsigned(
1067+
DW_AT_external));
1068+
ASSERT_FALSE(
1069+
subprogram_definition.GetAttributeValueAsReferenceDIE(DW_AT_specification)
1070+
.IsValid());
1071+
1072+
auto param_die = subprogram_definition.GetFirstChild();
1073+
ASSERT_TRUE(param_die.IsValid());
1074+
EXPECT_EQ(param_die,
1075+
ast_parser.GetObjectParameter(subprogram_definition, {}));
1076+
}
1077+
9191078
TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
9201079
// Tests parsing of a C++ non-static member function with an explicit object
9211080
// parameter that isn't called "this" and is not a pointer (but a CV-qualified

0 commit comments

Comments
 (0)