OSDN Git Service

[lldb/DWARF] Look for complete array element definitions in other modules
authorPavel Labath <pavel@labath.sk>
Mon, 6 Jul 2020 08:09:13 +0000 (10:09 +0200)
committerPavel Labath <pavel@labath.sk>
Mon, 6 Jul 2020 08:09:13 +0000 (10:09 +0200)
This applies the same logic we have for incomplete class bases and
members to array element types.

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/test/API/functionalities/limit-debug-info/TestLimitDebugInfo.py
lldb/test/API/functionalities/limit-debug-info/main.cpp
lldb/test/API/functionalities/limit-debug-info/one.cpp
lldb/test/API/functionalities/limit-debug-info/onetwo.h
lldb/test/API/functionalities/limit-debug-info/two.cpp

index 0bb69eb..0bd2d0c 100644 (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
index 396861f..9408ad6 100644 (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'"])
index 886b3fe..0a25de1 100644 (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; }
index 6822d84..67609dd 100644 (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