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"

Reply via email to