===================================================================
@@ -0,0 +1,55 @@
+// { dg-do compile }
+// { dg-options "--std=c++11 -dA -gdwarf-4 -fdebug-types-section -fno-merge-debug-strings" }
+
+// Check that -fdebug-types-sections does not copy a full referenced type
+// into a type unit.
+
+// Checks that at least one type unit is generated.
+//
+// { dg-final { scan-assembler "DIE \\(\[^\n\]*\\) DW_TAG_type_unit" } }
+//
+// Check that func is declared exactly twice in the debug info:
+// once in the type unit for struct D, and once in the compile unit.
+//
+// { dg-final { scan-assembler-times "\\.ascii \"func\\\\0\"\[^\n\]*DW_AT_name" 2 } }
+//
+// Check to make sure that no type unit contains a DIE with DW_AT_low_pc
+// or DW_AT_ranges. These patterns assume that the compile unit is always
+// emitted after all type units.
+//
+// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_low_pc.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } }
+// { dg-final { scan-assembler-not "\\.quad\[^\n\]*DW_AT_ranges.*DIE \\(\[^\n\]*\\) DW_TAG_compile_unit" } }
+
+struct A {
+ A();
+ virtual ~A();
+ virtual void foo();
+ private:
+ int data;
+};
+
+struct B {
+ B();
+ virtual ~B();
+};
+
+extern B* table[];
+
+struct D {
+ template <typename T>
+ T* get(int i)
+ {
+ B*& cell = table[i];
+ if (cell == 0)
+ cell = new T();
+ return static_cast<T*>(cell);
+ }
+};
+
+void func(D* d)
+{
+ struct C : B {
+ A a;
+ };
+ d->get<C>(0)->a.foo();
+}
===================================================================
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-gdwarf-4" } */
+/* { dg-options "-gdwarf-4 -fdebug-types-section" } */
/* Regression test for an ICE in output_die when using -gdwarf-4. */
===================================================================
@@ -6383,6 +6383,7 @@ clone_as_declaration (dw_die_ref die)
switch (a->dw_attr)
{
+ case DW_AT_abstract_origin:
case DW_AT_artificial:
case DW_AT_containing_type:
case DW_AT_external:
@@ -6515,6 +6516,12 @@ generate_skeleton_bottom_up (skeleton_ch
dw_die_ref clone = clone_die (c);
move_all_children (c, clone);
+ /* If the original has a DW_AT_object_pointer attribute,
+ it would now point to a child DIE just moved to the
+ cloned tree, so we need to remove that attribute from
+ the original. */
+ remove_AT (c, DW_AT_object_pointer);
+
replace_child (c, clone, prev);
generate_skeleton_ancestor_tree (parent);
add_child_die (parent->new_die, c);
@@ -6742,32 +6749,6 @@ copy_ancestor_tree (dw_die_ref unit, dw_
return copy;
}
-/* Like clone_tree, but additionally enter all the children into
- the hash table decl_table. */
-
-static dw_die_ref
-clone_tree_hash (dw_die_ref die, htab_t decl_table)
-{
- dw_die_ref c;
- dw_die_ref clone = clone_die (die);
- struct decl_table_entry *entry;
- void **slot = htab_find_slot_with_hash (decl_table, die,
- htab_hash_pointer (die), INSERT);
- /* Assert that DIE isn't in the hash table yet. If it would be there
- before, the ancestors would be necessarily there as well, therefore
- clone_tree_hash wouldn't be called. */
- gcc_assert (*slot == HTAB_EMPTY_ENTRY);
- entry = XCNEW (struct decl_table_entry);
- entry->orig = die;
- entry->copy = clone;
- *slot = entry;
-
- FOR_EACH_CHILD (die, c,
- add_child_die (clone, clone_tree_hash (c, decl_table)));
-
- return clone;
-}
-
/* Walk the DIE and its children, looking for references to incomplete
or trivial types that are unmarked (i.e., that are not in the current
type_unit). */
@@ -6814,10 +6795,6 @@ copy_decls_walk (dw_die_ref unit, dw_die
entry->copy = copy;
*slot = entry;
- FOR_EACH_CHILD (targ, c,
- add_child_die (copy,
- clone_tree_hash (c, decl_table)));
-
/* Make sure the cloned tree is marked as part of the
type unit. */
mark_dies (copy);