https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87295

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
The odd thing I see is that we have two type DIEs with the same signature
(but different members).


DIE    0: DW_TAG_compile_unit (0x7ffff68960a0)
  abbrev id: 0 offset: 0 mark: 0
  DW_AT_producer: "GNU C++17 9.0.1 20190125 (experimental) [trunk revision
268137] -flto -ffat-lto-objects -fdebug-types-section -g -std=gnu++17"
  DW_AT_language: 4
  DW_AT_name: "t.ii"
  DW_AT_comp_dir: "/abuild/rguenther/trunk2-g/gcc"
    DIE    0: DW_TAG_structure_type (0x7ffff6896820)
      abbrev id: 0 offset: 0 mark: 0
      signature: 2e365acce74a6a1f
      DW_AT_name: "integral_constant<bool, false>"
      DW_AT_signature: die -> signature: 2e365acce74a6a1f (0x7ffff68962d0)
      DW_AT_declaration: 1
        DIE    0: DW_TAG_member (0x7ffff6896320)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_name: "value"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 4
          DW_AT_decl_column: 24
          DW_AT_type: die -> 0 (0x7ffff68963c0)
          DW_AT_external: 1
          DW_AT_declaration: 1
          DW_AT_const_expr: 1
          DW_AT_inline: 1
        DIE    0: DW_TAG_subprogram (0x7ffff68964b0)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_external: 1
          DW_AT_name: "operator integral_constant<bool, false>::value_type"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 6
          DW_AT_decl_column: 13
          DW_AT_linkage_name: "_ZNK17integral_constantIbLb0EEcvbEv"
          DW_AT_type: die -> 0 (0x7ffff6896a00)
          DW_AT_declaration: 1
...
    DIE    0: DW_TAG_structure_type (0x7ffff6896a50)
      abbrev id: 0 offset: 0 mark: 0
      DW_AT_name: "integral_constant<bool, false>"
      DW_AT_signature: die -> signature: 2e365acce74a6a1f (0x7ffff68962d0)
      DW_AT_declaration: 1
        DIE    0: DW_TAG_typedef (0x7ffff6896a00)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_name: "value_type"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 5
          DW_AT_decl_column: 15
          DW_AT_type: die -> 0 (0x7ffff6896aa0)

but the DW_AT_signature of the first one gets somehow mangled.

So the "duplicate" is because originally it looks like

    DIE    0: DW_TAG_structure_type (0x7ffff68962d0)
      abbrev id: 0 offset: 0 mark: 0
      DW_AT_name: "integral_constant<bool, false>"
      DW_AT_byte_size: 1
      DW_AT_decl_file: "t.ii" (0)
      DW_AT_decl_line: 2
      DW_AT_decl_column: 8
        DIE    0: DW_TAG_member (0x7ffff6896320)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_name: "value"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 4
          DW_AT_decl_column: 24
          DW_AT_type: die -> 0 (0x7ffff68963c0)
          DW_AT_external: 1
          DW_AT_declaration: 1
          DW_AT_const_expr: 1
          DW_AT_inline: 1
        DIE    0: DW_TAG_typedef (0x7ffff6896460)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_name: "value_type"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 5
          DW_AT_decl_column: 15
          DW_AT_type: die -> 0 (0x7ffff6896370)
        DIE    0: DW_TAG_subprogram (0x7ffff68964b0)
          abbrev id: 0 offset: 0 mark: 0
          DW_AT_external: 1
          DW_AT_name: "operator integral_constant<bool, false>::value_type"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 6
          DW_AT_decl_column: 13
          DW_AT_type: die -> 0 (0x7ffff6896460)
          DW_AT_declaration: 1
          DW_AT_object_pointer: die -> 0 (0x7ffff6896500)
            DIE    0: DW_TAG_formal_parameter (0x7ffff6896500)
              abbrev id: 0 offset: 0 mark: 0
              DW_AT_type: die -> 0 (0x7ffff6896550)
              DW_AT_artificial: 1

