@@ -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+
9191078TEST_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