-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[lldb][DWARF] Fix adding children to clang type that hasn't started definition. #93839
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
Conversation
…t_type in UniqueDWARFASTTypeList.
@llvm/pr-subscribers-lldb Author: Zequan Wu (ZequanWu) ChangesThis fixes #92328 (comment). This contains two fixes:
Full diff: https://github.com/llvm/llvm-project/pull/93839.diff 2 Files Affected:
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index e0b1b430b266f..78969d4752f80 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2232,6 +2232,11 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
// For objective C we don't start the definition when the class is
// created.
TypeSystemClang::StartTagDeclarationDefinition(clang_type);
+ } else if (!clang_type.IsBeingDefined()) {
+ // In case of some weired DWARF causing we don't start definition on this
+ // definition DIE because we failed to find existing clang_type from
+ // UniqueDWARFASTTypeMap due to overstrict checking.
+ TypeSystemClang::StartTagDeclarationDefinition(clang_type);
}
AccessType default_accessibility = eAccessNone;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 4762356034cab..3d201e96f92c3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -13,12 +13,18 @@
using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;
+static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) {
+ return Tag == llvm::dwarf::Tag::DW_TAG_class_type ||
+ Tag == llvm::dwarf::Tag::DW_TAG_structure_type;
+}
+
UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
const DWARFDIE &die, const lldb_private::Declaration &decl,
const int32_t byte_size, bool is_forward_declaration) {
for (UniqueDWARFASTType &udt : m_collection) {
// Make sure the tags match
- if (udt.m_die.Tag() == die.Tag()) {
+ if (udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
+ IsStructOrClassTag(die.Tag()))) {
// If they are not both definition DIEs or both declaration DIEs, then
// don't check for byte size and declaration location, because declaration
// DIEs usually don't have those info.
@@ -39,7 +45,9 @@ UniqueDWARFASTType *UniqueDWARFASTTypeList::Find(
while (!done && match && parent_arg_die && parent_pos_die) {
const dw_tag_t parent_arg_tag = parent_arg_die.Tag();
const dw_tag_t parent_pos_tag = parent_pos_die.Tag();
- if (parent_arg_tag == parent_pos_tag) {
+ if (parent_arg_tag == parent_pos_tag ||
+ (IsStructOrClassTag(parent_arg_tag) &&
+ IsStructOrClassTag(parent_pos_tag))) {
switch (parent_arg_tag) {
case DW_TAG_class_type:
case DW_TAG_structure_type:
|
@@ -13,12 +13,18 @@ | |||
using namespace lldb_private::dwarf; | |||
using namespace lldb_private::plugin::dwarf; | |||
|
|||
static bool IsStructOrClassTag(llvm::dwarf::Tag Tag) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have this function somewhere already. Might be worth checking (possibly even in the llvm headers?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes in SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext
we have the same kind of check. Maybe one could consolidate those in one API? But might not be worth the churn, so feel free to ignore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's here:
bool IsStructOrClassTag(llvm::dwarf::Tag Tag) { |
lldb_private::plugin::dwarf
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there more tag equality checks around LLDB that could benefit from re-using the following check:
udt.m_die.Tag() == die.Tag() || (IsStructOrClassTag(udt.m_die.Tag()) &&
IsStructOrClassTag(die.Tag()))
There's at least two now. Not sure where we'd put such an API. Perhaps @felipepiovezan or @adrian-prantl have some input on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we can probably do it in a different change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also
/// Returns true if `tag` is a class_type of structure_type tag.
static bool IsClassOrStruct(dw_tag_t tag) {
return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
}
In AppleDWARFIndex
FYI
And it uses that for the same type of check:
return tag == expected_tag ||
(IsClassOrStruct(tag) && IsClassOrStruct(expected_tag));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, we definitely need to clean all of these up.
There might be one inside llvm/ too..
// In case of some weired DWARF causing we don't start definition on this | ||
// definition DIE because we failed to find existing clang_type from | ||
// UniqueDWARFASTTypeMap due to overstrict checking. | ||
TypeSystemClang::StartTagDeclarationDefinition(clang_type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm in the crashing test case the DWARF itself seems reasonable right? So the comment is a bit misleading.
I like the idea of doing both TypeSystemClang::StartTagDeclarationDefinition
and TypeSystemClang::CompleteTagDeclarationDefinition
in CompleteRecordType
(in fact that's what we're trying to do in https://discourse.llvm.org/t/rfc-lldb-more-reliable-completion-of-record-types/77442#changes-5), but I'd like to understand how we get here after #92328 but not prior. Let me re-read your comment on said PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the DWARF is reasonable. I added this just in case of UniqueDWARFASTTypeMap
failing to find the existing type again for some other reasons in the future... This checks doesn't get trigger for the test you reported before. Maybe it's not necessary, because the following loop also just check for the fully qualified names: https://github.com/llvm/llvm-project/blob/main/lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp#L39-L71.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah i see, I'd prefer not to add this then if it's going to be an untested codepath. Perhaps it's worth making this an lldbassert
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
…rClang::CompleteRecordType.
Update assertion message. Co-authored-by: Michael Buch <[email protected]>
You can test this locally with the following command:git-clang-format --diff 16a5fd3fdb91ffb39b97dbd3a7e9346ba406360d e7fc16ec5f31693191188b3b95728c4320465923 -- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp View the diff from clang-format here.diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 74bc5ac93a..dc4cfc96b8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2233,9 +2233,9 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
// created.
TypeSystemClang::StartTagDeclarationDefinition(clang_type);
} else {
- assert(
- clang_type.IsBeingDefined() &&
- "Trying to complete a definition without a prior call to StartTagDeclarationDefinition.");
+ assert(clang_type.IsBeingDefined() &&
+ "Trying to complete a definition without a prior call to "
+ "StartTagDeclarationDefinition.");
}
AccessType default_accessibility = eAccessNone;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets do the cleanup of IsClassOrStruct
as a follow-up since there seem quite a few places that could benefit from it
…ng when parsing declaration DIEs. (#98361) Summary: This is a reapply of #92328 and #93839. It now passes the [test](de3f1b6), which crashes with the original reverted changes. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251550
This fixes #92328 (comment) by not differentiating
DW_TAG_class_type
andDW_TAG_structure_type
inUniqueDWARFASTTypeList
, because it's possible that DIE for a type isDW_TAG_class_type
in one CU but isDW_TAG_structure_type
in a different CU.