and we duplicate this out to

    DIE    0: DW_TAG_structure_type (0x7ffff6896820)
      abbrev id: 0 offset: 0 mark: 1
      signature: 2e365acce74a6a1f
      DW_AT_name: "integral_constant<bool, false>"
      DW_AT_signature: die -> signature: 2e365acce74a6a1f (0x7ffff68962d0)
      DW_AT_declaration: 1
        DIE    0: DW_TAG_member (0x7ffff6896320)
          abbrev id: 0 offset: 0 mark: 1
          DW_AT_name: "value"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 4
          DW_AT_decl_column: 24
          DW_AT_type: die -> 0 (0x7ffff68963c0)
          DW_AT_external: 1
          DW_AT_declaration: 1
          DW_AT_const_expr: 1
          DW_AT_inline: 1
        DIE    0: DW_TAG_subprogram (0x7ffff68964b0)
          abbrev id: 0 offset: 0 mark: 1
          DW_AT_external: 1
          DW_AT_name: "operator integral_constant<bool, false>::value_type"
          DW_AT_decl_file: "t.ii" (0)
          DW_AT_decl_line: 6
          DW_AT_decl_column: 13
          DW_AT_linkage_name: "_ZNK17integral_constantIbLb0EEcvbEv"
          DW_AT_type: die -> 0 (0x7ffff6896460)
          DW_AT_declaration: 1

but now we have a reference in the DW_TAG_subprogram DIE to the
(non-copied, original DIE for the typedef).

The early output makes the first DW_AT_signature ref refer to the
second internal one which looks weird and is what output_external_refs
barfs on.  This happens via

#0  change_AT_die_ref (ref=0x7ffff69f14c8, 
    new_die=<dw_die_ref 0x7ffff6896a50 DW_TAG_structure_type
<parent=0x7ffff68960a0 DW_TAG_compile_unit>>)
    at /space/rguenther/src/svn/trunk2/gcc/dwarf2out.c:4794
#1  0x0000000000e1e5a3 in build_abbrev_table (
    die=<dw_die_ref 0x7ffff6896820 DW_TAG_structure_type <parent=0x7ffff68960a0
DW_TAG_compile_unit>>, extern_map=0x3373980)
    at /space/rguenther/src/svn/trunk2/gcc/dwarf2out.c:9032
#2  0x0000000000e1e7e4 in build_abbrev_table (
    die=<dw_die_ref 0x7ffff68960a0 DW_TAG_compile_unit>, extern_map=0x3373980)
    at /space/rguenther/src/svn/trunk2/gcc/dwarf2out.c:9081
#3  0x0000000000e22ea9 in output_comp_unit (
    die=<dw_die_ref 0x7ffff68960a0 DW_TAG_compile_unit>, output_if_empty=1, 
    dwo_id=0x0) at /space/rguenther/src/svn/trunk2/gcc/dwarf2out.c:10998
#4  0x0000000000e5d52b in dwarf2out_early_finish (
    filename=0x7fffffffe28b "t.ii")
    at /space/rguenther/src/svn/trunk2/gcc/dwarf2out.c:32167

it's an odd place to do this "optimization", it also leaves DIEs in
broken state.  We can either change DW_AT_signature to DW_AT_specification
(well, not really - both DIEs are DW_AT_declaration DIEs...) or fixup
the second round of optimize_external_refs to not see "local"
DW_AT_signature as external.

Thus,

Index: dwarf2out.c
===================================================================
--- dwarf2out.c (revision 268260)
+++ dwarf2out.c (working copy)
@@ -8911,7 +8911,11 @@ optimize_external_refs_1 (dw_die_ref die
   struct external_ref *ref_p;

   if (is_type_die (die)
-      && (c = get_AT_ref (die, DW_AT_signature)))
+      && (c = get_AT_ref (die, DW_AT_signature))
+      /* Make sure to not pick up optimized local refs from the
+         early LTO run of build_abbrev_table which performs the
+        actual redirection.  */
+      && c->comdat_type_p)
     {
       /* This is a local skeleton; use it for local references.  */
       ref_p = lookup_external_ref (map, c);

ideally we'd run local ref optimization on _types_ just once...

When I compare the FAT debug info part with non-LTO debug info I see
the single type unit of the testcase output twice here (because we lack
LTO copies of .debug_types, similar to PR88878).

Reply via email to