Hi!

Apparently gdb (and not very unlikely other consumers) weren't able to
handle arbitrary location descriptions in DW_AT_data_member_location,
and my recent optimization to try to optimize e.g. DW_OP_plus_uconst
into equivalent, but shorter sequence of more operations apparently
doesn't work there.  While GDB is being fixed (or has it been already?),
this affects just -gdwarf-2 and there it could be considered a fixed idiom.

We should IMHO change the default DWARF level to -gdwarf-3 at least for now,
except for targets with broken tools (that aren't able to cope properly even
with DWARF 2, like Apple).  DWARF 3 has been released more than 5 years
ago...

So, the following patch just disables the size optimization when
DW_AT_data_member_location -gdwarf-2 only op is DW_OP_plus_uconst.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2011-07-27  Jakub Jelinek  <ja...@redhat.com>

        * dwarf2out.c (resolve_addr): For -gdwarf-2 don't
        optimize DW_AT_data_member_location containing just
        DW_OP_plus_uconst.

--- gcc/dwarf2out.c.jj  2011-07-27 18:55:11.000000000 +0200
+++ gcc/dwarf2out.c     2011-07-27 20:53:55.000000000 +0200
@@ -21808,13 +21808,26 @@ resolve_addr (dw_die_ref die)
          }
        break;
       case dw_val_class_loc:
-       if (!resolve_addr_in_expr (AT_loc (a)))
-         {
-           remove_AT (die, a->dw_attr);
-           ix--;
-         }
-       else
-         mark_base_types (AT_loc (a));
+       {
+         dw_loc_descr_ref l = AT_loc (a);
+         /* For -gdwarf-2 don't attempt to optimize
+            DW_AT_data_member_location containing
+            DW_OP_plus_uconst - older consumers might
+            rely on it being that op instead of a more complex,
+            but shorter, location description.  */
+         if ((dwarf_version > 2
+              || a->dw_attr != DW_AT_data_member_location
+              || l == NULL
+              || l->dw_loc_opc != DW_OP_plus_uconst
+              || l->dw_loc_next != NULL)
+             && !resolve_addr_in_expr (l))
+           {
+             remove_AT (die, a->dw_attr);
+             ix--;
+           }
+         else
+           mark_base_types (l);
+       }
        break;
       case dw_val_class_addr:
        if (a->dw_attr == DW_AT_const_value


        Jakub

Reply via email to