Broken debug info with G++ anon struct typedefs

Ulrich Weigand
Thu Mar 15 19:41:00 GMT 2007


in debugging a failing GDB test case I've come upon what looks like bad
DWARF-2 debug info being generated by G++.

The problem has to do with typedefs of anonymous structs like:

typedef struct {
  int one;
  int two;
} tagless_struct;
tagless_struct v_tagless;

This causes the following DWARF-2 to be generated:

        .uleb128 0x2     # (DIE (0x6c) DW_TAG_structure_type)
        .ascii "<anonymous struct>\0"    # DW_AT_name
        .byte   0x8      # DW_AT_byte_size
        .byte   0x1      # DW_AT_decl_file (xxx.ii)
        .byte   0x1      # DW_AT_decl_line
        .4byte  0xa4     # DW_AT_sibling
        .uleb128 0x3     # (DIE (0x87) DW_TAG_member)
        .ascii "one\0"   # DW_AT_name
        .byte   0x1      # DW_AT_decl_file (xxx.ii)
        .byte   0x2      # DW_AT_decl_line
        .4byte  0xa4     # DW_AT_type
        .byte   0x2      # DW_AT_data_member_location
        .byte   0x23     # DW_OP_plus_uconst
        .uleb128 0x0
        .uleb128 0x3     # (DIE (0x95) DW_TAG_member)
        .ascii "two\0"   # DW_AT_name
        .byte   0x1      # DW_AT_decl_file (xxx.ii)
        .byte   0x3      # DW_AT_decl_line
        .4byte  0xa4     # DW_AT_type
        .byte   0x2      # DW_AT_data_member_location
        .byte   0x23     # DW_OP_plus_uconst
        .uleb128 0x4
        .byte   0x0      # end of children of DIE 0x6c

        .uleb128 0x4     # (DIE (0xa4) DW_TAG_base_type)
        .byte   0x4      # DW_AT_byte_size
        .byte   0x5      # DW_AT_encoding
        .ascii "int\0"   # DW_AT_name

        .uleb128 0x5     # (DIE (0xab) DW_TAG_variable)
        .ascii "v_tagless\0"     # DW_AT_name
        .byte   0x1      # DW_AT_decl_file (xxx.ii)
        .byte   0x5      # DW_AT_decl_line
        .4byte  0x6c     # DW_AT_type
        .byte   0x1      # DW_AT_external
        .byte   0x5      # DW_AT_location
        .byte   0x3      # DW_OP_addr
        .4byte  v_tagless

Note how the v_tagless variable records DIE 0x6c as type, which is
the anonymous struct -- the typedef is completely missing.

This is incorrect; we should see "tagless_struct" as type of

The reason for this appears to be the following optimization in
cp/decl.c (grokdeclarator):

      /* If the user declares "typedef struct {...} foo" then the
         struct will have an anonymous name.  Fill that name in now.
         Nothing can refer to it, so nothing needs know about the name
         change.  */
      if (type != error_mark_node
          && unqualified_id
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && TYPE_ANONYMOUS_P (type)
          /* Don't do this if there are attributes.  */
          && (!attrlist || !*attrlist)
          && cp_type_quals (type) == TYPE_UNQUALIFIED)
          tree oldname = TYPE_NAME (type);
          tree t;

          /* Replace the anonymous name with the real name everywhere.  */
          for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
            if (TYPE_NAME (t) == oldname)
              TYPE_NAME (t) = decl;

This attempts to change the <anonymous struct> name to the typedef name.
However, it comes too late.  The original anonymous struct type has already
run through rest_of_type_compilation at this stage, which has already called
dwarf2out_decl on it.  This in turn has already allocated the DIE and set up
the name information.  Changing TYPE_NAME afterwards has no effect on the
debug data any more.

Any suggestions how to fix this?


  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE

More information about the Gcc mailing list