[lldb/DWARF] Look for complete array element definitions in other modules

This applies the same logic we have for incomplete class bases and
members to array element types.
This commit is contained in:
Pavel Labath 2020-07-06 10:09:13 +02:00
parent 8849831d55
commit b65d4b23f6
6 changed files with 48 additions and 24 deletions

View File

@ -1267,32 +1267,20 @@ TypeSP DWARFASTParserClang::ParseArrayType(const DWARFDIE &die,
if (TypeSystemClang::IsCXXClassType(array_element_type) &&
!array_element_type.GetCompleteType()) {
ModuleSP module_sp = die.GetModule();
if (module_sp) {
if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
"class/union/struct element type DIE 0x%8.8x that is a "
"forward declaration, not a complete definition.\nTry "
"compiling the source file with -fstandalone-debug or "
"disable -gmodules",
die.GetOffset(), type_die.GetOffset());
else
module_sp->ReportError(
"DWARF DW_TAG_array_type DIE at 0x%8.8x has a "
"class/union/struct element type DIE 0x%8.8x that is a "
"forward declaration, not a complete definition.\nPlease "
"file a bug against the compiler and include the "
"preprocessed output for %s",
die.GetOffset(), type_die.GetOffset(), GetUnitName(die).c_str());
}
// We have no choice other than to pretend that the element class
// type is complete. If we don't do this, clang will crash when
// trying to layout the class. Since we provide layout
// assistance, all ivars in this class and other classes will be
// fine, this is the best we can do short of crashing.
// Mark the class as complete, but we make a note of the fact that
// this class is not _really_ complete so we can later search for a
// definition in a different module.
// Since we provide layout assistance, all ivars in this class and other
// classes will be fine even if we are not able to find the definition
// elsewhere.
if (TypeSystemClang::StartTagDeclarationDefinition(array_element_type)) {
TypeSystemClang::CompleteTagDeclarationDefinition(array_element_type);
const auto *td =
TypeSystemClang::GetQualType(array_element_type.GetOpaqueQualType())
.getTypePtr()
->getAsTagDecl();
m_ast.GetMetadata(td)->SetIsForcefullyCompleted();
} else {
module_sp->ReportError("DWARF DIE at 0x%8.8x was not able to "
"start its definition.\nPlease file a "
@ -2741,7 +2729,7 @@ void DWARFASTParserClang::ParseSingleMember(
if (TypeSystemClang::IsCXXClassType(member_clang_type) &&
!member_clang_type.GetCompleteType()) {
// Mark the class as complete, ut we make a note of the fact that
// Mark the class as complete, but we make a note of the fact that
// this class is not _really_ complete so we can later search for a
// definition in a different module.
// Since we provide layout assistance, all ivars in this class and

View File

@ -54,6 +54,10 @@ class LimitDebugInfoTestCase(TestBase):
self.expect_expr("two_as_member.two.one.member", result_value="147")
self.expect_expr("two_as_member.two.member", result_value="247")
self.expect_expr("array_of_one[2].member", result_value="174")
self.expect_expr("array_of_two[2].one[2].member", result_value="174")
self.expect_expr("array_of_two[2].member", result_value="274")
@skipIf(bugnumber="pr46284", debug_info="gmodules")
@skipIfWindows # Clang emits type info even with -flimit-debug-info
def test_two_debug(self):
@ -81,6 +85,12 @@ class LimitDebugInfoTestCase(TestBase):
substrs=["no member named 'member' in 'member::One'"])
self.expect_expr("two_as_member.two.member", result_value="247")
self.expect("expr array_of_one[2].member", error=True,
substrs=["no member named 'member' in 'array::One'"])
self.expect("expr array_of_two[2].one[2].member", error=True,
substrs=["no member named 'member' in 'array::One'"])
self.expect_expr("array_of_two[2].member", result_value="274")
@skipIf(bugnumber="pr46284", debug_info="gmodules")
@skipIfWindows # Clang emits type info even with -flimit-debug-info
def test_one_debug(self):
@ -110,3 +120,9 @@ class LimitDebugInfoTestCase(TestBase):
substrs=["no member named 'one' in 'member::Two'"])
self.expect("expr two_as_member.two.member", error=True,
substrs=["no member named 'member' in 'member::Two'"])
self.expect_expr("array_of_one[2].member", result_value="174")
self.expect("expr array_of_two[2].one[2].member", error=True,
substrs=["no member named 'one' in 'array::Two'"])
self.expect("expr array_of_two[2].member", error=True,
substrs=["no member named 'member' in 'array::Two'"])

View File

@ -22,4 +22,7 @@ struct TwoAsMember {
int member = 47;
} two_as_member;
array::One array_of_one[3];
array::Two array_of_two[3];
int main() { return 0; }

View File

@ -2,3 +2,4 @@
One::~One() = default;
member::One::~One() = default;
array::One::~One() = default;

View File

@ -24,3 +24,18 @@ struct Two {
virtual ~Two();
};
} // namespace member
namespace array {
struct One {
int member = 174;
constexpr One() = default;
virtual ~One();
};
struct Two {
One one[3];
int member = 274;
constexpr Two() = default;
virtual ~Two();
};
} // namespace array

View File

@ -2,3 +2,4 @@
Two::~Two() = default;
member::Two::~Two() = default;
array::Two::~Two() = default;