OSDN Git Service

* 30_threads/thread/native_handle/typesizes.cc: Do not run on cygwin.
[pf3gnuchains/gcc-fork.git] / gcc / dwarf2out.c
index d430753..d6fbce6 100644 (file)
@@ -1,6 +1,6 @@
 /* Output Dwarf2 format symbol table information from GCC.
    Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+   2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
    Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
@@ -98,6 +98,7 @@ along with GCC; see the file COPYING3.  If not see
 
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
 static rtx last_var_location_insn;
+static rtx cached_next_real_insn;
 
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
@@ -1090,6 +1091,7 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
   last_var_location_insn = NULL_RTX;
+  cached_next_real_insn = NULL_RTX;
 
   if (dwarf2out_do_cfi_asm ())
     fprintf (asm_out_file, "\t.cfi_endproc\n");
@@ -1175,7 +1177,8 @@ dwarf2out_switch_text_section (void)
 
   var_location_switch_text_section ();
 
-  set_cur_line_info_table (sect);
+  if (cold_text_section != NULL)
+    set_cur_line_info_table (sect);
 }
 \f
 /* And now, the subset of the debugging information support code necessary
@@ -3300,11 +3303,12 @@ static int should_move_die_to_comdat (dw_die_ref);
 static dw_die_ref clone_as_declaration (dw_die_ref);
 static dw_die_ref clone_die (dw_die_ref);
 static dw_die_ref clone_tree (dw_die_ref);
-static void copy_declaration_context (dw_die_ref, dw_die_ref);
+static dw_die_ref copy_declaration_context (dw_die_ref, dw_die_ref);
 static void generate_skeleton_ancestor_tree (skeleton_chain_node *);
 static void generate_skeleton_bottom_up (skeleton_chain_node *);
 static dw_die_ref generate_skeleton (dw_die_ref);
 static dw_die_ref remove_child_or_replace_with_skeleton (dw_die_ref,
+                                                         dw_die_ref,
                                                          dw_die_ref);
 static void break_out_comdat_types (dw_die_ref);
 static dw_die_ref copy_ancestor_tree (dw_die_ref, dw_die_ref, htab_t);
@@ -7068,16 +7072,18 @@ clone_as_declaration (dw_die_ref die)
   return clone;
 }
 
-/* Copy the declaration context to the new compile unit DIE.  This includes
+/* Copy the declaration context to the new type unit DIE.  This includes
    any surrounding namespace or type declarations.  If the DIE has an
    AT_specification attribute, it also includes attributes and children
-   attached to the specification.  */
+   attached to the specification, and returns a pointer to the original
+   parent of the declaration DIE.  Returns NULL otherwise.  */
 
-static void
+static dw_die_ref
 copy_declaration_context (dw_die_ref unit, dw_die_ref die)
 {
   dw_die_ref decl;
   dw_die_ref new_decl;
+  dw_die_ref orig_parent = NULL;
 
   decl = get_AT_ref (die, DW_AT_specification);
   if (decl == NULL)
@@ -7088,6 +7094,10 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
       dw_die_ref c;
       dw_attr_ref a;
 
+      /* The original DIE will be changed to a declaration, and must
+         be moved to be a child of the original declaration DIE.  */
+      orig_parent = decl->die_parent;
+
       /* Copy the type node pointer from the new DIE to the original
          declaration DIE so we can forward references later.  */
       decl->die_id.die_type_node = die->die_id.die_type_node;
@@ -7116,6 +7126,8 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
           add_AT_specification (die, new_decl);
         }
     }
+
+  return orig_parent;
 }
 
 /* Generate the skeleton ancestor tree for the given NODE, then clone
@@ -7199,17 +7211,23 @@ generate_skeleton (dw_die_ref die)
   return node.new_die;
 }
 
-/* Remove the DIE from its parent, possibly replacing it with a cloned
-   declaration.  The original DIE will be moved to a new compile unit
-   so that existing references to it follow it to the new location.  If
-   any of the original DIE's descendants is a declaration, we need to
-   replace the original DIE with a skeleton tree and move the
-   declarations back into the skeleton tree.  */
+/* Remove the CHILD DIE from its parent, possibly replacing it with a cloned
+   declaration.  The original DIE is moved to a new compile unit so that
+   existing references to it follow it to the new location.  If any of the
+   original DIE's descendants is a declaration, we need to replace the
+   original DIE with a skeleton tree and move the declarations back into the
+   skeleton tree.  */
 
 static dw_die_ref
