diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-11-13 21:04:32 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-11-13 21:04:32 +0000 |
commit | 4e55a39528c30036da819bdf22a485a9d10f94b2 (patch) | |
tree | 5984652bd92b5b512b5029b2254b987961bc499d /gcc/dwarf2out.c | |
parent | 96bda40f8f639fe66dc1b84659578e575f4140d5 (diff) | |
download | gcc-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.c | 71 |
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)); |