https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86413
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2018-07-06 CC| |rguenth at gcc dot gnu.org Assignee|unassigned at gcc dot gnu.org |rguenth at gcc dot gnu.org Target Milestone|--- |9.0 Ever confirmed|0 |1 --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- Hmm, we have <1><101>: Abbrev Number: 5 (DW_TAG_subprogram) <102> DW_AT_external : 1 <102> DW_AT_name : (indirect string, offset: 0x21e): main <106> DW_AT_decl_file : 1 <107> DW_AT_decl_line : 2 <108> DW_AT_decl_column : 5 <109> DW_AT_type : <0xf5> <2><10d>: Abbrev Number: 6 (DW_TAG_variable) <10e> DW_AT_name : i <110> DW_AT_decl_file : 1 <111> DW_AT_decl_line : 4 <112> DW_AT_decl_column : 16 <113> DW_AT_type : <0xfc> <2><117>: Abbrev Number: 7 (DW_TAG_lexical_block) <3><118>: Abbrev Number: 8 (DW_TAG_variable) <119> DW_AT_name : i <11b> DW_AT_decl_file : 1 <11c> DW_AT_decl_line : 7 <11d> DW_AT_decl_column : 18 <11e> DW_AT_type : <0xf5> <122> DW_AT_external : 1 <122> DW_AT_declaration : 1 and <1><153>: Abbrev Number: 3 (DW_TAG_subprogram) <154> DW_AT_abstract_origin: <0x101> <158> DW_AT_low_pc : 0x4003e0 <160> DW_AT_high_pc : 0x30 <168> DW_AT_frame_base : 1 byte block: 9c (DW_OP_call_frame_cfa) <16a> DW_AT_GNU_all_call_sites: 1 <16a> DW_AT_sibling : <0x17c> <2><16e>: Abbrev Number: 4 (DW_TAG_lexical_block) <16f> DW_AT_abstract_origin: <0x117> <2><173>: Abbrev Number: 5 (DW_TAG_variable) <174> DW_AT_abstract_origin: <0x10d> <178> DW_AT_location : 2 byte block: 91 74 (DW_OP_fbreg: -12) <2><17b>: Abbrev Number: 0 <1><17c>: Abbrev Number: 5 (DW_TAG_variable) <17d> DW_AT_abstract_origin: <0xeb> <181> DW_AT_location : 9 byte block: 3 34 10 60 0 0 0 0 0 (DW_OP_addr: 601034) so what seems to be missing is location info for <16e>. Quite possibly this happens because we remove the BLOCK from the block tree given there's nothing left in it. So I think we have to preserve even non-VAR_DECLs like types because without high/low-pc attributes for the BLOCKs gdb cannot handle scoping correctly. Or somehow mark the BLOCKs as to be "used" for scoping. I guess that would then keep most of the BLOCKs live in result ... Hmm, OTOH the live stmt should keep the BLOCK live which in turn should make it get the locations... ah, it's /* Determine if this block directly contains any "significant" local declarations which we will need to output DIEs for. */ if (debug_info_level > DINFO_LEVEL_TERSE) /* We are not in terse mode so *any* local declaration counts as being a "significant" one. */ must_output_die = ((BLOCK_VARS (stmt) != NULL || BLOCK_NUM_NONLOCALIZED_VARS (stmt)) && (TREE_USED (stmt) || TREE_ASM_WRITTEN (stmt) || BLOCK_ABSTRACT (stmt))); where w/o vars we don't even output locations (we created the DIE for the BLOCK already though). That means a similar testcase for non-LTO should be possible as soon as we'd start to run free-lang-data unconditionally. The following fixes the FAIL for me and would allow us to prune unused vars not only from local_decls but also from the BLOCK tree. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index a7c4620cfc3..95232177d83 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -25622,6 +25622,11 @@ gen_block_die (tree stmt, dw_die_ref context_die) /* The outer scopes for inlinings *must* always be represented. We generate DW_TAG_inlined_subroutine DIEs for them. (See below.) */ must_output_die = 1; + else if (BLOCK_DIE (stmt)) + /* If we already have a DIE then it was filled early. Meanwhile + we might have pruned all BLOCK_VARS as optimized out but we + still want to generate high/low PC attributes so output it. */ + must_output_die = 1; else { /* Determine if this block directly contains any "significant"