-remove_child_or_replace_with_skeleton (dw_die_ref child, dw_die_ref prev)
+remove_child_or_replace_with_skeleton (dw_die_ref unit, dw_die_ref child,
+                                      dw_die_ref prev)
 {
-  dw_die_ref skeleton;
+  dw_die_ref skeleton, orig_parent;
+
+  /* Copy the declaration context to the type unit DIE.  If the returned
+     ORIG_PARENT is not NULL, the skeleton needs to be added as a child of
+     that DIE.  */
+  orig_parent = copy_declaration_context (unit, child);
 
   skeleton = generate_skeleton (child);
   if (skeleton == NULL)
@@ -7217,7 +7235,19 @@ remove_child_or_replace_with_skeleton (dw_die_ref child, dw_die_ref prev)
   else
     {
       skeleton->die_id.die_type_node = child->die_id.die_type_node;
-      replace_child (child, skeleton, prev);
+
+      /* If the original DIE was a specification, we need to put
+         the skeleton under the parent DIE of the declaration.
+        This leaves the original declaration in the tree, but
+        it will be pruned later since there are no longer any
+        references to it.  */
+      if (orig_parent != NULL)
+       {
+         remove_child_with_prev (child, prev);
+         add_child_die (orig_parent, skeleton);
+       }
+      else
+       replace_child (child, skeleton, prev);
     }
 
   return skeleton;
@@ -7262,11 +7292,9 @@ break_out_comdat_types (dw_die_ref die)
         generate_type_signature (c, type_node);
 
         /* Copy the declaration context, attributes, and children of the
-           declaration into the new compile unit DIE.  */
-       copy_declaration_context (unit, c);
-
-        /* Remove this DIE from the main CU.  */
-       replacement = remove_child_or_replace_with_skeleton (c, prev);
+           declaration into the new type unit DIE, then remove this DIE
+          from the main CU (or replace it with a skeleton if necessary).  */
+       replacement = remove_child_or_replace_with_skeleton (unit, c, prev);
 
         /* Break out nested types into their own type units.  */
         break_out_comdat_types (c);
@@ -7379,6 +7407,32 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
   return copy;
 }
 
+/* Like clone_tree, but additionally enter all the children into
+   the hash table decl_table.  */
+
+static dw_die_ref
+clone_tree_hash (dw_die_ref die, htab_t decl_table)
+{
+  dw_die_ref c;
+  dw_die_ref clone = clone_die (die);
+  struct decl_table_entry *entry;
+  void **slot = htab_find_slot_with_hash (decl_table, die,
+                                         htab_hash_pointer (die), INSERT);
+  /* Assert that DIE isn't in the hash table yet.  If it would be there
+     before, the ancestors would be necessarily there as well, therefore
+     clone_tree_hash wouldn't be called.  */
+  gcc_assert (*slot == HTAB_EMPTY_ENTRY);
+  entry = XCNEW (struct decl_table_entry);
+  entry->orig = die;
+  entry->copy = clone;
+  *slot = entry;
+
+  FOR_EACH_CHILD (die, c,
+                 add_child_die (clone, clone_tree_hash (c, decl_table)));
+
+  return clone;
+}
+
 /* Walk the DIE and its children, looking for references to incomplete
    or trivial types that are unmarked (i.e., that are not in the current
    type_unit).  */
