summaryrefslogtreecommitdiff
path: root/gcc/dwarf2out.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-13 21:04:32 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-13 21:04:32 +0000
commit4e55a39528c30036da819bdf22a485a9d10f94b2 (patch)
tree5984652bd92b5b512b5029b2254b987961bc499d /gcc/dwarf2out.c
parent96bda40f8f639fe66dc1b84659578e575f4140d5 (diff)
downloadgcc-4e55a39528c30036da819bdf22a485a9d10f94b2.tar.gz
PR c++/27017
* dwarf2out.c (prune_unused_types_walk_local_classes): New function. (prune_unused_types_walk): Call it for non-perennial local classes. Set die_mark to 2 if recursing on children. If die_mark is 1 on entry, just set it to 2 and recurse on children, don't walk attributes again. * g++.dg/debug/dwarf2/localclass1.C: New test. * g++.dg/debug/dwarf2/localclass2.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141829 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/dwarf2out.c')
-rw-r--r--gcc/dwarf2out.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 614871ed917..337c22e119c 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -16248,6 +16248,37 @@ prune_unused_types_mark (dw_die_ref die, int dokids)
}
}
+/* For local classes, look if any static member functions were emitted
+ and if so, mark them. */
+
+static void
+prune_unused_types_walk_local_classes (dw_die_ref die)
+{
+ dw_die_ref c;
+
+ if (die->die_mark == 2)
+ return;
+
+ switch (die->die_tag)
+ {
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ break;
+
+ case DW_TAG_subprogram:
+ if (!get_AT_flag (die, DW_AT_declaration)
+ || die->die_definition != NULL)
+ prune_unused_types_mark (die, 1);
+ return;
+
+ default:
+ return;
+ }
+
+ /* Mark children. */
+ FOR_EACH_CHILD (die, c, prune_unused_types_walk_local_classes (c));
+}
/* Walk the tree DIE and mark types that we actually use. */
@@ -16256,12 +16287,34 @@ prune_unused_types_walk (dw_die_ref die)
{
dw_die_ref c;
- /* Don't do anything if this node is already marked. */
- if (die->die_mark)
+ /* Don't do anything if this node is already marked and
+ children have been marked as well. */
+ if (die->die_mark == 2)
return;
switch (die->die_tag)
{
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_class_type:
+ if (die->die_perennial_p)
+ break;
+
+ for (c = die->die_parent; c; c = c->die_parent)
+ if (c->die_tag == DW_TAG_subprogram)
+ break;
+
+ /* Finding used static member functions inside of classes
+ is needed just for local classes, because for other classes
+ static member function DIEs with DW_AT_specification
+ are emitted outside of the DW_TAG_*_type. If we ever change
+ it, we'd need to call this even for non-local classes. */
+ if (c)
+ prune_unused_types_walk_local_classes (die);
+
+ /* It's a type node --- don't mark it. */
+ return;
+
case DW_TAG_const_type:
case DW_TAG_packed_type:
case DW_TAG_pointer_type:
@@ -16269,9 +16322,6 @@ prune_unused_types_walk (dw_die_ref die)
case DW_TAG_volatile_type:
case DW_TAG_typedef:
case DW_TAG_array_type:
- case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_friend:
case DW_TAG_variant_part:
@@ -16293,10 +16343,15 @@ prune_unused_types_walk (dw_die_ref die)
break;
}
- die->die_mark = 1;
+ if (die->die_mark == 0)
+ {
+ die->die_mark = 1;
+
+ /* Now, mark any dies referenced from here. */
+ prune_unused_types_walk_attribs (die);
+ }
- /* Now, mark any dies referenced from here. */
- prune_unused_types_walk_attribs (die);
+ die->die_mark = 2;
/* Mark children. */
FOR_EACH_CHILD (die, c, prune_unused_types_walk (c));