[llvm] r312274 - [dsymutil] Don't mark forward declarations as canonical.

Jonas Devlieghere via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 31 13:22:31 PDT 2017


Author: jdevlieghere
Date: Thu Aug 31 13:22:31 2017
New Revision: 312274

URL: http://llvm.org/viewvc/llvm-project?rev=312274&view=rev
Log:
[dsymutil] Don't mark forward declarations as canonical.

This patch completes the work done by Frederic Riss to addresses
dsymutil incorrectly considering forward declaration as canonical during
uniquing. This resulted in references to the forward declaration even
after the definition was encountered.

In addition to the test provided by Alexander Shaposhnikov in D29609, I
added another test to cover several scenarios that were mentioned in his
conversation with Fred. We now also check that uniquing still occurs
after the definition was encountered.

For more context please refer to D29609

Differential revision: https://reviews.llvm.org/D37127

Added:
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/1.o
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/2.o
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/3.o
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/1.o
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/2.o
    llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/3.o
    llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration.cpp
    llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration2.cpp
Modified:
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/1.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/1.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/1.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/1.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/2.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/2.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/2.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/2.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/3.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/3.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/3.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration/3.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/1.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/1.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/1.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/1.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/2.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/2.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/2.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/2.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/3.o
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/3.o?rev=312274&view=auto
==============================================================================
Binary files llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/3.o (added) and llvm/trunk/test/tools/dsymutil/Inputs/odr-fwd-declaration2/3.o Thu Aug 31 13:22:31 2017 differ

Added: llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration.cpp?rev=312274&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration.cpp (added)
+++ llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration.cpp Thu Aug 31 13:22:31 2017
@@ -0,0 +1,127 @@
+/* Compile with:
+   for FILE in `seq 3`; do
+     clang -g -c  X86/odr-fwd-declaration.cpp -DFILE$FILE -o Inputs/odr-fwd-declaration/$FILE.o
+   done
+ */
+
+// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-fwd-declaration -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+#ifdef FILE1
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source1.cpp" 2
+void foo() {
+  Sptrptr ptr1 = 0;
+}
+
+// First we confirm that the typedefs reference the forward declaration of the
+// struct S.
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr1"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF1:[a-f0-9]*]]
+//
+// CHECK: [[TYPEDEF1]]:{{.*}}TAG_typedef
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR1:[a-f0-9]*]]
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "Sptrptr"
+//
+// CHECK: [[PTR1]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF2:[a-f0-9]*]]
+//
+// CHECK: [[TYPEDEF2]]:{{.*}}TAG_typedef
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR2:[a-f0-9]*]]
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "Sptr"
+//
+// CHECK: [[PTR2]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[FWDSTRUCT:[a-f0-9]*]]
+//
+// CHECK: [[FWDSTRUCT]]:{{.*}}TAG_structure_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "S"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_declaration
+// CHECK-NOT AT_byte_size
+
+#elif defined(FILE2)
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source2.cpp" 2
+struct S {
+  int field;
+};
+void bar() {
+  Sptrptr ptr2 = 0;
+}
+
+// Next we confirm that the typedefs reference the definition rather than the
+// previous declaration of S.
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr2"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF3:[a-f0-9]*]]
+//
+// CHECK: [[TYPEDEF3]]:{{.*}}TAG_typedef
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR3:[a-f0-9]*]]
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "Sptrptr"
+//
+// CHECK: [[PTR3]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF4:[a-f0-9]*]]
+//
+// CHECK: [[TYPEDEF4]]:{{.*}}TAG_typedef
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR4:[a-f0-9]*]]
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "Sptr"
+//
+// CHECK: [[PTR4]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT:[a-f0-9]*]]
+//
+// CHECK: [[STRUCT]]:{{.*}}TAG_structure_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "S"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK-NOT: AT_declaration
+// CHECK: AT_byte_size
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: TAG_member
+
+#elif defined(FILE3)
+# 1 "Header.h" 1
+typedef struct S *Sptr;
+typedef Sptr *Sptrptr;
+# 3 "Source1.cpp" 2
+void foo() {
+  Sptrptr ptr1 = 0;
+}
+
+// Finally we confirm that uniquing is not broken and the same typedef is
+// referenced by ptr1.
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr1"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[TYPEDEF3]]
+// CHECK-NOT: TAG_typedef
+// CHECK-NOT: TAG_pointer
+// CHECK-NOT: TAG_structure_type
+
+#else
+#error "You must define which file you generate"
+#endif