@@ -7415,7 +7469,11 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, htab_t decl_table)
           else
             {
               dw_die_ref parent = unit;
-              dw_die_ref copy = clone_tree (targ);
+             dw_die_ref copy = clone_die (targ);
+
+             FOR_EACH_CHILD (targ, c,
+                             add_child_die (copy,
+                                            clone_tree_hash (c, decl_table)));
 
               /* Make sure the cloned tree is marked as part of the
                  type unit.  */
@@ -7652,7 +7710,15 @@ size_of_die (dw_die_ref die)
          size += size_of_sleb128 (AT_int (a));
          break;
        case dw_val_class_unsigned_const:
-         size += constant_size (AT_unsigned (a));
+         {
+           int csize = constant_size (AT_unsigned (a));
+           if (dwarf_version == 3
+               && a->dw_attr == DW_AT_data_member_location
+               && csize >= 4)
+             size += size_of_uleb128 (AT_unsigned (a));
+           else
+             size += csize;
+         }
          break;
        case dw_val_class_const_double:
          size += 2 * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
@@ -7953,8 +8019,16 @@ value_format (dw_attr_ref a)
        case 2:
          return DW_FORM_data2;
        case 4:
+         /* In DWARF3 DW_AT_data_member_location with
+            DW_FORM_data4 or DW_FORM_data8 is a loclistptr, not
+            constant, so we need to use DW_FORM_udata if we need
+            a large constant.  */
+         if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+           return DW_FORM_udata;
          return DW_FORM_data4;
        case 8:
+         if (dwarf_version == 3 && a->dw_attr == DW_AT_data_member_location)
+           return DW_FORM_udata;
          return DW_FORM_data8;
        default:
          gcc_unreachable ();
@@ -8148,6 +8222,13 @@ output_loc_list (dw_loc_list_ref list_head)
       /* Don't output an entry that starts and ends at the same address.  */
       if (strcmp (curr->begin, curr->end) == 0 && !curr->force)
        continue;
+      size = size_of_locs (curr->expr);
+      /* If the expression is too large, drop it on the floor.  We could
+        perhaps put it into DW_TAG_dwarf_procedure and refer to that
+        in the expression, but >= 64KB expressions for a single value
+        in a single range are unlikely very useful.  */
+      if (size > 0xffff)
+       continue;
       if (!have_multiple_function_sections)
        {
          dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
@@ -8166,7 +8247,6 @@ output_loc_list (dw_loc_list_ref list_head)
                               "Location list end address (%s)",
                               list_head->ll_symbol);
        }
-      size = size_of_locs (curr->expr);
 
       /* Output the block length for this list of location operations.  */
       gcc_assert (size <= 0xffff);
@@ -8261,8 +8341,15 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_unsigned_const:
-         dw2_asm_output_data (constant_size (AT_unsigned (a)),
-                              AT_unsigned (a), "%s", name);
+         {
+           int csize = constant_size (AT_unsigned (a));
+           if (dwarf_version == 3
+               && a->dw_attr == DW_AT_data_member_location
+               && csize >= 4)
+             dw2_asm_output_data_uleb128 (AT_unsigned (a), "%s", name);
+           else
+             dw2_asm_output_data (csize, AT_unsigned (a), "%s", name);
+         }
          break;
 
        case dw_val_class_const_double:
@@ -9848,7 +9935,14 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
     }
   /* This probably indicates a bug.  */
   else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
-    add_name_attribute (mod_type_die, "__unknown__");
+    {
+      name = TYPE_NAME (type);
+      if (name
+         && TREE_CODE (name) == TYPE_DECL)
+       name = DECL_NAME (name);
+      add_name_attribute (mod_type_die,
+                         name ? IDENTIFIER_POINTER (name) : "__unknown__");
+    }
 
   if (qualified_type)
     equate_type_number_to_die (qualified_type, mod_type_die);
@@ -10620,6 +10714,13 @@ const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
       return 1;
     }
 
+  if (targetm.const_not_ok_for_debug_p (rtl))
+    {
+      expansion_failed (NULL_TREE, rtl,
+                       "Expression rejected for debug by the backend.\n");
+      return 1;
+    }
+
   if (GET_CODE (rtl) != SYMBOL_REF)
     return 0;
 
@@ -11672,12 +11773,22 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       break;
 
     case MEM:
+      {
+       rtx new_rtl = avoid_constant_pool_reference (rtl);
+       if (new_rtl != rtl)
+         {
+           mem_loc_result = mem_loc_descriptor (new_rtl, mode, mem_mode,
+                                                initialized);
+           if (mem_loc_result != NULL)
+             return mem_loc_result;
+         }
+      }
       mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0),
                                           get_address_mode (rtl), mode,
                                           VAR_INIT_STATUS_INITIALIZED);
       if (mem_loc_result == NULL)
        mem_loc_result = tls_mem_loc_descriptor (rtl);
-      if (mem_loc_result != 0)
+      if (mem_loc_result != NULL)
        {
          if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
              || GET_MODE_CLASS (mode) != MODE_INT)
@@ -11705,12 +11816,6 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                           new_loc_descr (DW_OP_deref_size,
                                          GET_MODE_SIZE (mode), 0));
        }
