Skip to content

[lldb][DWARFASTParserClang] Make C++ method parsing aware of explicit object parameters #124096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,9 @@ GetCXXObjectParameter(const DWARFDIE &subprogram,
if (!DeclKindIsCXXClass(containing_decl_ctx.getDeclKind()))
return {};

// FIXME: if subprogram has a explicit DW_AT_object_pointer, use it.
if (DWARFDIE object_parameter =
subprogram.GetAttributeValueAsReferenceDIE(DW_AT_object_pointer))
return object_parameter;

// If no DW_AT_object_pointer was specified, assume the implicit object
// parameter is the first parameter to the function, is called "this" and is
Expand Down Expand Up @@ -215,11 +217,6 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram,
return 0;

uint32_t encoding_mask = this_type->GetEncodingMask();

// FIXME: explicit object parameters need not to be pointers
if (!(encoding_mask & (1u << Type::eEncodingIsPointerUID)))
return 0;

unsigned cv_quals = 0;
if (encoding_mask & (1u << Type::eEncodingIsConstUID))
cv_quals |= clang::Qualifiers::Const;
Expand Down
178 changes: 178 additions & 0 deletions lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -902,3 +902,181 @@ TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointer) {
EXPECT_TRUE(attrs.object_pointer.IsValid());
EXPECT_EQ(attrs.object_pointer, param_die);
}

TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
// Tests parsing of a C++ non-static member function with an explicit object
// parameter that isn't called "this" and is not a pointer (but a CV-qualified
// rvalue reference instead).

const char *yamldata = R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_AARCH64
DWARF:
debug_str:
- Context
- func
- mySelf
debug_abbrev:
- ID: 0
Table:
- Code: 0x1
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Code: 0x2
Tag: DW_TAG_structure_type
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Code: 0x3
Tag: DW_TAG_subprogram
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_declaration
Form: DW_FORM_flag_present
- Attribute: DW_AT_object_pointer
Form: DW_FORM_ref4
- Attribute: DW_AT_external
Form: DW_FORM_flag_present
- Code: 0x4
Tag: DW_TAG_formal_parameter
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_type
Form: DW_FORM_ref4
- Code: 0x5
Tag: DW_TAG_rvalue_reference_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_type
Form: DW_FORM_ref4
- Code: 0x6
Tag: DW_TAG_const_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_type
Form: DW_FORM_ref4
- Code: 0x7
Tag: DW_TAG_volatile_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_type
Form: DW_FORM_ref4
debug_info:
- Version: 5
UnitType: DW_UT_compile
AddrSize: 8
Entries:

# DW_TAG_compile_unit
# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)

- AbbrCode: 0x1
Values:
- Value: 0x04

# DW_TAG_structure_type
# DW_AT_name [DW_FORM_strp] ("Context")

- AbbrCode: 0x2
Values:
- Value: 0x0

# DW_TAG_subprogram
# DW_AT_name [DW_FORM_strp] ("func")
# DW_AT_object_pointer [DW_FORM_ref4]
- AbbrCode: 0x3
Values:
- Value: 0x8
- Value: 0x1
- Value: 0x1d
- Value: 0x1

# DW_TAG_formal_parameter
# DW_AT_name [DW_FORM_strp] ("mySelf")
# DW_AT_type [DW_FORM_ref4] (const volatile Context &&)
- AbbrCode: 0x4
Values:
- Value: 0xd
- Value: 0x28

- AbbrCode: 0x0
- AbbrCode: 0x0

# DW_TAG_rvalue_reference_type
# DW_AT_type [DW_FORM_ref4] ("const volatile Context")

- AbbrCode: 0x5
Values:
- Value: 0x2d

# DW_TAG_const_type
# DW_AT_type [DW_FORM_ref4] ("volatile Context")

- AbbrCode: 0x6
Values:
- Value: 0x32

# DW_TAG_volatile_type
# DW_AT_type [DW_FORM_ref4] ("Context")

- AbbrCode: 0x7
Values:
- Value: 0xf

- AbbrCode: 0x0
...
)";
YAMLModuleTester t(yamldata);

DWARFUnit *unit = t.GetDwarfUnit();
ASSERT_NE(unit, nullptr);
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
DWARFDIE cu_die(unit, cu_entry);

auto ts_or_err =
cu_die.GetDWARF()->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
auto *parser =
static_cast<DWARFASTParserClang *>((*ts_or_err)->GetDWARFParser());

auto context_die = cu_die.GetFirstChild();
ASSERT_TRUE(context_die.IsValid());
ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);

SymbolContext sc;
bool new_type;
auto context_type_sp = parser->ParseTypeFromDWARF(sc, context_die, &new_type);
ASSERT_NE(context_type_sp, nullptr);

ASSERT_TRUE(
parser->CompleteTypeFromDWARF(context_die, context_type_sp.get(),
context_type_sp->GetForwardCompilerType()));

auto *record_decl = llvm::dyn_cast_or_null<clang::CXXRecordDecl>(
ClangUtil::GetAsTagDecl(context_type_sp->GetForwardCompilerType()));
ASSERT_NE(record_decl, nullptr);

auto method_it = record_decl->method_begin();
ASSERT_NE(method_it, record_decl->method_end());

// Check that we didn't parse the function as static.
EXPECT_FALSE(method_it->isStatic());

// Check that method qualifiers were correctly set.
EXPECT_EQ(method_it->getMethodQualifiers(),
clang::Qualifiers::fromCVRMask(clang::Qualifiers::Const |
clang::Qualifiers::Volatile));
}
Loading