Added: llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration2.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration2.cpp?rev=312274&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration2.cpp (added)
+++ llvm/trunk/test/tools/dsymutil/X86/odr-fwd-declaration2.cpp Thu Aug 31 13:22:31 2017
@@ -0,0 +1,151 @@
+/* Compile with:
+   for FILE in `seq 3`; do
+     clang -g -c  X86/odr-fwd-declaration2.cpp -DFILE$FILE -o Inputs/odr-fwd-declaration2/$FILE.o
+   done
+ */
+
+// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/odr-fwd-declaration2 -y %p/dummy-debug-map.map -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+#ifdef FILE1
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source1.cpp" 2
+void foo() {
+  A *ptr1 = 0;
+}
+
+// First we confirm that bPtr, bRef and bPtrToField reference the forward
+// declaration of the struct B.
+//
+// CHECK: DW_TAG_member
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "bPtr"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR1:[a-f0-9]*]]
+//
+// CHECK: [[STRUCT1:[a-f0-9]*]]:{{.*}}TAG_structure_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "B"
+// CHECK-NOT: AT_byte_size
+// CHECK: DW_AT_declaration
+//
+// CHECK: DW_TAG_member
+// CHECK: AT_name{{.*}} "bRef"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[REF1:[a-f0-9]*]]
+//
+// CHECK: TAG_member
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "bPtrToField"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER1:[a-f0-9]*]]
+//
+// CHECK: [[PTR1]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]]
+//
+// CHECK: [[REF1]]:{{.*}}TAG_reference_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT1]]
+//
+// CHECK: [[PTRTOMEMBER1]]:{{.*}}TAG_ptr_to_member_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT1]]
+
+#elif defined(FILE2)
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source2.cpp" 2
+struct A::B {
+  int x;
+};
+void bar() {
+  A *ptr2 = 0;
+}
+
+// Next we confirm that bPtr, bRef and bPtrToField reference the definition of
+// B, rather than its declaration.
+//
+// CHECK: [[STRUCTA:[a-f0-9]*]]:{{.*}}TAG_structure_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "A"
+// CHECK-NOT: AT_byte_size
+// CHECK: DW_AT_byte_size
+//
+// CHECK: DW_TAG_member
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "bPtr"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR2:[a-f0-9]*]]
+//
+// CHECK: [[STRUCT2:[a-f0-9]*]]:{{.*}}TAG_structure_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "B"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: DW_AT_byte_size
+//
+// CHECK: DW_TAG_member
+// CHECK: AT_name{{.*}} "bRef"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[REF2:[a-f0-9]*]]
+//
+// CHECK: TAG_member
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "bPtrToField"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTRTOMEMBER2:[a-f0-9]*]]
+//
+// CHECK: [[PTR2]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]]
+//
+// CHECK: [[REF2]]:{{.*}}TAG_reference_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCT2]]
+//
+// CHECK: [[PTRTOMEMBER2]]:{{.*}}TAG_ptr_to_member_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_containing_type{{.*}}0x{{0*}}[[STRUCT2:[a-f0-9]*]]
+
+#elif defined(FILE3)
+# 1 "Header.h" 1
+struct A {
+  struct B;
+  B *bPtr;
+  B &bRef;
+  int B::*bPtrToField;
+};
+# 3 "Source2.cpp" 2
+struct A::B {
+  int x;
+};
+void bar() {
+  A *ptr2 = 0;
+}
+
+// Finally we confirm that uniquing isn't broken by checking that further
+// references to 'struct A' point to its now complete definition.
+//
+// CHECK: TAG_variable
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_name{{.*}} "ptr2"
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[PTR3:[a-f0-9]*]]
+//
+// CHECK: [[PTR3]]:{{.*}}TAG_pointer_type
+// CHECK-NOT: {{DW_TAG|NULL}}
+// CHECK: AT_type{{.*}}0x{{0*}}[[STRUCTA]]
+
+#else
+#error "You must define which file you generate"
+#endif

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=312274&r1=312273&r2=312274&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Thu Aug 31 13:22:31 2017
@@ -185,13 +185,14 @@ class CompileUnit {
 public:
   /// Information gathered about a DIE in the object file.
   struct DIEInfo {
-    int64_t AddrAdjust; ///< Address offset to apply to the described entity.
-    DeclContext *Ctxt;  ///< ODR Declaration context.
-    DIE *Clone;         ///< Cloned version of that DIE.
-    uint32_t ParentIdx; ///< The index of this DIE's parent.
-    bool Keep : 1;      ///< Is the DIE part of the linked output?
-    bool InDebugMap : 1;///< Was this DIE's entity found in the map?
-    bool Prune : 1;     ///< Is this a pure forward declaration we can strip?
+    int64_t AddrAdjust;  ///< Address offset to apply to the described entity.
+    DeclContext *Ctxt;   ///< ODR Declaration context.
+    DIE *Clone;          ///< Cloned version of that DIE.
+    uint32_t ParentIdx;  ///< The index of this DIE's parent.
+    bool Keep : 1;       ///< Is the DIE part of the linked output?
+    bool InDebugMap : 1; ///< Was this DIE's entity found in the map?
+    bool Prune : 1;      ///< Is this a pure forward declaration we can strip?
+    bool Incomplete : 1; ///< Does DIE transitively refer an incomplete decl?
   };
 
   CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR,
@@ -1198,8 +1199,9 @@ private:
   /// @{
   /// Recursively walk the \p DIE tree and look for DIEs to
   /// keep. Store that information in \p CU's DIEInfo.
-  void lookForDIEsToKeep(RelocationManager &RelocMgr,
-                         const DWARFDie &DIE,
+  ///
+  /// The return value indicates whether the DIE is incomplete.
+  bool lookForDIEsToKeep(RelocationManager &RelocMgr, const DWARFDie &DIE,
                          const DebugMapObject &DMO, CompileUnit &CU,
                          unsigned Flags);
 
@@ -2196,6 +2198,11 @@ void DwarfLinker::keepDIEAndDependencies
   DWARFUnit &Unit = CU.getOrigUnit();
   MyInfo.Keep = true;
 
+  // We're looking for incomplete types.
+  MyInfo.Incomplete = Die.getTag() != dwarf::DW_TAG_subprogram &&
+                      Die.getTag() != dwarf::DW_TAG_member &&
+                      dwarf::toUnsigned(Die.find(dwarf::DW_AT_declaration), 0);
+
   // First mark all the parent chain as kept.
   unsigned AncestorIdx = MyInfo.ParentIdx;
   while (!CU.getInfo(AncestorIdx).Keep) {
@@ -2211,7 +2218,7 @@ void DwarfLinker::keepDIEAndDependencies
   const auto *Abbrev = Die.getAbbreviationDeclarationPtr();
   uint32_t Offset = Die.getOffset() + getULEB128Size(Abbrev->getCode());
 
-  // Mark all DIEs referenced through atttributes as kept.
+  // Mark all DIEs referenced through attributes as kept.
   for (const auto &AttrSpec : Abbrev->attributes()) {
     DWARFFormValue Val(AttrSpec.Form);
 
@@ -2251,6 +2258,16 @@ void DwarfLinker::keepDIEAndDependencies
       unsigned ODRFlag = UseODR ? TF_ODR : 0;
       lookForDIEsToKeep(RelocMgr, RefDie, DMO, *ReferencedCU,
                         TF_Keep | TF_DependencyWalk | ODRFlag);
+
+      // The incomplete property is propagated if the current DIE is complete
+      // but references an incomplete DIE.
+      if (Info.Incomplete && !MyInfo.Incomplete &&
+          (Die.getTag() == dwarf::DW_TAG_typedef ||
+           Die.getTag() == dwarf::DW_TAG_member ||
+           Die.getTag() == dwarf::DW_TAG_reference_type ||
+           Die.getTag() == dwarf::DW_TAG_ptr_to_member_type ||
+           Die.getTag() == dwarf::DW_TAG_pointer_type))
+        MyInfo.Incomplete = true;
     }
   }
 }
@@ -2267,7 +2284,9 @@ void DwarfLinker::keepDIEAndDependencies
 /// also called, but during these dependency walks the file order is
 /// not respected. The TF_DependencyWalk flag tells us which kind of
 /// traversal we are currently doing.
-void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
+///
+/// The return value indicates whether the DIE is incomplete.
+bool DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
                                     const DWARFDie &Die,
                                     const DebugMapObject &DMO, CompileUnit &CU,
                                     unsigned Flags) {
@@ -2275,13 +2294,13 @@ void DwarfLinker::lookForDIEsToKeep(Relo
   CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx);
   bool AlreadyKept = MyInfo.Keep;
   if (MyInfo.Prune)
-    return;
+    return true;
 
   // If the Keep flag is set, we are marking a required DIE's
   // dependencies. If our target is already marked as kept, we're all
   // set.
   if ((Flags & TF_DependencyWalk) && AlreadyKept)
-    return;
+    return MyInfo.Incomplete;
 
   // We must not call shouldKeepDIE while called from keepDIEAndDependencies,
   // because it would screw up the relocation finding logic.
@@ -2303,10 +2322,19 @@ void DwarfLinker::lookForDIEsToKeep(Relo
     Flags &= ~TF_ParentWalk;
 
   if (!Die.hasChildren() || (Flags & TF_ParentWalk))
-    return;
+    return MyInfo.Incomplete;
 
-  for (auto Child: Die.children())
-    lookForDIEsToKeep(RelocMgr, Child, DMO, CU, Flags);
+  bool Incomplete = false;
+  for (auto Child : Die.children()) {
+    Incomplete |= lookForDIEsToKeep(RelocMgr, Child, DMO, CU, Flags);
+
+    // If any of the members are incomplete we propagate the incompleteness.
+    if (!MyInfo.Incomplete && Incomplete &&
+        (Die.getTag() == dwarf::DW_TAG_structure_type ||
+         Die.getTag() == dwarf::DW_TAG_class_type))
+      MyInfo.Incomplete = true;
+  }
+  return MyInfo.Incomplete;
 }
 
 /// Assign an abbreviation numer to \p Abbrev.
@@ -2716,7 +2744,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
 
   assert(Die->getTag() == InputDIE.getTag());
   Die->setOffset(OutOffset);
-  if ((Unit.hasODR() || Unit.isClangModule()) &&
+  if ((Unit.hasODR() || Unit.isClangModule()) && !Info.Incomplete &&
       Die->getTag() != dwarf::DW_TAG_namespace && Info.Ctxt &&
       Info.Ctxt != Unit.getInfo(Info.ParentIdx).Ctxt &&
       !Info.Ctxt->getCanonicalDIEOffset()) {




More information about the llvm-commits mailing list