-      else
-       {
-         rtx new_rtl = avoid_constant_pool_reference (rtl);
-         if (new_rtl != rtl)
-           return mem_loc_descriptor (new_rtl, mode, mem_mode, initialized);
-       }
       break;
 
     case LO_SUM:
@@ -12475,7 +12580,8 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
         legitimate to make the Dwarf info refer to the whole register which
         contains the given subreg.  */
       if (REG_P (SUBREG_REG (rtl)) && subreg_lowpart_p (rtl))
-       loc_result = loc_descriptor (SUBREG_REG (rtl), mode, initialized);
+       loc_result = loc_descriptor (SUBREG_REG (rtl),
+                                    GET_MODE (SUBREG_REG (rtl)), initialized);
       else
        goto do_default;
       break;
@@ -15387,7 +15493,11 @@ add_gnat_descriptive_type_attribute (dw_die_ref die, tree type,
   dtype_die = lookup_type_die (dtype);
   if (!dtype_die)
     {
+      /* The descriptive type indirectly references TYPE if this is also the
+        case for TYPE itself.  Do not deal with the circularity here.  */
+      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
       gen_type_die (dtype, context_die);
+      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 0;
       dtype_die = lookup_type_die (dtype);
       gcc_assert (dtype_die);
     }
@@ -17986,6 +18096,14 @@ gen_label_die (tree decl, dw_die_ref context_die)
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
          add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
        }
+      else if (insn
+              && NOTE_P (insn)
+              && NOTE_KIND (insn) == NOTE_INSN_DELETED_DEBUG_LABEL
+              && CODE_LABEL_NUMBER (insn) != -1)
+       {
+         ASM_GENERATE_INTERNAL_LABEL (label, "LDL", CODE_LABEL_NUMBER (insn));
+         add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
+       }
     }
 }
 
@@ -18244,6 +18362,7 @@ gen_producer_string (void)
       case OPT__output_pch_:
       case OPT_fdiagnostics_show_location_:
       case OPT_fdiagnostics_show_option:
+      case OPT_fverbose_asm:
       case OPT____:
       case OPT__sysroot_:
       case OPT_nostdinc:
@@ -18383,6 +18502,11 @@ gen_compile_unit_die (const char *filename)
        language = DW_LANG_ObjC;
       else if (strcmp (language_string, "GNU Objective-C++") == 0)
        language = DW_LANG_ObjC_plus_plus;
+      else if (dwarf_version >= 5 || !dwarf_strict)
+       {
+         if (strcmp (language_string, "GNU Go") == 0)
+           language = DW_LANG_Go;
+       }
     }
 
   add_AT_unsigned (die, DW_AT_language, language);
@@ -18799,8 +18923,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 
       /* Use the DIE of the containing namespace as the parent DIE of
          the type description DIE we want to generate.  */
-      if (DECL_CONTEXT (TYPE_NAME (type))
-         && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
+      if (DECL_FILE_SCOPE_P (TYPE_NAME (type))
+         || (DECL_CONTEXT (TYPE_NAME (type))
+             && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL))
        context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
 
       TREE_ASM_WRITTEN (type) = 1;
@@ -20094,10 +20219,11 @@ dwarf2out_var_location (rtx loc_note)
 {
   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
-  rtx next_real;
+  rtx next_real, next_note;
   static const char *last_label;
   static const char *last_postcall_label;
   static bool last_in_cold_section_p;
+  static rtx expected_next_loc_note;
   tree decl;
   bool var_loc_p;
 
@@ -20116,7 +20242,35 @@ dwarf2out_var_location (rtx loc_note)
   if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note)))
     return;
 
-  next_real = next_real_insn (loc_note);
+  /* Optimize processing a large consecutive sequence of location
+     notes so we don't spend too much time in next_real_insn.  If the
+     next insn is another location note, remember the next_real_insn
+     calculation for next time.  */
+  next_real = cached_next_real_insn;
+  if (next_real)
+    {
+      if (expected_next_loc_note != loc_note)
+       next_real = NULL_RTX;
+    }
+
+  next_note = NEXT_INSN (loc_note);
+  if (! next_note
+      || INSN_DELETED_P (next_note)
+      || GET_CODE (next_note) != NOTE
+      || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
+         && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
+    next_note = NULL_RTX;
+
+  if (! next_real)
+    next_real = next_real_insn (loc_note);
+
+  if (next_note)
+    {
+      expected_next_loc_note = next_note;
+      cached_next_real_insn = next_real;
+    }
+  else
+    cached_next_real_insn = NULL_RTX;
 
   /* If there are no instructions which would be affected by this note,
      don't do anything.  */
@@ -20299,6 +20453,10 @@ set_cur_line_info_table (section *sec)
       VEC_safe_push (dw_line_info_table_p, gc, separate_line_info, table);
     }
 
+  if (DWARF2_ASM_LINE_DEBUG_INFO)
+    table->is_stmt = (cur_line_info_table
+                     ? cur_line_info_table->is_stmt
+                     : DWARF_LINE_DEFAULT_IS_STMT_START);
   cur_line_info_table = table;
 }
 
@@ -20396,12 +20554,27 @@ dwarf2out_source_line (unsigned int line, const char *filename,
   if (DWARF2_ASM_LINE_DEBUG_INFO)
     {
       /* Emit the .loc directive understood by GNU as.  */
-      fprintf (asm_out_file, "\t.loc %d %d 0", file_num, line);
+      /* "\t.loc %u %u 0 is_stmt %u discriminator %u",
+        file_num, line, is_stmt, discriminator */
+      fputs ("\t.loc ", asm_out_file);
+      fprint_ul (asm_out_file, file_num);
+      putc (' ', asm_out_file);
+      fprint_ul (asm_out_file, line);
+      putc (' ', asm_out_file);
+      putc ('0', asm_out_file);
+
       if (is_stmt != table->is_stmt)
-       fprintf (asm_out_file, " is_stmt %d", is_stmt ? 1 : 0);
+       {
+         fputs (" is_stmt ", asm_out_file);
+         putc (is_stmt ? '1' : '0', asm_out_file);
+       }
       if (SUPPORTS_DISCRIMINATOR && discriminator != 0)
-       fprintf (asm_out_file, " discriminator %d", discriminator);
-      fputc ('\n', asm_out_file);
+       {
+         gcc_assert (discriminator > 0);
+         fputs (" discriminator ", asm_out_file);
+         fprint_ul (asm_out_file, (unsigned long) discriminator);
+       }
+      putc ('\n', asm_out_file);
     }
   else
     {
@@ -20445,7 +20618,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
       macinfo_entry e;
       e.code = DW_MACINFO_start_file;
       e.lineno = lineno;
-      e.info = xstrdup (filename);
+      e.info = ggc_strdup (filename);
       VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
     }
 }
@@ -20491,7 +20664,7 @@ dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED,
        }
       e.code = DW_MACINFO_define;
       e.lineno = lineno;
-      e.info = xstrdup (buffer);;
+      e.info = ggc_strdup (buffer);
       VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
     }
 }
@@ -20518,7 +20691,7 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
        }
       e.code = DW_MACINFO_undef;
       e.lineno = lineno;
-      e.info = xstrdup (buffer);
+      e.info = ggc_strdup (buffer);
       VEC_safe_push (macinfo_entry, gc, macinfo_table, &e);
     }
 }
@@ -20552,11 +20725,13 @@ output_macinfo_op (macinfo_entry *ref)
   size_t len;
   struct indirect_string_node *node;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
+  struct dwarf_file_data *fd;
 
   switch (ref->code)
     {
     case DW_MACINFO_start_file:
-      file_num = maybe_emit_file (lookup_filename (ref->info));
+      fd = lookup_filename (ref->info);
+      file_num = maybe_emit_file (fd);
       dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file");
       dw2_asm_output_data_uleb128 (ref->lineno,
                                   "Included from line number %lu", 
@@ -20694,8 +20869,8 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
   linebuf_len = strlen (linebuf);
 
   /* The group name format is: wmN.[<encoded filename>.]<lineno>.<md5sum>  */
-  grp_name = XNEWVEC (char, 4 + encoded_filename_len + linebuf_len + 1
-                     + 16 * 2 + 1);
+  grp_name = XALLOCAVEC (char, 4 + encoded_filename_len + linebuf_len + 1
+                        + 16 * 2 + 1);
   memcpy (grp_name, DWARF_OFFSET_SIZE == 4 ? "wm4." : "wm8.", 4);
   tail = grp_name + 4;
   if (encoded_filename_len)
@@ -20716,14 +20891,13 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
   inc = VEC_index (macinfo_entry, macinfo_table, idx - 1);
   inc->code = DW_MACRO_GNU_transparent_include;
   inc->lineno = 0;
-  inc->info = grp_name;
+  inc->info = ggc_strdup (grp_name);
   if (*macinfo_htab == NULL)
     *macinfo_htab = htab_create (10, htab_macinfo_hash, htab_macinfo_eq, NULL);
   /* Avoid emitting duplicates.  */
   slot = htab_find_slot (*macinfo_htab, inc, INSERT);
   if (*slot != NULL)
     {
-      free (CONST_CAST (char *, inc->info));
       inc->code = 0;
       inc->info = NULL;
       /* If such an entry has been used before, just emit
@@ -20738,7 +20912,6 @@ optimize_macinfo_range (unsigned int idx, VEC (macinfo_entry, gc) *files,
           i++)
        {
          cur->code = 0;
-         free (CONST_CAST (char *, cur->info));
          cur->info = NULL;
        }
     }
@@ -20799,11 +20972,7 @@ output_macinfo (void)
          break;
        case DW_MACINFO_end_file:
          if (!VEC_empty (macinfo_entry, files))
-           {
-             macinfo_entry *file = VEC_last (macinfo_entry, files);
-             free (CONST_CAST (char *, file->info));
-             VEC_pop (macinfo_entry, files);
-           }
+           VEC_pop (macinfo_entry, files);
          break;
        case DW_MACINFO_define:
        case DW_MACINFO_undef:
@@ -20831,10 +21000,6 @@ output_macinfo (void)
          break;
        }
       output_macinfo_op (ref);
-      /* For DW_MACINFO_start_file ref->info has been copied into files
-        vector.  */
-      if (ref->code != DW_MACINFO_start_file)
-       free (CONST_CAST (char *, ref->info));
       ref->info = NULL;
       ref->code = 0;
     }
@@ -20868,7 +21033,6 @@ output_macinfo (void)
                                       ref->lineno);
          ASM_OUTPUT_LABEL (asm_out_file, label);
          ref->code = 0;
-         free (CONST_CAST (char *, ref->info));
          ref->info = NULL;
          dw2_asm_output_data (2, 4, "DWARF macro version number");
          if (DWARF_OFFSET_SIZE == 8)
@@ -20881,7 +21045,6 @@ output_macinfo (void)
       case DW_MACINFO_undef:
        output_macinfo_op (ref);
        ref->code = 0;
-       free (CONST_CAST (char *, ref->info));
        ref->info = NULL;
        break;
       default:
@@ -21781,13 +21944,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
@@ -22380,15 +22556,8 @@ dwarf2out_finish (const char *filename)
              else if (TYPE_P (node->created_for))
                context = TYPE_CONTEXT (node->created_for);
 
-             gcc_assert (context
-                         && (TREE_CODE (context) == FUNCTION_DECL
-                             || TREE_CODE (context) == NAMESPACE_DECL));
-
-             origin = lookup_decl_die (context);
-             if (origin)
-               add_child_die (origin, die);
-             else
-               add_child_die (comp_unit_die (), die);
+             origin = get_context_die (context);
+             add_child_die (origin, die);
            }
        }
     }
@@ -22637,6 +22806,16 @@ dwarf2out_finish (const char *filename)
       output_ranges ();
     }
 
+  /* Have to end the macro section.  */
+  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+    {
+      switch_to_section (debug_macinfo_section);
+      ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
+      if (!VEC_empty (macinfo_entry, macinfo_table))
+       output_macinfo ();
+      dw2_asm_output_data (1, 0, "End compilation unit");
+    }
+
   /* Output the source line correspondence table.  We must do this
      even if there is no line information.  Otherwise, on an empty
      translation unit, we will generate a present, but empty,
@@ -22648,16 +22827,6 @@ dwarf2out_finish (const char *filename)
   if (! DWARF2_ASM_LINE_DEBUG_INFO)
     output_line_info ();
 
-  /* Have to end the macro section.  */
-  if (debug_info_level >= DINFO_LEVEL_VERBOSE)
-    {
-      switch_to_section (debug_macinfo_section);
-      ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label);
-      if (!VEC_empty (macinfo_entry, macinfo_table))
-        output_macinfo ();
-      dw2_asm_output_data (1, 0, "End compilation unit");
-    }
-
   /* If we emitted any DW_FORM_strp form attribute, output the string
      table too.  */
   if (debug_str_hash)