coretypes.h: Include hash-table.h and hash-set.h for host files.
[gcc.git] / gcc / dwarf2out.c
index 22282d8b1cac1ba795a674ef09783bfbf3233eb9..ee2bcb11a3b06e82dfb9054339a23c17ff77c5b9 100644 (file)
@@ -1,5 +1,5 @@
 /* Output Dwarf2 format symbol table information from GCC.
-   Copyright (C) 1992-2014 Free Software Foundation, Inc.
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
    Contributed by Gary Funck (gary@intrepid.com).
    Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com).
    Extensively modified by Jason Merrill (jason@cygnus.com).
@@ -60,21 +60,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "rtl.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
 #include "tree.h"
+#include "fold-const.h"
 #include "stringpool.h"
 #include "stor-layout.h"
 #include "varasm.h"
+#include "hard-reg-set.h"
 #include "function.h"
 #include "emit-rtl.h"
-#include "hash-table.h"
 #include "version.h"
 #include "flags.h"
-#include "hard-reg-set.h"
 #include "regs.h"
+#include "rtlhash.h"
 #include "insn-config.h"
 #include "reload.h"
-#include "function.h"
 #include "output.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "stmt.h"
 #include "expr.h"
 #include "except.h"
 #include "dwarf2.h"
@@ -89,18 +97,22 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
+#include "is-a.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
 #include "cgraph.h"
-#include "input.h"
 #include "ira.h"
 #include "lra.h"
 #include "dumpfile.h"
 #include "opts.h"
 #include "tree-dfa.h"
 #include "gdb/gdb-index.h"
+#include "rtl-iter.h"
 
 static void dwarf2out_source_line (unsigned int, const char *, int, bool);
-static rtx last_var_location_insn;
-static rtx cached_next_real_insn;
+static rtx_insn *last_var_location_insn;
+static rtx_insn *cached_next_real_insn;
+static void dwarf2out_decl (tree);
 
 #ifdef VMS_DEBUGGING_INFO
 int vms_file_stats_name (const char *, long long *, long *, char *, int *);
@@ -202,7 +214,7 @@ static GTY(()) section *debug_frame_section;
 
 static GTY(()) vec<dw_fde_ref, va_gc> *fde_vec;
 
-struct GTY(()) indirect_string_node {
+struct GTY((for_user)) indirect_string_node {
   const char *str;
   unsigned int refcount;
   enum dwarf_form form;
@@ -210,7 +222,15 @@ struct GTY(()) indirect_string_node {
   unsigned int index;
 };
 
-static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
+struct indirect_string_hasher : ggc_hasher<indirect_string_node *>
+{
+  typedef const char *compare_type;
+
+  static hashval_t hash (indirect_string_node *);
+  static bool equal (indirect_string_node *, const char *);
+};
+
+static GTY (()) hash_table<indirect_string_hasher> *debug_str_hash;
 
 /* With split_debug_info, both the comp_dir and dwo_name go in the
    main object file, rather than the dwo, similar to the force_direct
@@ -231,8 +251,7 @@ static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash;
    main object file.  This limits the complexity to just the places
    that need it.  */
 
-static GTY ((param_is (struct indirect_string_node)))
-  htab_t skeleton_debug_str_hash;
+static GTY (()) hash_table<indirect_string_hasher> *skeleton_debug_str_hash;
 
 static GTY(()) int dw2_string_counter;
 
@@ -247,6 +266,12 @@ static GTY(()) bool cold_text_section_used = false;
 /* The default cold text section.  */
 static GTY(()) section *cold_text_section;
 
+/* The DIE for C++14 'auto' in a function return type.  */
+static GTY(()) dw_die_ref auto_die;
+
+/* The DIE for C++14 'decltype(auto)' in a function return type.  */
+static GTY(()) dw_die_ref decltype_auto_die;
+
 /* Forward declarations for functions defined in this file.  */
 
 static char *stripattributes (const char *);
@@ -351,6 +376,16 @@ dump_struct_debug (tree type, enum debug_info_usage usage,
 
 #endif
 
+/* Get the number of HOST_WIDE_INTs needed to represent the precision
+   of the number.  */
+
+static unsigned int
+get_full_len (const wide_int &op)
+{
+  return ((op.get_precision () + HOST_BITS_PER_WIDE_INT - 1)
+         / HOST_BITS_PER_WIDE_INT);
+}
+
 static bool
 should_emit_struct_debug (tree type, enum debug_info_usage usage)
 {
@@ -976,7 +1011,7 @@ dwarf2out_alloc_current_fde (void)
 {
   dw_fde_ref fde;
 
-  fde = ggc_alloc_cleared_dw_fde_node ();
+  fde = ggc_cleared_alloc<dw_fde_node> ();
   fde->decl = current_function_decl;
   fde->funcdef_number = current_function_funcdef_no;
   fde->fde_index = vec_safe_length (fde_vec);
@@ -1121,8 +1156,8 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   dw_fde_ref fde;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  last_var_location_insn = NULL_RTX;
-  cached_next_real_insn = NULL_RTX;
+  last_var_location_insn = NULL;
+  cached_next_real_insn = NULL;
 
   if (dwarf2out_do_cfi_asm ())
     fprintf (asm_out_file, "\t.cfi_endproc\n");
@@ -1216,21 +1251,11 @@ dwarf2out_switch_text_section (void)
    for emitting location expressions.  */
 
 /* Data about a single source file.  */
-struct GTY(()) dwarf_file_data {
+struct GTY((for_user)) dwarf_file_data {
   const char * filename;
   int emitted_number;
 };
 
-typedef struct GTY(()) deferred_locations_struct
-{
-  tree variable;
-  dw_die_ref die;
-} deferred_locations;
-
-
-static GTY(()) vec<deferred_locations, va_gc> *deferred_locations_list;
-
-
 /* Describe an entry into the .debug_addr section.  */
 
 enum ate_kind {
@@ -1239,7 +1264,7 @@ enum ate_kind {
   ate_kind_label
 };
 
-typedef struct GTY(()) addr_table_entry_struct {
+typedef struct GTY((for_user)) addr_table_entry_struct {
   enum ate_kind kind;
   unsigned int refcount;
   unsigned int index;
@@ -1299,7 +1324,7 @@ static inline dw_loc_descr_ref
 new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
               unsigned HOST_WIDE_INT oprnd2)
 {
-  dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
+  dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
 
   descr->dw_loc_opc = op;
   descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -1386,6 +1411,9 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
       return (a->v.val_double.high == b->v.val_double.high
              && a->v.val_double.low == b->v.val_double.low);
 
+    case dw_val_class_wide_int:
+      return *a->v.val_wide == *b->v.val_wide;
+
     case dw_val_class_vec:
       {
        size_t a_len = a->v.val_vec.elt_size * a->v.val_vec.length;
@@ -1642,6 +1670,10 @@ size_of_loc_descr (dw_loc_descr_ref loc)
          case dw_val_class_const_double:
            size += HOST_BITS_PER_DOUBLE_INT / BITS_PER_UNIT;
            break;
+         case dw_val_class_wide_int:
+           size += (get_full_len (*loc->dw_loc_oprnd2.v.val_wide)
+                    * HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT);
+           break;
          default:
            gcc_unreachable ();
          }
@@ -1819,6 +1851,20 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
                                 second, NULL);
          }
          break;
+       case dw_val_class_wide_int:
+         {
+           int i;
+           int len = get_full_len (*val2->v.val_wide);
+           if (WORDS_BIG_ENDIAN)
+             for (i = len - 1; i >= 0; --i)
+               dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
+                                    val2->v.val_wide->elt (i), NULL);
+           else
+             for (i = 0; i < len; ++i)
+               dw2_asm_output_data (HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR,
+                                    val2->v.val_wide->elt (i), NULL);
+         }
+         break;
        case dw_val_class_addr:
          gcc_assert (val1->v.val_unsigned == DWARF2_ADDR_SIZE);
          dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, val2->v.val_addr, NULL);
@@ -2028,6 +2074,21 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
              dw2_asm_output_data (l, second, NULL);
            }
            break;
+         case dw_val_class_wide_int:
+           {
+             int i;
+             int len = get_full_len (*val2->v.val_wide);
+             l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
+
+             dw2_asm_output_data (1, len * l, NULL);
+             if (WORDS_BIG_ENDIAN)
+               for (i = len - 1; i >= 0; --i)
+                 dw2_asm_output_data (l, val2->v.val_wide->elt (i), NULL);
+             else
+               for (i = 0; i < len; ++i)
+                 dw2_asm_output_data (l, val2->v.val_wide->elt (i), NULL);
+           }
+           break;
          default:
            gcc_unreachable ();
          }
@@ -2362,10 +2423,10 @@ build_cfa_aligned_loc (dw_cfa_location *cfa,
 /* And now, the support for symbolic debugging information.  */
 
 /* .debug_str support.  */
-static int output_indirect_string (void **, void *);
 
 static void dwarf2out_init (const char *);
 static void dwarf2out_finish (const char *);
+static void dwarf2out_early_finish (void);
 static void dwarf2out_assembly_start (void);
 static void dwarf2out_define (unsigned int, const char *);
 static void dwarf2out_undef (unsigned int, const char *);
@@ -2375,13 +2436,14 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
-static void dwarf2out_global_decl (tree);
+static void dwarf2out_early_global_decl (tree);
+static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
 static void dwarf2out_imported_module_or_decl (tree, tree, tree, bool);
 static void dwarf2out_imported_module_or_decl_1 (tree, tree, tree,
                                                 dw_die_ref);
 static void dwarf2out_abstract_function (tree);
-static void dwarf2out_var_location (rtx);
+static void dwarf2out_var_location (rtx_insn *);
 static void dwarf2out_begin_function (tree);
 static void dwarf2out_end_function (unsigned int);
 static void dwarf2out_set_name (tree, tree);
@@ -2392,6 +2454,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
 {
   dwarf2out_init,
   dwarf2out_finish,
+  dwarf2out_early_finish,
   dwarf2out_assembly_start,
   dwarf2out_define,
   dwarf2out_undef,
@@ -2413,7 +2476,8 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_begin_function,
   dwarf2out_end_function,      /* end_function */
   dwarf2out_function_decl,     /* function_decl */
-  dwarf2out_global_decl,
+  dwarf2out_early_global_decl,
+  dwarf2out_late_global_decl,
   dwarf2out_type_decl,         /* type_decl */
   dwarf2out_imported_module_or_decl,
   debug_nothing_tree,          /* deferred_inline_function */
@@ -2421,7 +2485,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
      emitting the abstract description of inline functions until
      something tries to reference them.  */
   dwarf2out_abstract_function, /* outlining_inline_function */
-  debug_nothing_rtx,           /* label */
+  debug_nothing_rtx_code_label,        /* label */
   debug_nothing_int,           /* handle_pch */
   dwarf2out_var_location,
   dwarf2out_switch_text_section,
@@ -2534,7 +2598,7 @@ dw_attr_node;
    The children of each node form a circular list linked by
    die_sib.  die_child points to the node *before* the "first" child node.  */
 
-typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
+typedef struct GTY((chain_circular ("%h.die_sib"), for_user)) die_struct {
   union die_symbol_or_type_node
     {
       const char * GTY ((tag ("0"))) die_symbol;
@@ -2558,6 +2622,14 @@ typedef struct GTY((chain_circular ("%h.die_sib"))) die_struct {
 }
 die_node;
 
+/* Set to TRUE while dwarf2out_early_global_decl is running.  */
+static bool early_dwarf;
+struct set_early_dwarf {
+  bool saved;
+  set_early_dwarf () : saved(early_dwarf) { early_dwarf = true; }
+  ~set_early_dwarf () { early_dwarf = saved; }
+};
+
 /* Evaluate 'expr' while 'c' is set to each child of DIE in order.  */
 #define FOR_EACH_CHILD(die, c, expr) do {      \
   c = die->die_child;                          \
@@ -2608,9 +2680,13 @@ typedef struct GTY(()) comdat_type_struct
 }
 comdat_type_node;
 
-/* The limbo die list structure.  */
+/* A list of DIEs for which we can't determine ancestry (parent_die
+   field) just yet.  Later in dwarf2out_finish we will fill in the
+   missing bits.  */
 typedef struct GTY(()) limbo_die_struct {
   dw_die_ref die;
+  /* The tree for which this DIE was created.  We use this to
+     determine ancestry later.  */
   tree created_for;
   struct limbo_die_struct *next;
 }
@@ -2720,16 +2796,37 @@ static GTY(()) limbo_die_node *limbo_die_list;
    DW_AT_{,MIPS_}linkage_name once their DECL_ASSEMBLER_NAMEs are set.  */
 static GTY(()) limbo_die_node *deferred_asm_name;
 
+struct dwarf_file_hasher : ggc_hasher<dwarf_file_data *>
+{
+  typedef const char *compare_type;
+
+  static hashval_t hash (dwarf_file_data *);
+  static bool equal (dwarf_file_data *, const char *);
+};
+
 /* Filenames referenced by this compilation unit.  */
-static GTY((param_is (struct dwarf_file_data))) htab_t file_table;
+static GTY(()) hash_table<dwarf_file_hasher> *file_table;
+
+struct decl_die_hasher : ggc_hasher<die_node *>
+{
+  typedef tree compare_type;
 
+  static hashval_t hash (die_node *);
+  static bool equal (die_node *, tree);
+};
 /* A hash table of references to DIE's that describe declarations.
    The key is a DECL_UID() which is a unique number identifying each decl.  */
-static GTY ((param_is (struct die_struct))) htab_t decl_die_table;
+static GTY (()) hash_table<decl_die_hasher> *decl_die_table;
+
+struct block_die_hasher : ggc_hasher<die_struct *>
+{
+  static hashval_t hash (die_struct *);
+  static bool equal (die_struct *, die_struct *);
+};
 
 /* A hash table of references to DIE's that describe COMMON blocks.
    The key is DECL_UID() ^ die_parent.  */
-static GTY ((param_is (struct die_struct))) htab_t common_block_die_table;
+static GTY (()) hash_table<block_die_hasher> *common_block_die_table;
 
 typedef struct GTY(()) die_arg_entry_struct {
     dw_die_ref die;
@@ -2753,7 +2850,7 @@ struct GTY ((chain_next ("%h.next"))) var_loc_node {
 };
 
 /* Variable location list.  */
-struct GTY (()) var_loc_list_def {
+struct GTY ((for_user)) var_loc_list_def {
   struct var_loc_node * GTY (()) first;
 
   /* Pointer to the last but one or last element of the
@@ -2785,8 +2882,16 @@ struct GTY ((chain_next ("%h.next"))) call_arg_loc_node {
 };
 
 
+struct decl_loc_hasher : ggc_hasher<var_loc_list *>
+{
+  typedef const_tree compare_type;
+
+  static hashval_t hash (var_loc_list *);
+  static bool equal (var_loc_list *, const_tree);
+};
+
 /* Table of decl location linked lists.  */
-static GTY ((param_is (var_loc_list))) htab_t decl_loc_table;
+static GTY (()) hash_table<decl_loc_hasher> *decl_loc_table;
 
 /* Head and tail of call_arg_loc chain.  */
 static GTY (()) struct call_arg_loc_node *call_arg_locations;
@@ -2797,12 +2902,8 @@ static int call_site_count = -1;
 /* Number of tail call sites in the current function.  */
 static int tail_call_site_count = -1;
 
-/* Vector mapping block numbers to DW_TAG_{lexical_block,inlined_subroutine}
-   DIEs.  */
-static vec<dw_die_ref> block_map;
-
 /* A cached location list.  */
-struct GTY (()) cached_dw_loc_list_def {
+struct GTY ((for_user)) cached_dw_loc_list_def {
   /* The DECL_UID of the decl that this entry describes.  */
   unsigned int decl_id;
 
@@ -2811,8 +2912,17 @@ struct GTY (()) cached_dw_loc_list_def {
 };
 typedef struct cached_dw_loc_list_def cached_dw_loc_list;
 
+struct dw_loc_list_hasher : ggc_hasher<cached_dw_loc_list *>
+{
+
+  typedef const_tree compare_type;
+  
+  static hashval_t hash (cached_dw_loc_list *);
+  static bool equal (cached_dw_loc_list *, const_tree);
+};
+
 /* Table of cached location lists.  */
-static GTY ((param_is (cached_dw_loc_list))) htab_t cached_dw_loc_list_table;
+static GTY (()) hash_table<dw_loc_list_hasher> *cached_dw_loc_list_table;
 
 /* A pointer to the base of a list of references to DIE's that
    are uniquely identified by their tag, presence/absence of
@@ -2823,7 +2933,7 @@ static GTY((length ("abbrev_die_table_allocated")))
 /* Number of elements currently allocated for abbrev_die_table.  */
 static GTY(()) unsigned abbrev_die_table_allocated;
 
-/* Number of elements in type_die_table currently in use.  */
+/* Number of elements in abbrev_die_table currently in use.  */
 static GTY(()) unsigned abbrev_die_table_in_use;
 
 /* Size (in elements) of increments by which we may expand the
@@ -2899,18 +3009,12 @@ static GTY(()) unsigned int loclabel_num;
 /* Unique label counter for point-of-call tables.  */
 static GTY(()) unsigned int poc_label_num;
 
-/* Record whether the function being analyzed contains inlined functions.  */
-static int current_function_has_inlines;
-
 /* The last file entry emitted by maybe_emit_file().  */
 static GTY(()) struct dwarf_file_data * last_emitted_file;
 
 /* Number of internal labels generated by gen_internal_sym().  */
 static GTY(()) int label_num;
 
-/* Cached result of previous call to lookup_filename.  */
-static GTY(()) struct dwarf_file_data * file_table_last_lookup;
-
 static GTY(()) vec<die_arg_entry, va_gc> *tmpl_value_parm_die_table;
 
 /* Instances of generic types for which we need to generate debug
@@ -2926,6 +3030,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -2950,8 +3063,6 @@ static void add_AT_double (dw_die_ref, enum dwarf_attribute,
 static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int,
                               unsigned int, unsigned char *);
 static void add_AT_data8 (dw_die_ref, enum dwarf_attribute, unsigned char *);
-static hashval_t debug_str_do_hash (const void *);
-static int debug_str_eq (const void *, const void *);
 static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *);
 static inline const char *AT_string (dw_attr_ref);
 static enum dwarf_form AT_string_form (dw_attr_ref);
@@ -2988,7 +3099,7 @@ static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
 static bool is_cxx (void);
 static bool is_fortran (void);
 static bool is_ada (void);
-static void remove_AT (dw_die_ref, enum dwarf_attribute);
+static bool remove_AT (dw_die_ref, enum dwarf_attribute);
 static void remove_child_TAG (dw_die_ref, enum dwarf_tag);
 static void add_child_die (dw_die_ref, dw_die_ref);
 static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree);
@@ -2996,13 +3107,7 @@ static dw_die_ref lookup_type_die (tree);
 static dw_die_ref strip_naming_typedef (tree, dw_die_ref);
 static dw_die_ref lookup_type_die_strip_naming_typedef (tree);
 static void equate_type_number_to_die (tree, dw_die_ref);
-static hashval_t decl_die_table_hash (const void *);
-static int decl_die_table_eq (const void *, const void *);
 static dw_die_ref lookup_decl_die (tree);
-static hashval_t common_block_die_table_hash (const void *);
-static int common_block_die_table_eq (const void *, const void *);
-static hashval_t decl_loc_table_hash (const void *);
-static int decl_loc_table_eq (const void *, const void *);
 static var_loc_list *lookup_decl_loc (const_tree);
 static void equate_decl_number_to_die (tree, dw_die_ref);
 static struct var_loc_node *add_var_loc_to_decl (tree, rtx, const char *);
@@ -3088,7 +3193,8 @@ static void output_file_names (void);
 static dw_die_ref base_type_die (tree);
 static int is_base_type (tree);
 static dw_die_ref subrange_type_die (tree, tree, tree, dw_die_ref);
-static dw_die_ref modified_type_die (tree, int, int, dw_die_ref);
+static int decl_quals (const_tree);
+static dw_die_ref modified_type_die (tree, int, dw_die_ref);
 static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref);
 static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref);
 static int type_is_enum (const_tree);
@@ -3102,13 +3208,16 @@ static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx,
 static dw_loc_descr_ref based_loc_descr (rtx, HOST_WIDE_INT,
                                         enum var_init_status);
 static int is_based_loc (const_rtx);
-static int resolve_one_addr (rtx *, void *);
+static bool resolve_one_addr (rtx *);
 static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
                                               enum var_init_status);
-static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
+static dw_loc_descr_ref loc_descriptor (rtx, machine_mode mode,
                                        enum var_init_status);
-static dw_loc_list_ref loc_list_from_tree (tree, int);
-static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+struct loc_descr_context;
+static dw_loc_list_ref loc_list_from_tree (tree, int,
+                                          const struct loc_descr_context *);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
+                                                 const struct loc_descr_context *);
 static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
 static tree field_type (const_tree);
 static unsigned int simple_type_align_in_bits (const_tree);
@@ -3120,7 +3229,7 @@ static void add_AT_location_description   (dw_die_ref, enum dwarf_attribute,
 static void add_data_member_location_attribute (dw_die_ref, tree);
 static bool add_const_value_attribute (dw_die_ref, rtx);
 static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *);
-static void insert_double (double_int, unsigned char *);
+static void insert_wide_int (const wide_int &, unsigned char *, int);
 static void insert_float (const_rtx, unsigned char *);
 static rtx rtl_for_decl_location (tree);
 static bool add_location_or_const_value_attribute (dw_die_ref, tree, bool,
@@ -3130,7 +3239,10 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
-static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
+                            const struct loc_descr_context *);
+static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree,
+                           const struct loc_descr_context *);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
 static void add_bit_offset_attribute (dw_die_ref, tree);
@@ -3146,7 +3258,7 @@ static dw_die_ref scope_die_for (tree, dw_die_ref);
 static inline int local_scope_p (dw_die_ref);
 static inline int class_scope_p (dw_die_ref);
 static inline int class_or_namespace_scope_p (dw_die_ref);
-static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref);
+static void add_type_attribute (dw_die_ref, tree, int, dw_die_ref);
 static void add_calling_convention_attribute (dw_die_ref, tree);
 static const char *type_tag (const_tree);
 static tree member_declared_type (const_tree);
@@ -3167,8 +3279,8 @@ static void gen_subprogram_die (tree, dw_die_ref);
 static void gen_variable_die (tree, tree, dw_die_ref);
 static void gen_const_die (tree, dw_die_ref);
 static void gen_label_die (tree, dw_die_ref);
-static void gen_lexical_block_die (tree, dw_die_ref, int);
-static void gen_inlined_subroutine_die (tree, dw_die_ref, int);
+static void gen_lexical_block_die (tree, dw_die_ref);
+static void gen_inlined_subroutine_die (tree, dw_die_ref);
 static void gen_field_die (tree, dw_die_ref);
 static void gen_ptr_to_mbr_type_die (tree, dw_die_ref);
 static dw_die_ref gen_compile_unit_die (const char *);
@@ -3179,8 +3291,8 @@ static void gen_struct_or_union_type_die (tree, dw_die_ref,
 static void gen_subroutine_type_die (tree, dw_die_ref);
 static void gen_typedef_die (tree, dw_die_ref);
 static void gen_type_die (tree, dw_die_ref);
-static void gen_block_die (tree, dw_die_ref, int);
-static void decls_for_scope (tree, dw_die_ref, int);
+static void gen_block_die (tree, dw_die_ref);
+static void decls_for_scope (tree, dw_die_ref);
 static inline int is_redundant_typedef (const_tree);
 static bool is_naming_typedef_decl (const_tree);
 static inline dw_die_ref get_context_die (tree);
@@ -3225,7 +3337,7 @@ static void gen_scheduled_generic_parms_dies (void);
 
 static const char *comp_dir_string (void);
 
-static hashval_t hash_loc_operands (dw_loc_descr_ref, hashval_t);
+static void hash_loc_operands (dw_loc_descr_ref, inchash::hash &);
 
 /* enum for tracking thread-local variables whose address is really an offset
    relative to the TLS pointer, which will need link-time relocation, but will
@@ -3620,10 +3732,9 @@ decl_ultimate_origin (const_tree decl)
   if (!CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_COMMON))
     return NULL_TREE;
 
-  /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the
-     nodes in the function to point to themselves; ignore that if
+  /* DECL_ABSTRACT_ORIGIN can point to itself; ignore that if
      we're trying to output the abstract instance of this function.  */
-  if (DECL_ABSTRACT (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl)
+  if (DECL_ABSTRACT_P (decl) && DECL_ABSTRACT_ORIGIN (decl) == decl)
     return NULL_TREE;
 
   /* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
@@ -3752,6 +3863,22 @@ AT_unsigned (dw_attr_ref a)
   return a->dw_attr_val.v.val_unsigned;
 }
 
+/* Add an unsigned wide integer attribute value to a DIE.  */
+
+static inline void
+add_AT_wide (dw_die_ref die, enum dwarf_attribute attr_kind,
+            const wide_int& w)
+{
+  dw_attr_node attr;
+
+  attr.dw_attr = attr_kind;
+  attr.dw_attr_val.val_class = dw_val_class_wide_int;
+  attr.dw_attr_val.val_entry = NULL;
+  attr.dw_attr_val.v.val_wide = ggc_alloc<wide_int> ();
+  *attr.dw_attr_val.v.val_wide = w;
+  add_dwarf_attr (die, &attr);
+}
+
 /* Add an unsigned double integer attribute value to a DIE.  */
 
 static inline void
@@ -3841,37 +3968,36 @@ add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high,
 
 /* Hash and equality functions for debug_str_hash.  */
 
-static hashval_t
-debug_str_do_hash (const void *x)
+hashval_t
+indirect_string_hasher::hash (indirect_string_node *x)
 {
-  return htab_hash_string (((const struct indirect_string_node *)x)->str);
+  return htab_hash_string (x->str);
 }
 
-static int
-debug_str_eq (const void *x1, const void *x2)
+bool
+indirect_string_hasher::equal (indirect_string_node *x1, const char *x2)
 {
-  return strcmp ((((const struct indirect_string_node *)x1)->str),
-                (const char *)x2) == 0;
+  return strcmp (x1->str, x2) == 0;
 }
 
 /* Add STR to the given string hash table.  */
 
 static struct indirect_string_node *
-find_AT_string_in_table (const char *str, htab_t table)
+find_AT_string_in_table (const char *str,
+                        hash_table<indirect_string_hasher> *table)
 {
   struct indirect_string_node *node;
-  void **slot;
 
-  slot = htab_find_slot_with_hash (table, str,
-                                  htab_hash_string (str), INSERT);
+  indirect_string_node **slot
+    = table->find_slot_with_hash (str, htab_hash_string (str), INSERT);
   if (*slot == NULL)
     {
-      node = ggc_alloc_cleared_indirect_string_node ();
+      node = ggc_cleared_alloc<indirect_string_node> ();
       node->str = ggc_strdup (str);
       *slot = node;
     }
   else
-    node = (struct indirect_string_node *) *slot;
+    node = *slot;
 
   node->refcount++;
   return node;
@@ -3883,8 +4009,7 @@ static struct indirect_string_node *
 find_AT_string (const char *str)
 {
   if (! debug_str_hash)
-    debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
-                                     debug_str_eq, NULL);
+    debug_str_hash = hash_table<indirect_string_hasher>::create_ggc (10);
 
   return find_AT_string_in_table (str, debug_str_hash);
 }
@@ -4113,37 +4238,44 @@ AT_loc_list_ptr (dw_attr_ref a)
   return &a->dw_attr_val.v.val_loc_list;
 }
 
+struct addr_hasher : ggc_hasher<addr_table_entry *>
+{
+  static hashval_t hash (addr_table_entry *);
+  static bool equal (addr_table_entry *, addr_table_entry *);
+};
+
 /* Table of entries into the .debug_addr section.  */
 
-static GTY ((param_is (addr_table_entry))) htab_t addr_index_table;
+static GTY (()) hash_table<addr_hasher> *addr_index_table;
 
 /* Hash an address_table_entry.  */
 
-static hashval_t
-addr_table_entry_do_hash (const void *x)
+hashval_t
+addr_hasher::hash (addr_table_entry *a)
 {
-  const addr_table_entry *a = (const addr_table_entry *) x;
+  inchash::hash hstate;
   switch (a->kind)
     {
       case ate_kind_rtx:
-        return iterative_hash_rtx (a->addr.rtl, 0);
+       hstate.add_int (0);
+       break;
       case ate_kind_rtx_dtprel:
-        return iterative_hash_rtx (a->addr.rtl, 1);
+       hstate.add_int (1);
+       break;
       case ate_kind_label:
         return htab_hash_string (a->addr.label);
       default:
         gcc_unreachable ();
     }
+  inchash::add_rtx (a->addr.rtl, hstate);
+  return hstate.end ();
 }
 
 /* Determine equality for two address_table_entries.  */
 
-static int
-addr_table_entry_eq (const void *x1, const void *x2)
+bool
+addr_hasher::equal (addr_table_entry *a1, addr_table_entry *a2)
 {
-  const addr_table_entry *a1 = (const addr_table_entry *) x1;
-  const addr_table_entry *a2 = (const addr_table_entry *) x2;
-
   if (a1->kind != a2->kind)
     return 0;
   switch (a1->kind)
@@ -4186,23 +4318,21 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
 {
   addr_table_entry *node;
   addr_table_entry finder;
-  void **slot;
 
   gcc_assert (dwarf_split_debug_info);
   if (! addr_index_table)
-    addr_index_table = htab_create_ggc (10, addr_table_entry_do_hash,
-                                        addr_table_entry_eq, NULL);
+    addr_index_table = hash_table<addr_hasher>::create_ggc (10);
   init_addr_table_entry (&finder, kind, addr);
-  slot = htab_find_slot (addr_index_table, &finder, INSERT);
+  addr_table_entry **slot = addr_index_table->find_slot (&finder, INSERT);
 
   if (*slot == HTAB_EMPTY_ENTRY)
     {
-      node = ggc_alloc_cleared_addr_table_entry ();
+      node = ggc_cleared_alloc<addr_table_entry> ();
       init_addr_table_entry (node, kind, addr);
       *slot = node;
     }
   else
-    node = (addr_table_entry *) *slot;
+    node = *slot;
 
   node->refcount++;
   return node;
@@ -4216,13 +4346,10 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
 static void
 remove_addr_table_entry (addr_table_entry *entry)
 {
-  addr_table_entry *node;
-
   gcc_assert (dwarf_split_debug_info && addr_index_table);
-  node = (addr_table_entry *) htab_find (addr_index_table, entry);
   /* After an index is assigned, the table is frozen.  */
-  gcc_assert (node->refcount > 0 && node->index == NO_INDEX_ASSIGNED);
-  node->refcount--;
+  gcc_assert (entry->refcount > 0 && entry->index == NO_INDEX_ASSIGNED);
+  entry->refcount--;
 }
 
 /* Given a location list, remove all addresses it refers to from the
@@ -4245,11 +4372,10 @@ remove_loc_list_addr_table_entries (dw_loc_descr_ref descr)
    because the indexing code relies on htab_traverse to traverse nodes
    in the same order for each run. */
 
-static int
-index_addr_table_entry (void **h, void *v)
+int
+index_addr_table_entry (addr_table_entry **h, unsigned int *index)
 {
-  addr_table_entry *node = (addr_table_entry *) *h;
-  unsigned int *index = (unsigned int *) v;
+  addr_table_entry *node = *h;
 
   /* Don't index unreferenced nodes.  */
   if (node->refcount == 0)
@@ -4575,7 +4701,8 @@ is_cxx (void)
 {
   unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language);
 
-  return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus;
+  return (lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus
+         || lang == DW_LANG_C_plus_plus_11 || lang == DW_LANG_C_plus_plus_14);
 }
 
 /* Return TRUE if the language is Java.  */
@@ -4597,7 +4724,9 @@ is_fortran (void)
 
   return (lang == DW_LANG_Fortran77
          || lang == DW_LANG_Fortran90
-         || lang == DW_LANG_Fortran95);
+         || lang == DW_LANG_Fortran95
+         || lang == DW_LANG_Fortran03
+         || lang == DW_LANG_Fortran08);
 }
 
 /* Return TRUE if the language is Ada.  */
@@ -4610,16 +4739,17 @@ is_ada (void)
   return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83;
 }
 
-/* Remove the specified attribute if present.  */
+/* Remove the specified attribute if present.  Return TRUE if removal
+   was successful.  */
 
-static void
+static bool
 remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 {
   dw_attr_ref a;
   unsigned ix;
 
   if (! die)
-    return;
+    return false;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
     if (a->dw_attr == attr_kind)
@@ -4631,8 +4761,9 @@ remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
        /* vec::ordered_remove should help reduce the number of abbrevs
           that are needed.  */
        die->die_attr->ordered_remove (ix);
-       return;
+       return true;
       }
+  return false;
 }
 
 /* Remove CHILD from its parent.  PREV must have the property that
@@ -4706,6 +4837,7 @@ remove_child_TAG (dw_die_ref die, enum dwarf_tag tag)
     while (c->die_tag == tag)
       {
        remove_child_with_prev (c, prev);
+       c->die_parent = NULL;
        /* Might have removed every child.  */
        if (c == c->die_sib)
          return;
@@ -4735,6 +4867,21 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
   die->die_child = child_die;
 }
 
+/* Unassociate CHILD from its parent, and make its parent be
+   NEW_PARENT.  */
+
+static void
+reparent_child (dw_die_ref child, dw_die_ref new_parent)
+{
+  for (dw_die_ref p = child->die_parent->die_child; ; p = p->die_sib)
+    if (p->die_sib == child)
+      {
+       remove_child_with_prev (child, p);
+       break;
+      }
+  add_child_die (new_parent, child);
+}
+
 /* Move CHILD, which must be a child of PARENT or the DIE for which PARENT
    is the specification, to the end of PARENT's list of children.
    This is done by removing and re-adding it.  */
@@ -4742,8 +4889,6 @@ add_child_die (dw_die_ref die, dw_die_ref child_die)
 static void
 splice_child_die (dw_die_ref parent, dw_die_ref child)
 {
-  dw_die_ref p;
-
   /* We want the declaration DIE from inside the class, not the
      specification DIE at toplevel.  */
   if (child->die_parent != parent)
@@ -4758,22 +4903,18 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
              || (child->die_parent
                  == get_AT_ref (parent, DW_AT_specification)));
 
-  for (p = child->die_parent->die_child; ; p = p->die_sib)
-    if (p->die_sib == child)
-      {
-       remove_child_with_prev (child, p);
-       break;
-      }
-
-  add_child_die (parent, child);
+  reparent_child (child, parent);
 }
 
-/* Return a pointer to a newly created DIE node.  */
+/* Create and return a new die with a parent of PARENT_DIE.  If
+   PARENT_DIE is NULL, the new DIE is placed in limbo and an
+   associated tree T must be supplied to determine parenthood
+   later.  */
 
 static inline dw_die_ref
 new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
 {
-  dw_die_ref die = ggc_alloc_cleared_die_node ();
+  dw_die_ref die = ggc_cleared_alloc<die_node> ();
 
   die->die_tag = tag_value;
 
@@ -4783,7 +4924,36 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
     {
       limbo_die_node *limbo_node;
 
-      limbo_node = ggc_alloc_cleared_limbo_die_node ();
+      /* No DIEs created after early dwarf should end up in limbo,
+        because the limbo list should not persist past LTO
+        streaming.  */
+      if (tag_value != DW_TAG_compile_unit
+         /* These are allowed because they're generated while
+            breaking out COMDAT units late.  */
+         && tag_value != DW_TAG_type_unit
+         && !early_dwarf
+         /* Allow nested functions to live in limbo because they will
+            only temporarily live there, as decls_for_scope will fix
+            them up.  */
+         && (TREE_CODE (t) != FUNCTION_DECL
+             || !decl_function_context (t))
+         /* Same as nested functions above but for types.  Types that
+            are local to a function will be fixed in
+            decls_for_scope.  */
+         && (!RECORD_OR_UNION_TYPE_P (t)
+             || !TYPE_CONTEXT (t)
+             || TREE_CODE (TYPE_CONTEXT (t)) != FUNCTION_DECL)
+         /* FIXME debug-early: Allow late limbo DIE creation for LTO,
+            especially in the ltrans stage, but once we implement LTO
+            dwarf streaming, we should remove this exception.  */
+         && !in_lto_p)
+       {
+         fprintf (stderr, "symbol ended up in limbo too late:");
+         debug_generic_stmt (t);
+         gcc_unreachable ();
+       }
+
+      limbo_node = ggc_cleared_alloc<limbo_die_node> ();
       limbo_node->die = die;
       limbo_node->created_for = t;
       limbo_node->next = limbo_die_list;
@@ -4844,18 +5014,18 @@ equate_type_number_to_die (tree type, dw_die_ref type_die)
 
 /* Returns a hash value for X (which really is a die_struct).  */
 
-static hashval_t
-decl_die_table_hash (const void *x)
+inline hashval_t
+decl_die_hasher::hash (die_node *x)
 {
-  return (hashval_t) ((const_dw_die_ref) x)->decl_id;
+  return (hashval_t) x->decl_id;
 }
 
 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
 
-static int
-decl_die_table_eq (const void *x, const void *y)
+inline bool
+decl_die_hasher::equal (die_node *x, tree y)
 {
-  return (((const_dw_die_ref) x)->decl_id == DECL_UID ((const_tree) y));
+  return (x->decl_id == DECL_UID (y));
 }
 
 /* Return the DIE associated with a given declaration.  */
@@ -4863,24 +5033,24 @@ decl_die_table_eq (const void *x, const void *y)
 static inline dw_die_ref
 lookup_decl_die (tree decl)
 {
-  return (dw_die_ref) htab_find_with_hash (decl_die_table, decl, DECL_UID (decl));
+  return decl_die_table->find_with_hash (decl, DECL_UID (decl));
 }
 
 /* Returns a hash value for X (which really is a var_loc_list).  */
 
-static hashval_t
-decl_loc_table_hash (const void *x)
+inline hashval_t
+decl_loc_hasher::hash (var_loc_list *x)
 {
-  return (hashval_t) ((const var_loc_list *) x)->decl_id;
+  return (hashval_t) x->decl_id;
 }
 
 /* Return nonzero if decl_id of var_loc_list X is the same as
    UID of decl *Y.  */
 
-static int
-decl_loc_table_eq (const void *x, const void *y)
+inline bool
+decl_loc_hasher::equal (var_loc_list *x, const_tree y)
 {
-  return (((const var_loc_list *) x)->decl_id == DECL_UID ((const_tree) y));
+  return (x->decl_id == DECL_UID (y));
 }
 
 /* Return the var_loc list associated with a given declaration.  */
@@ -4890,26 +5060,24 @@ lookup_decl_loc (const_tree decl)
 {
   if (!decl_loc_table)
     return NULL;
-  return (var_loc_list *)
-    htab_find_with_hash (decl_loc_table, decl, DECL_UID (decl));
+  return decl_loc_table->find_with_hash (decl, DECL_UID (decl));
 }
 
 /* Returns a hash value for X (which really is a cached_dw_loc_list_list).  */
 
-static hashval_t
-cached_dw_loc_list_table_hash (const void *x)
+inline hashval_t
+dw_loc_list_hasher::hash (cached_dw_loc_list *x)
 {
-  return (hashval_t) ((const cached_dw_loc_list *) x)->decl_id;
+  return (hashval_t) x->decl_id;
 }
 
 /* Return nonzero if decl_id of cached_dw_loc_list X is the same as
    UID of decl *Y.  */
 
-static int
-cached_dw_loc_list_table_eq (const void *x, const void *y)
+inline bool
+dw_loc_list_hasher::equal (cached_dw_loc_list *x, const_tree y)
 {
-  return (((const cached_dw_loc_list *) x)->decl_id
-         == DECL_UID ((const_tree) y));
+  return (x->decl_id == DECL_UID (y));
 }
 
 /* Equate a DIE to a particular declaration.  */
@@ -4918,16 +5086,14 @@ static void
 equate_decl_number_to_die (tree decl, dw_die_ref decl_die)
 {
   unsigned int decl_id = DECL_UID (decl);
-  void **slot;
 
-  slot = htab_find_slot_with_hash (decl_die_table, decl, decl_id, INSERT);
-  *slot = decl_die;
+  *decl_die_table->find_slot_with_hash (decl, decl_id, INSERT) = decl_die;
   decl_die->decl_id = decl_id;
 }
 
 /* Return how many bits covers PIECE EXPR_LIST.  */
 
-static int
+static HOST_WIDE_INT
 decl_piece_bitsize (rtx piece)
 {
   int ret = (int) GET_MODE (piece);
@@ -4952,10 +5118,10 @@ decl_piece_varloc_ptr (rtx piece)
 /* Create an EXPR_LIST for location note LOC_NOTE covering BITSIZE bits.
    Next is the chain of following piece nodes.  */
 
-static rtx
+static rtx_expr_list *
 decl_piece_node (rtx loc_note, HOST_WIDE_INT bitsize, rtx next)
 {
-  if (bitsize <= (int) MAX_MACHINE_MODE)
+  if (bitsize > 0 && bitsize <= (int) MAX_MACHINE_MODE)
     return alloc_EXPR_LIST (bitsize, loc_note, next);
   else
     return alloc_EXPR_LIST (0, gen_rtx_CONCAT (VOIDmode,
@@ -4994,7 +5160,7 @@ adjust_piece_list (rtx *dest, rtx *src, rtx *inner,
                   HOST_WIDE_INT bitpos, HOST_WIDE_INT piece_bitpos,
                   HOST_WIDE_INT bitsize, rtx loc_note)
 {
-  int diff;
+  HOST_WIDE_INT diff;
   bool copy = inner != NULL;
 
   if (copy)
@@ -5069,7 +5235,6 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
 {
   unsigned int decl_id;
   var_loc_list *temp;
-  void **slot;
   struct var_loc_node *loc = NULL;
   HOST_WIDE_INT bitsize = -1, bitpos = -1;
 
@@ -5097,15 +5262,16 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
     }
 
   decl_id = DECL_UID (decl);
-  slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
+  var_loc_list **slot
+    = decl_loc_table->find_slot_with_hash (decl, decl_id, INSERT);
   if (*slot == NULL)
     {
-      temp = ggc_alloc_cleared_var_loc_list ();
+      temp = ggc_cleared_alloc<var_loc_list> ();
       temp->decl_id = decl_id;
       *slot = temp;
     }
   else
-    temp = (var_loc_list *) *slot;
+    temp = *slot;
 
   /* For PARM_DECLs try to keep around the original incoming value,
      even if that means we'll emit a zero-range .debug_loc entry.  */
@@ -5125,7 +5291,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
          || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
              != NOTE_VAR_LOCATION_STATUS (loc_note))))
     {
-      loc = ggc_alloc_cleared_var_loc_node ();
+      loc = ggc_cleared_alloc<var_loc_node> ();
       temp->first->next = loc;
       temp->last = loc;
       loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -5134,7 +5300,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
     {
       struct var_loc_node *last = temp->last, *unused = NULL;
       rtx *piece_loc = NULL, last_loc_note;
-      int piece_bitpos = 0;
+      HOST_WIDE_INT piece_bitpos = 0;
       if (last->next)
        {
          last = last->next;
@@ -5145,7 +5311,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
          piece_loc = &last->loc;
          do
            {
-             int cur_bitsize = decl_piece_bitsize (*piece_loc);
+             HOST_WIDE_INT cur_bitsize = decl_piece_bitsize (*piece_loc);
              if (piece_bitpos + cur_bitsize > bitpos)
                break;
              piece_bitpos += cur_bitsize;
@@ -5215,7 +5381,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
              memset (loc, '\0', sizeof (*loc));
            }
          else
-           loc = ggc_alloc_cleared_var_loc_node ();
+           loc = ggc_cleared_alloc<var_loc_node> ();
          if (bitsize == -1 || piece_loc == NULL)
            loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
          else
@@ -5232,7 +5398,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
     }
   else
     {
-      loc = ggc_alloc_cleared_var_loc_node ();
+      loc = ggc_cleared_alloc<var_loc_node> ();
       temp->first = loc;
       temp->last = loc;
       loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -5264,6 +5430,173 @@ print_signature (FILE *outfile, char *sig)
     fprintf (outfile, "%02x", sig[i] & 0xff);
 }
 
+static void print_loc_descr (dw_loc_descr_ref, FILE *);
+
+/* Print the value associated to the VAL DWARF value node to OUTFILE.  If
+   RECURSE, output location descriptor operations.  */
+
+static void
+print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
+{
+  switch (val->val_class)
+    {
+    case dw_val_class_addr:
+      fprintf (outfile, "address");
+      break;
+    case dw_val_class_offset:
+      fprintf (outfile, "offset");
+      break;
+    case dw_val_class_loc:
+      fprintf (outfile, "location descriptor");
+      if (val->v.val_loc == NULL)
+       fprintf (outfile, " -> <null>\n");
+      else if (recurse)
+       {
+         fprintf (outfile, ":\n");
+         print_indent += 4;
+         print_loc_descr (val->v.val_loc, outfile);
+         print_indent -= 4;
+       }
+      else
+       fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+      break;
+    case dw_val_class_loc_list:
+      fprintf (outfile, "location list -> label:%s",
+              val->v.val_loc_list->ll_symbol);
+      break;
+    case dw_val_class_range_list:
+      fprintf (outfile, "range list");
+      break;
+    case dw_val_class_const:
+      fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
+      break;
+    case dw_val_class_unsigned_const:
+      fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
+      break;
+    case dw_val_class_const_double:
+      fprintf (outfile, "constant (" HOST_WIDE_INT_PRINT_DEC","\
+                       HOST_WIDE_INT_PRINT_UNSIGNED")",
+              val->v.val_double.high,
+              val->v.val_double.low);
+      break;
+    case dw_val_class_wide_int:
+      {
+       int i = val->v.val_wide->get_len ();
+       fprintf (outfile, "constant (");
+       gcc_assert (i > 0);
+       if (val->v.val_wide->elt (i - 1) == 0)
+         fprintf (outfile, "0x");
+       fprintf (outfile, HOST_WIDE_INT_PRINT_HEX,
+                val->v.val_wide->elt (--i));
+       while (--i >= 0)
+         fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX,
+                  val->v.val_wide->elt (i));
+       fprintf (outfile, ")");
+       break;
+      }
+    case dw_val_class_vec:
+      fprintf (outfile, "floating-point or vector constant");
+      break;
+    case dw_val_class_flag:
+      fprintf (outfile, "%u", val->v.val_flag);
+      break;
+    case dw_val_class_die_ref:
+      if (val->v.val_die_ref.die != NULL)
+       {
+         dw_die_ref die = val->v.val_die_ref.die;
+
+         if (die->comdat_type_p)
+           {
+             fprintf (outfile, "die -> signature: ");
+             print_signature (outfile,
+                              die->die_id.die_type_node->signature);
+           }
+         else if (die->die_id.die_symbol)
+           fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
+         else
+           fprintf (outfile, "die -> %ld", die->die_offset);
+         fprintf (outfile, " (%p)", (void *) die);
+       }
+      else
+       fprintf (outfile, "die -> <null>");
+      break;
+    case dw_val_class_vms_delta:
+      fprintf (outfile, "delta: @slotcount(%s-%s)",
+              val->v.val_vms_delta.lbl2, val->v.val_vms_delta.lbl1);
+      break;
+    case dw_val_class_lbl_id:
+    case dw_val_class_lineptr:
+    case dw_val_class_macptr:
+    case dw_val_class_high_pc:
+      fprintf (outfile, "label: %s", val->v.val_lbl_id);
+      break;
+    case dw_val_class_str:
+      if (val->v.val_str->str != NULL)
+       fprintf (outfile, "\"%s\"", val->v.val_str->str);
+      else
+       fprintf (outfile, "<null>");
+      break;
+    case dw_val_class_file:
+      fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename,
+              val->v.val_file->emitted_number);
+      break;
+    case dw_val_class_data8:
+      {
+       int i;
+
+       for (i = 0; i < 8; i++)
+         fprintf (outfile, "%02x", val->v.val_data8[i]);
+       break;
+      }
+    default:
+      break;
+    }
+}
+
+/* Likewise, for a DIE attribute.  */
+
+static void
+print_attribute (dw_attr_ref a, bool recurse, FILE *outfile)
+{
+  print_dw_val (&a->dw_attr_val, recurse, outfile);
+}
+
+
+/* Print the list of operands in the LOC location description to OUTFILE.  This
+   routine is a debugging aid only.  */
+
+static void
+print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
+{
+  dw_loc_descr_ref l = loc;
+
+  if (loc == NULL)
+    {
+      print_spaces (outfile);
+      fprintf (outfile, "<null>\n");
+      return;
+    }
+
+  for (l = loc; l != NULL; l = l->dw_loc_next)
+    {
+      print_spaces (outfile);
+      fprintf (outfile, "(%p) %s",
+              (void *) l,
+              dwarf_stack_op_name (l->dw_loc_opc));
+      if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
+       {
+         fprintf (outfile, " ");
+         print_dw_val (&l->dw_loc_oprnd1, false, outfile);
+       }
+      if (l->dw_loc_oprnd2.val_class != dw_val_class_none)
+       {
+         fprintf (outfile, ", ");
+         print_dw_val (&l->dw_loc_oprnd2, false, outfile);
+       }
+      fprintf (outfile, "\n");
+    }
+}
+
 /* Print the information associated with a given DIE, and its children.
    This routine is a debugging aid only.  */
 
@@ -5296,93 +5629,7 @@ print_die (dw_die_ref die, FILE *outfile)
       print_spaces (outfile);
       fprintf (outfile, "  %s: ", dwarf_attr_name (a->dw_attr));
 
-      switch (AT_class (a))
-       {
-       case dw_val_class_addr:
-         fprintf (outfile, "address");
-         break;
-       case dw_val_class_offset:
-         fprintf (outfile, "offset");
-         break;
-       case dw_val_class_loc:
-         fprintf (outfile, "location descriptor");
-         break;
-       case dw_val_class_loc_list:
-         fprintf (outfile, "location list -> label:%s",
-                  AT_loc_list (a)->ll_symbol);
-         break;
-       case dw_val_class_range_list:
-         fprintf (outfile, "range list");
-         break;
-       case dw_val_class_const:
-         fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, AT_int (a));
-         break;
-       case dw_val_class_unsigned_const:
-         fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a));
-         break;
-       case dw_val_class_const_double:
-         fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
-                           HOST_WIDE_INT_PRINT_UNSIGNED")",
-                  a->dw_attr_val.v.val_double.high,
-                  a->dw_attr_val.v.val_double.low);
-         break;
-       case dw_val_class_vec:
-         fprintf (outfile, "floating-point or vector constant");
-         break;
-       case dw_val_class_flag:
-         fprintf (outfile, "%u", AT_flag (a));
-         break;
-       case dw_val_class_die_ref:
-         if (AT_ref (a) != NULL)
-           {
-             if (AT_ref (a)->comdat_type_p)
-               {
-                 fprintf (outfile, "die -> signature: ");
-                 print_signature (outfile,
-                                  AT_ref (a)->die_id.die_type_node->signature);
-                }
-             else if (AT_ref (a)->die_id.die_symbol)
-               fprintf (outfile, "die -> label: %s",
-                        AT_ref (a)->die_id.die_symbol);
-             else
-               fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
-             fprintf (outfile, " (%p)", (void *) AT_ref (a));
-           }
-         else
-           fprintf (outfile, "die -> <null>");
-         break;
-       case dw_val_class_vms_delta:
-         fprintf (outfile, "delta: @slotcount(%s-%s)",
-                  AT_vms_delta2 (a), AT_vms_delta1 (a));
-         break;
-       case dw_val_class_lbl_id:
-       case dw_val_class_lineptr:
-       case dw_val_class_macptr:
-       case dw_val_class_high_pc:
-         fprintf (outfile, "label: %s", AT_lbl (a));
-         break;
-       case dw_val_class_str:
-         if (AT_string (a) != NULL)
-           fprintf (outfile, "\"%s\"", AT_string (a));
-         else
-           fprintf (outfile, "<null>");
-         break;
-       case dw_val_class_file:
-         fprintf (outfile, "\"%s\" (%d)", AT_file (a)->filename,
-                  AT_file (a)->emitted_number);
-         break;
-       case dw_val_class_data8:
-         {
-           int i;
-
-            for (i = 0; i < 8; i++)
-              fprintf (outfile, "%02x", a->dw_attr_val.v.val_data8[i]);
-           break;
-          }
-       default:
-         break;
-       }
-
+      print_attribute (a, true, outfile);
       fprintf (outfile, "\n");
     }
 
@@ -5396,6 +5643,14 @@ print_die (dw_die_ref die, FILE *outfile)
     fprintf (outfile, "\n");
 }
 
+/* Print the list of operations in the LOC location description.  */
+
+DEBUG_FUNCTION void
+debug_dwarf_loc_descr (dw_loc_descr_ref loc)
+{
+  print_loc_descr (loc, stderr);
+}
+
 /* Print the information collected for a given DIE.  */
 
 DEBUG_FUNCTION void
@@ -5429,6 +5684,34 @@ debug_dwarf (void)
   print_indent = 0;
   print_die (comp_unit_die (), stderr);
 }
+
+/* Sanity checks on DIEs.  */
+
+static void
+check_die (dw_die_ref die)
+{
+  /* A debugging information entry that is a member of an abstract
+     instance tree [that has DW_AT_inline] should not contain any
+     attributes which describe aspects of the subroutine which vary
+     between distinct inlined expansions or distinct out-of-line
+     expansions.  */
+  unsigned ix;
+  dw_attr_ref a;
+  bool inline_found = false;
+  FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+    if (a->dw_attr == DW_AT_inline && a->dw_attr_val.v.val_unsigned)
+      inline_found = true;
+  if (inline_found)
+    {
+      /* Catch the most common mistakes.  */
+      FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+       gcc_assert (a->dw_attr != DW_AT_low_pc
+                   && a->dw_attr != DW_AT_high_pc
+                   && a->dw_attr != DW_AT_location
+                   && a->dw_attr != DW_AT_frame_base
+                   && a->dw_attr != DW_AT_GNU_all_call_sites);
+    }
+}
 \f
 /* Start a new compilation unit DIE for an include file.  OLD_UNIT is the CU
    for the enclosing include file, if any.  BINCL_DIE is the DW_TAG_GNU_BINCL
@@ -5465,11 +5748,13 @@ static inline void
 loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
 {
   int tem;
-  hashval_t hash = 0;
+  inchash::hash hstate;
+  hashval_t hash;
 
   tem = (loc->dtprel << 8) | ((unsigned int) loc->dw_loc_opc);
   CHECKSUM (tem);
-  hash = hash_loc_operands (loc, hash);
+  hash_loc_operands (loc, hstate);
+  hash = hstate.end();
   CHECKSUM (hash);
 }
 
@@ -5499,6 +5784,11 @@ attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark)
     case dw_val_class_const_double:
       CHECKSUM (at->dw_attr_val.v.val_double);
       break;
+    case dw_val_class_wide_int:
+      CHECKSUM_BLOCK (at->dw_attr_val.v.val_wide->get_val (),
+                     get_full_len (*at->dw_attr_val.v.val_wide)
+                     * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
+      break;
     case dw_val_class_vec:
       CHECKSUM_BLOCK (at->dw_attr_val.v.val_vec.array,
                      (at->dw_attr_val.v.val_vec.length
@@ -5676,11 +5966,13 @@ loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
   /* Otherwise, just checksum the raw location expression.  */
   while (loc != NULL)
     {
-      hashval_t hash = 0;
+      inchash::hash hstate;
+      hashval_t hash;
 
       CHECKSUM_ULEB128 (loc->dtprel);
       CHECKSUM_ULEB128 (loc->dw_loc_opc);
-      hash = hash_loc_operands (loc, hash);
+      hash_loc_operands (loc, hstate);
+      hash = hstate.end ();
       CHECKSUM (hash);
       loc = loc->dw_loc_next;
     }
@@ -5776,6 +6068,15 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_ref at,
       CHECKSUM (at->dw_attr_val.v.val_double);
       break;
 
+    case dw_val_class_wide_int:
+      CHECKSUM_ULEB128 (DW_FORM_block);
+      CHECKSUM_ULEB128 (get_full_len (*at->dw_attr_val.v.val_wide)
+                       * HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT);
+      CHECKSUM_BLOCK (at->dw_attr_val.v.val_wide->get_val (),
+                     get_full_len (*at->dw_attr_val.v.val_wide)
+                     * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
+      break;
+
     case dw_val_class_vec:
       CHECKSUM_ULEB128 (DW_FORM_block);
       CHECKSUM_ULEB128 (at->dw_attr_val.v.val_vec.length
@@ -6258,6 +6559,8 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
     case dw_val_class_const_double:
       return v1->v.val_double.high == v2->v.val_double.high
             && v1->v.val_double.low == v2->v.val_double.low;
+    case dw_val_class_wide_int:
+      return *v1->v.val_wide == *v2->v.val_wide;
     case dw_val_class_vec:
       if (v1->v.val_vec.length != v2->v.val_vec.length
          || v1->v.val_vec.elt_size != v2->v.val_vec.elt_size)
@@ -6619,28 +6922,28 @@ struct cu_hash_table_entry
 
 struct cu_hash_table_entry_hasher
 {
-  typedef cu_hash_table_entry value_type;
-  typedef die_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
-  static inline void remove (value_type *);
+  typedef cu_hash_table_entry *value_type;
+  typedef die_struct *compare_type;
+  static inline hashval_t hash (const cu_hash_table_entry *);
+  static inline bool equal (const cu_hash_table_entry *, const die_struct *);
+  static inline void remove (cu_hash_table_entry *);
 };
 
 inline hashval_t
-cu_hash_table_entry_hasher::hash (const value_type *entry)
+cu_hash_table_entry_hasher::hash (const cu_hash_table_entry *entry)
 {
   return htab_hash_string (entry->cu->die_id.die_symbol);
 }
 
 inline bool
-cu_hash_table_entry_hasher::equal (const value_type *entry1,
-                                  const compare_type *entry2)
+cu_hash_table_entry_hasher::equal (const cu_hash_table_entry *entry1,
+                                  const die_struct *entry2)
 {
   return !strcmp (entry1->cu->die_id.die_symbol, entry2->die_id.die_symbol);
 }
 
 inline void
-cu_hash_table_entry_hasher::remove (value_type *entry)
+cu_hash_table_entry_hasher::remove (cu_hash_table_entry *entry)
 {
   struct cu_hash_table_entry *next;
 
@@ -6652,21 +6955,21 @@ cu_hash_table_entry_hasher::remove (value_type *entry)
     }
 }
 
-typedef hash_table <cu_hash_table_entry_hasher> cu_hash_type;
+typedef hash_table<cu_hash_table_entry_hasher> cu_hash_type;
 
 /* Check whether we have already seen this CU and set up SYM_NUM
    accordingly.  */
 static int
-check_duplicate_cu (dw_die_ref cu, cu_hash_type htable, unsigned int *sym_num)
+check_duplicate_cu (dw_die_ref cu, cu_hash_type *htable, unsigned int *sym_num)
 {
   struct cu_hash_table_entry dummy;
   struct cu_hash_table_entry **slot, *entry, *last = &dummy;
 
   dummy.max_comdat_num = 0;
 
-  slot = htable.find_slot_with_hash (cu,
-                                    htab_hash_string (cu->die_id.die_symbol),
-                                    INSERT);
+  slot = htable->find_slot_with_hash (cu,
+                                     htab_hash_string (cu->die_id.die_symbol),
+                                     INSERT);
   entry = *slot;
 
   for (; entry; last = entry, entry = entry->next)
@@ -6692,14 +6995,14 @@ check_duplicate_cu (dw_die_ref cu, cu_hash_type htable, unsigned int *sym_num)
 
 /* Record SYM_NUM to record of CU in HTABLE.  */
 static void
-record_comdat_symbol_number (dw_die_ref cu, cu_hash_type htable,
+record_comdat_symbol_number (dw_die_ref cu, cu_hash_type *htable,
                             unsigned int sym_num)
 {
   struct cu_hash_table_entry **slot, *entry;
 
-  slot = htable.find_slot_with_hash (cu,
-                                    htab_hash_string (cu->die_id.die_symbol),
-                                    NO_INSERT);
+  slot = htable->find_slot_with_hash (cu,
+                                     htab_hash_string (cu->die_id.die_symbol),
+                                     NO_INSERT);
   entry = *slot;
 
   entry->max_comdat_num = sym_num;
@@ -6715,7 +7018,6 @@ break_out_includes (dw_die_ref die)
   dw_die_ref c;
   dw_die_ref unit = NULL;
   limbo_die_node *node, **pnode;
-  cu_hash_type cu_hash_table;
 
   c = die->die_child;
   if (c) do {
@@ -6748,7 +7050,7 @@ break_out_includes (dw_die_ref die)
 #endif
 
   assign_symbol_names (die);
-  cu_hash_table.create (10);
+  cu_hash_type cu_hash_table (10);
   for (node = limbo_die_list, pnode = &limbo_die_list;
        node;
        node = node->next)
@@ -6756,7 +7058,7 @@ break_out_includes (dw_die_ref die)
       int is_dupl;
 
       compute_section_prefix (node->die);
-      is_dupl = check_duplicate_cu (node->die, cu_hash_table,
+      is_dupl = check_duplicate_cu (node->die, &cu_hash_table,
                        &comdat_symbol_number);
       assign_symbol_names (node->die);
       if (is_dupl)
@@ -6764,11 +7066,10 @@ break_out_includes (dw_die_ref die)
       else
        {
          pnode = &node->next;
-         record_comdat_symbol_number (node->die, cu_hash_table,
+         record_comdat_symbol_number (node->die, &cu_hash_table,
                comdat_symbol_number);
        }
     }
-  cu_hash_table.dispose ();
 }
 
 /* Return non-zero if this DIE is a declaration.  */
@@ -6824,14 +7125,13 @@ should_move_die_to_comdat (dw_die_ref die)
     case DW_TAG_structure_type:
     case DW_TAG_enumeration_type:
     case DW_TAG_union_type:
-      /* Don't move declarations, inlined instances, or types nested in a
-        subprogram.  */
+      /* Don't move declarations, inlined instances, types nested in a
+        subprogram, or types that contain subprogram definitions.  */
       if (is_declaration_die (die)
           || get_AT (die, DW_AT_abstract_origin)
-          || is_nested_in_subprogram (die))
+          || is_nested_in_subprogram (die)
+          || contains_subprogram_definition (die))
         return 0;
-      /* A type definition should never contain a subprogram definition.  */
-      gcc_assert (!contains_subprogram_definition (die));
       return 1;
     case DW_TAG_array_type:
     case DW_TAG_interface_type:
@@ -6863,7 +7163,7 @@ clone_die (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  clone = ggc_alloc_cleared_die_node ();
+  clone = ggc_cleared_alloc<die_node> ();
   clone->die_tag = die->die_tag;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -6909,7 +7209,7 @@ clone_as_declaration (dw_die_ref die)
       return clone;
     }
 
-  clone = ggc_alloc_cleared_die_node ();
+  clone = ggc_cleared_alloc<die_node> ();
   clone->die_tag = die->die_tag;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -6920,6 +7220,7 @@ clone_as_declaration (dw_die_ref die)
 
       switch (a->dw_attr)
         {
+        case DW_AT_abstract_origin:
         case DW_AT_artificial:
         case DW_AT_containing_type:
         case DW_AT_external:
@@ -6958,26 +7259,26 @@ struct decl_table_entry
 
 struct decl_table_entry_hasher : typed_free_remove <decl_table_entry>
 {
-  typedef decl_table_entry value_type;
-  typedef die_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef decl_table_entry *value_type;
+  typedef die_struct *compare_type;
+  static inline hashval_t hash (const decl_table_entry *);
+  static inline bool equal (const decl_table_entry *, const die_struct *);
 };
 
 inline hashval_t
-decl_table_entry_hasher::hash (const value_type *entry)
+decl_table_entry_hasher::hash (const decl_table_entry *entry)
 {
   return htab_hash_pointer (entry->orig);
 }
 
 inline bool
-decl_table_entry_hasher::equal (const value_type *entry1,
-                               const compare_type *entry2)
+decl_table_entry_hasher::equal (const decl_table_entry *entry1,
+                               const die_struct *entry2)
 {
   return entry1->orig == entry2;
 }
 
-typedef hash_table <decl_table_entry_hasher> decl_hash_type;
+typedef hash_table<decl_table_entry_hasher> decl_hash_type;
 
 /* Copy DIE and its ancestors, up to, but not including, the compile unit
    or type unit entry, to a new tree.  Adds the new tree to UNIT and returns
@@ -6985,7 +7286,8 @@ typedef hash_table <decl_table_entry_hasher> decl_hash_type;
    to check if the ancestor has already been copied into UNIT.  */
 
 static dw_die_ref
-copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
+copy_ancestor_tree (dw_die_ref unit, dw_die_ref die,
+                   decl_hash_type *decl_table)
 {
   dw_die_ref parent = die->die_parent;
   dw_die_ref new_parent = unit;
@@ -6993,11 +7295,11 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
   decl_table_entry **slot = NULL;
   struct decl_table_entry *entry = NULL;
 
-  if (decl_table.is_created ())
+  if (decl_table)
     {
       /* Check if the entry has already been copied to UNIT.  */
-      slot = decl_table.find_slot_with_hash (die, htab_hash_pointer (die),
-                                            INSERT);
+      slot = decl_table->find_slot_with_hash (die, htab_hash_pointer (die),
+                                             INSERT);
       if (*slot != HTAB_EMPTY_ENTRY)
         {
           entry = *slot;
@@ -7023,7 +7325,7 @@ copy_ancestor_tree (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
   copy = clone_as_declaration (die);
   add_child_die (new_parent, copy);
 
-  if (decl_table.is_created ())
+  if (decl_table)
     {
       /* Record the pointer to the copy.  */
       entry->copy = copy;
@@ -7078,7 +7380,7 @@ copy_declaration_context (dw_die_ref unit, dw_die_ref die)
   if (decl->die_parent != NULL
       && !is_unit_die (decl->die_parent))
     {
-      new_decl = copy_ancestor_tree (unit, decl, decl_hash_type ());
+      new_decl = copy_ancestor_tree (unit, decl, NULL);
       if (new_decl != NULL)
         {
           remove_AT (new_decl, DW_AT_signature);
@@ -7152,6 +7454,12 @@ generate_skeleton_bottom_up (skeleton_chain_node *parent)
            dw_die_ref clone = clone_die (c);
            move_all_children (c, clone);
 
+           /* If the original has a DW_AT_object_pointer attribute,
+              it would now point to a child DIE just moved to the
+              cloned tree, so we need to remove that attribute from
+              the original.  */
+           remove_AT (c, DW_AT_object_pointer);
+
            replace_child (c, clone, prev);
            generate_skeleton_ancestor_tree (parent);
            add_child_die (parent->new_die, c);
@@ -7262,7 +7570,7 @@ break_out_comdat_types (dw_die_ref die)
         unit = new_die (DW_TAG_type_unit, NULL, NULL);
         add_AT_unsigned (unit, DW_AT_language,
                          get_AT_unsigned (comp_unit_die (), DW_AT_language));
-        type_node = ggc_alloc_cleared_comdat_type_node ();
+        type_node = ggc_cleared_alloc<comdat_type_node> ();
         type_node->root_die = unit;
         type_node->next = comdat_type_list;
         comdat_type_list = type_node;
@@ -7293,28 +7601,38 @@ break_out_comdat_types (dw_die_ref die)
   } while (next != NULL);
 }
 
-/* Like clone_tree, but additionally enter all the children into
-   the hash table decl_table.  */
+/* Like clone_tree, but copy DW_TAG_subprogram DIEs as declarations.
+   Enter all the cloned children into the hash table decl_table.  */
 
 static dw_die_ref
-clone_tree_hash (dw_die_ref die, decl_hash_type decl_table)
+clone_tree_partial (dw_die_ref die, decl_hash_type *decl_table)
 {
   dw_die_ref c;
-  dw_die_ref clone = clone_die (die);
+  dw_die_ref clone;
   struct decl_table_entry *entry;
-  decl_table_entry **slot = decl_table.find_slot_with_hash (die,
+  decl_table_entry **slot;
+
+  if (die->die_tag == DW_TAG_subprogram)
+    clone = clone_as_declaration (die);
+  else
+    clone = clone_die (die);
+
+  slot = decl_table->find_slot_with_hash (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.  */
+     clone_tree_partial 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)));
+  if (die->die_tag != DW_TAG_subprogram)
+    FOR_EACH_CHILD (die, c,
+                   add_child_die (clone, clone_tree_partial (c, decl_table)));
 
   return clone;
 }
@@ -7324,7 +7642,7 @@ clone_tree_hash (dw_die_ref die, decl_hash_type decl_table)
    type_unit).  */
 
 static void
-copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
+copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type *decl_table)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7341,8 +7659,9 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
           if (targ->die_mark != 0 || targ->comdat_type_p)
             continue;
 
-          slot = decl_table.find_slot_with_hash (targ, htab_hash_pointer (targ),
-                                                INSERT);
+          slot = decl_table->find_slot_with_hash (targ,
+                                                 htab_hash_pointer (targ),
+                                                 INSERT);
 
           if (*slot != HTAB_EMPTY_ENTRY)
             {
@@ -7365,9 +7684,15 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
               entry->copy = copy;
               *slot = entry;
 
-             FOR_EACH_CHILD (targ, c,
-                             add_child_die (copy,
-                                            clone_tree_hash (c, decl_table)));
+             /* If TARG is not a declaration DIE, we need to copy its
+                children.  */
+             if (!is_declaration_die (targ))
+               {
+                 FOR_EACH_CHILD (
+                     targ, c,
+                     add_child_die (copy,
+                                    clone_tree_partial (c, decl_table)));
+               }
 
               /* Make sure the cloned tree is marked as part of the
                  type unit.  */
@@ -7415,12 +7740,9 @@ copy_decls_walk (dw_die_ref unit, dw_die_ref die, decl_hash_type decl_table)
 static void
 copy_decls_for_unworthy_types (dw_die_ref unit)
 {
-  decl_hash_type decl_table;
-
   mark_dies (unit);
-  decl_table.create (10);
-  copy_decls_walk (unit, unit, decl_table);
-  decl_table.dispose ();
+  decl_hash_type decl_table (10);
+  copy_decls_walk (unit, unit, &decl_table);
   unmark_dies (unit);
 }
 
@@ -7479,14 +7801,14 @@ struct external_ref
 
 struct external_ref_hasher : typed_free_remove <external_ref>
 {
-  typedef external_ref value_type;
-  typedef external_ref compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef external_ref *value_type;
+  typedef external_ref *compare_type;
+  static inline hashval_t hash (const external_ref *);
+  static inline bool equal (const external_ref *, const external_ref *);
 };
 
 inline hashval_t
-external_ref_hasher::hash (const value_type *r)
+external_ref_hasher::hash (const external_ref *r)
 {
   dw_die_ref die = r->type;
   hashval_t h = 0;
@@ -7507,23 +7829,23 @@ external_ref_hasher::hash (const value_type *r)
 }
 
 inline bool
-external_ref_hasher::equal (const value_type *r1, const compare_type *r2)
+external_ref_hasher::equal (const external_ref *r1, const external_ref *r2)
 {
   return r1->type == r2->type;
 }
 
-typedef hash_table <external_ref_hasher> external_ref_hash_type;
+typedef hash_table<external_ref_hasher> external_ref_hash_type;
 
 /* Return a pointer to the external_ref for references to DIE.  */
 
 static struct external_ref *
-lookup_external_ref (external_ref_hash_type map, dw_die_ref die)
+lookup_external_ref (external_ref_hash_type *map, dw_die_ref die)
 {
   struct external_ref ref, *ref_p;
   external_ref **slot;
 
   ref.type = die;
-  slot = map.find_slot (&ref, INSERT);
+  slot = map->find_slot (&ref, INSERT);
   if (*slot != HTAB_EMPTY_ENTRY)
     return *slot;
 
@@ -7539,7 +7861,7 @@ lookup_external_ref (external_ref_hash_type map, dw_die_ref die)
    references, remember how many we've seen.  */
 
 static void
-optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type map)
+optimize_external_refs_1 (dw_die_ref die, external_ref_hash_type *map)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -7610,13 +7932,12 @@ dwarf2_build_local_stub (external_ref **slot, dw_die_ref data)
    them which will be applied in build_abbrev_table.  This is useful because
    references to local DIEs are smaller.  */
 
-static external_ref_hash_type
+static external_ref_hash_type *
 optimize_external_refs (dw_die_ref die)
 {
-  external_ref_hash_type map;
-  map.create (10);
+  external_ref_hash_type *map = new external_ref_hash_type (10);
   optimize_external_refs_1 (die, map);
-  map.traverse <dw_die_ref, dwarf2_build_local_stub> (die);
+  map->traverse <dw_die_ref, dwarf2_build_local_stub> (die);
   return map;
 }
 
@@ -7626,7 +7947,7 @@ optimize_external_refs (dw_die_ref die)
    die are visited recursively.  */
 
 static void
-build_abbrev_table (dw_die_ref die, external_ref_hash_type extern_map)
+build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
 {
   unsigned long abbrev_id;
   unsigned int n_alloc;
@@ -7791,6 +8112,13 @@ size_of_die (dw_die_ref die)
          if (HOST_BITS_PER_WIDE_INT >= 64)
            size++; /* block */
          break;
+       case dw_val_class_wide_int:
+         size += (get_full_len (*a->dw_attr_val.v.val_wide)
+                  * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
+         if (get_full_len (*a->dw_attr_val.v.val_wide) * HOST_BITS_PER_WIDE_INT
+             > 64)
+           size++; /* block */
+         break;
        case dw_val_class_vec:
          size += constant_size (a->dw_attr_val.v.val_vec.length
                                 * a->dw_attr_val.v.val_vec.elt_size)
@@ -8160,6 +8488,20 @@ value_format (dw_attr_ref a)
        default:
          return DW_FORM_block1;
        }
+    case dw_val_class_wide_int:
+      switch (get_full_len (*a->dw_attr_val.v.val_wide) * HOST_BITS_PER_WIDE_INT)
+       {
+       case 8:
+         return DW_FORM_data1;
+       case 16:
+         return DW_FORM_data2;
+       case 32:
+         return DW_FORM_data4;
+       case 64:
+         return DW_FORM_data8;
+       default:
+         return DW_FORM_block1;
+       }
     case dw_val_class_vec:
       switch (constant_size (a->dw_attr_val.v.val_vec.length
                             * a->dw_attr_val.v.val_vec.elt_size))
@@ -8319,7 +8661,7 @@ static inline dw_loc_list_ref
 new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
              const char *section)
 {
-  dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
+  dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
 
   retlist->begin = begin;
   retlist->begin_entry = NULL;
@@ -8599,6 +8941,32 @@ output_die (dw_die_ref die)
          }
          break;
 
+       case dw_val_class_wide_int:
+         {
+           int i;
+           int len = get_full_len (*a->dw_attr_val.v.val_wide);
+           int l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
+           if (len * HOST_BITS_PER_WIDE_INT > 64)
+             dw2_asm_output_data (1, get_full_len (*a->dw_attr_val.v.val_wide) * l,
+                                  NULL);
+
+           if (WORDS_BIG_ENDIAN)
+             for (i = len - 1; i >= 0; --i)
+               {
+                 dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
+                                      "%s", name);
+                 name = NULL;
+               }
+           else
+             for (i = 0; i < len; ++i)
+               {
+                 dw2_asm_output_data (l, a->dw_attr_val.v.val_wide->elt (i),
+                                      "%s", name);
+                 name = NULL;
+               }
+         }
+         break;
+
        case dw_val_class_vec:
          {
            unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size;
@@ -8691,9 +9059,15 @@ output_die (dw_die_ref die)
          break;
 
        case dw_val_class_vms_delta:
+#ifdef ASM_OUTPUT_DWARF_VMS_DELTA
          dw2_asm_output_vms_delta (DWARF_OFFSET_SIZE,
                                    AT_vms_delta2 (a), AT_vms_delta1 (a),
                                    "%s", name);
+#else
+         dw2_asm_output_delta (DWARF_OFFSET_SIZE,
+                               AT_vms_delta2 (a), AT_vms_delta1 (a),
+                               "%s", name);
+#endif
          break;
 
        case dw_val_class_lbl_id:
@@ -8766,7 +9140,9 @@ output_die (dw_die_ref die)
 static void
 output_compilation_unit_header (void)
 {
-  int ver = dwarf_version;
+  /* We don't support actual DWARFv5 units yet, we just use some
+     DWARFv5 draft DIE tags in DWARFv4 format.  */
+  int ver = dwarf_version < 5 ? dwarf_version : 4;
 
   if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
     dw2_asm_output_data (4, 0xffffffff,
@@ -8788,7 +9164,6 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
 {
   const char *secname, *oldsym;
   char *tmp;
-  external_ref_hash_type extern_map;
 
   /* Unless we are outputting main CU, we may throw away empty ones.  */
   if (!output_if_empty && die->die_child == NULL)
@@ -8801,11 +9176,11 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
      this CU so we know which get local refs.  */
   mark_dies (die);
 
-  extern_map = optimize_external_refs (die);
+  external_ref_hash_type *extern_map = optimize_external_refs (die);
 
   build_abbrev_table (die, extern_map);
 
-  extern_map.dispose ();
+  delete extern_map;
 
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
@@ -8874,8 +9249,8 @@ add_skeleton_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind,
   struct indirect_string_node *node;
 
   if (! skeleton_debug_str_hash)
-    skeleton_debug_str_hash = htab_create_ggc (10, debug_str_do_hash,
-                                               debug_str_eq, NULL);
+    skeleton_debug_str_hash
+      = hash_table<indirect_string_hasher>::create_ggc (10);
 
   node = find_AT_string_in_table (str, skeleton_debug_str_hash);
   find_string_form (node);
@@ -8905,31 +9280,15 @@ add_top_level_skeleton_die_attrs (dw_die_ref die)
   add_AT_lineptr (die, DW_AT_GNU_addr_base, debug_addr_section_label);
 }
 
-/* Return the single type-unit die for skeleton type units.  */
-
-static dw_die_ref
-get_skeleton_type_unit (void)
-{
-  /* For dwarf_split_debug_sections with use_type info, all type units in the
-     skeleton sections have identical dies (but different headers).  This
-     single die will be output many times.  */
-
-  static dw_die_ref skeleton_type_unit = NULL;
-
-  if (skeleton_type_unit == NULL)
-    {
-      skeleton_type_unit = new_die (DW_TAG_type_unit, NULL, NULL);
-      add_top_level_skeleton_die_attrs (skeleton_type_unit);
-      skeleton_type_unit->die_abbrev = SKELETON_TYPE_DIE_ABBREV;
-    }
-  return skeleton_type_unit;
-}
-
 /* Output skeleton debug sections that point to the dwo file.  */
 
 static void
 output_skeleton_debug_sections (dw_die_ref comp_unit)
 {
+  /* We don't support actual DWARFv5 units yet, we just use some
+     DWARFv5 draft DIE tags in DWARFv4 format.  */
+  int ver = dwarf_version < 5 ? dwarf_version : 4;
+
   /* These attributes will be found in the full debug_info section.  */
   remove_AT (comp_unit, DW_AT_producer);
   remove_AT (comp_unit, DW_AT_language);
@@ -8949,7 +9308,7 @@ output_skeleton_debug_sections (dw_die_ref comp_unit)
                        - DWARF_INITIAL_LENGTH_SIZE
                        + size_of_die (comp_unit),
                       "Length of Compilation Unit Info");
-  dw2_asm_output_data (2, dwarf_version, "DWARF version number");
+  dw2_asm_output_data (2, ver, "DWARF version number");
   dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label,
                          debug_abbrev_section,
                          "Offset Into Abbrev. Section");
@@ -8963,8 +9322,6 @@ output_skeleton_debug_sections (dw_die_ref comp_unit)
   ASM_OUTPUT_LABEL (asm_out_file, debug_skeleton_abbrev_section_label);
 
   output_die_abbrevs (SKELETON_COMP_DIE_ABBREV, comp_unit);
-  if (use_debug_types)
-    output_die_abbrevs (SKELETON_TYPE_DIE_ABBREV, get_skeleton_type_unit ());
 
   dw2_asm_output_data (1, 0, "end of skeleton .debug_abbrev");
 }
@@ -8980,16 +9337,16 @@ output_comdat_type_unit (comdat_type_node *node)
 #if defined (OBJECT_FORMAT_ELF)
   tree comdat_key;
 #endif
-  external_ref_hash_type extern_map;
 
   /* First mark all the DIEs in this CU so we know which get local refs.  */
   mark_dies (node->root_die);
 
-  extern_map = optimize_external_refs (node->root_die);
+  external_ref_hash_type *extern_map = optimize_external_refs (node->root_die);
 
   build_abbrev_table (node->root_die, extern_map);
 
-  extern_map.dispose ();
+  delete extern_map;
+  extern_map = NULL;
 
   /* Initialize the beginning DIE offset - and calculate sizes/offsets.  */
   next_die_offset = DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE;
@@ -9026,38 +9383,6 @@ output_comdat_type_unit (comdat_type_node *node)
   output_die (node->root_die);
 
   unmark_dies (node->root_die);
-
-#if defined (OBJECT_FORMAT_ELF)
-  if (dwarf_split_debug_info)
-    {
-      /* Produce the skeleton type-unit header.  */
-      const char *secname = ".debug_types";
-
-      targetm.asm_out.named_section (secname,
-                                     SECTION_DEBUG | SECTION_LINKONCE,
-                                     comdat_key);
-      if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
-        dw2_asm_output_data (4, 0xffffffff,
-          "Initial length escape value indicating 64-bit DWARF extension");
-
-      dw2_asm_output_data (DWARF_OFFSET_SIZE,
-                           DWARF_COMPILE_UNIT_HEADER_SIZE
-                           - DWARF_INITIAL_LENGTH_SIZE
-                           + size_of_die (get_skeleton_type_unit ())
-                           + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE,
-                           "Length of Type Unit Info");
-      dw2_asm_output_data (2, dwarf_version, "DWARF version number");
-      dw2_asm_output_offset (DWARF_OFFSET_SIZE,
-                             debug_skeleton_abbrev_section_label,
-                             debug_abbrev_section,
-                             "Offset Into Abbrev. Section");
-      dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
-      output_signature (node->signature, "Type Signature");
-      dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Offset to Type DIE");
-
-      output_die (get_skeleton_type_unit ());
-    }
-#endif
 }
 
 /* Return the DWARF2/3 pubname associated with a decl.  */
@@ -9336,7 +9661,7 @@ output_aranges (unsigned long aranges_length)
       "Initial length escape value indicating 64-bit DWARF extension");
   dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length,
                       "Length of Address Ranges Info");
-  /* Version number for aranges is still 2, even in DWARF3.  */
+  /* Version number for aranges is still 2, even up to DWARF5.  */
   dw2_asm_output_data (2, 2, "DWARF Version");
   if (dwarf_split_debug_info)
     dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label,
@@ -9630,11 +9955,10 @@ struct file_name_acquire_data
 
 /* Traversal function for the hash table.  */
 
-static int
-file_name_acquire (void ** slot, void *data)
+int
+file_name_acquire (dwarf_file_data **slot, file_name_acquire_data *fnad)
 {
-  struct file_name_acquire_data *fnad = (struct file_name_acquire_data *) data;
-  struct dwarf_file_data *d = (struct dwarf_file_data *) *slot;
+  struct dwarf_file_data *d = *slot;
   struct file_info *fi;
   const char *f;
 
@@ -9709,7 +10033,7 @@ output_file_names (void)
   fnad.files = files;
   fnad.used_files = 0;
   fnad.max_files = numfiles;
-  htab_traverse (file_table, file_name_acquire, &fnad);
+  file_table->traverse<file_name_acquire_data *, file_name_acquire> (&fnad);
   gcc_assert (fnad.used_files == fnad.max_files);
 
   qsort (files, numfiles, sizeof (files[0]), file_info_cmp);
@@ -10012,7 +10336,8 @@ static void
 output_line_info (bool prologue_only)
 {
   char l1[20], l2[20], p1[20], p2[20];
-  int ver = dwarf_version;
+  /* We don't support DWARFv5 line tables yet.  */
+  int ver = dwarf_version < 5 ? dwarf_version : 4;
   bool saw_one = false;
   int opc;
 
@@ -10216,6 +10541,22 @@ base_type_die (tree type)
   return base_type_result;
 }
 
+/* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM
+   named 'auto' in its type: return true for it, false otherwise.  */
+
+static inline bool
+is_cxx_auto (tree type)
+{
+  if (is_cxx ())
+    {
+      tree name = TYPE_IDENTIFIER (type);
+      if (name == get_identifier ("auto")
+         || name == get_identifier ("decltype(auto)"))
+       return true;
+    }
+  return false;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
    given input type is a Dwarf "fundamental" type.  Otherwise return null.  */
 
@@ -10231,6 +10572,7 @@ is_base_type (tree type)
     case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
+    case POINTER_BOUNDS_TYPE:
       return 1;
 
     case ARRAY_TYPE:
@@ -10249,6 +10591,8 @@ is_base_type (tree type)
       return 0;
 
     default:
+      if (is_cxx_auto (type))
+       return 0;
       gcc_unreachable ();
     }
 
@@ -10274,19 +10618,19 @@ simple_type_size_in_bits (const_tree type)
     return TYPE_ALIGN (type);
 }
 
-/* Similarly, but return a double_int instead of UHWI.  */
+/* Similarly, but return an offset_int instead of UHWI.  */
 
-static inline double_int
-double_int_type_size_in_bits (const_tree type)
+static inline offset_int
+offset_int_type_size_in_bits (const_tree type)
 {
   if (TREE_CODE (type) == ERROR_MARK)
-    return double_int::from_uhwi (BITS_PER_WORD);
+    return BITS_PER_WORD;
   else if (TYPE_SIZE (type) == NULL_TREE)
-    return double_int_zero;
+    return 0;
   else if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
-    return tree_to_double_int (TYPE_SIZE (type));
+    return wi::to_offset (TYPE_SIZE (type));
   else
-    return double_int::from_uhwi (TYPE_ALIGN (type));
+    return TYPE_ALIGN (type);
 }
 
 /*  Given a pointer to a tree node for a subrange type, return a pointer
@@ -10311,19 +10655,65 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
     }
 
   if (low)
-    add_bound_info (subrange_die, DW_AT_lower_bound, low);
+    add_bound_info (subrange_die, DW_AT_lower_bound, low, NULL);
   if (high)
-    add_bound_info (subrange_die, DW_AT_upper_bound, high);
+    add_bound_info (subrange_die, DW_AT_upper_bound, high, NULL);
 
   return subrange_die;
 }
 
+/* Returns the (const and/or volatile) cv_qualifiers associated with
+   the decl node.  This will normally be augmented with the
+   cv_qualifiers of the underlying type in add_type_attribute.  */
+
+static int
+decl_quals (const_tree decl)
+{
+  return ((TREE_READONLY (decl)
+          ? TYPE_QUAL_CONST : TYPE_UNQUALIFIED)
+         | (TREE_THIS_VOLATILE (decl)
+            ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED));
+}
+
+/* Determine the TYPE whose qualifiers match the largest strict subset
+   of the given TYPE_QUALS, and return its qualifiers.  Ignore all
+   qualifiers outside QUAL_MASK.  */
+
+static int
+get_nearest_type_subqualifiers (tree type, int type_quals, int qual_mask)
+{
+  tree t;
+  int best_rank = 0, best_qual = 0, max_rank;
+
+  type_quals &= qual_mask;
+  max_rank = popcount_hwi (type_quals) - 1;
+
+  for (t = TYPE_MAIN_VARIANT (type); t && best_rank < max_rank;
+       t = TYPE_NEXT_VARIANT (t))
+    {
+      int q = TYPE_QUALS (t) & qual_mask;
+
+      if ((q & type_quals) == q && q != type_quals
+         && check_base_type (t, type))
+       {
+         int rank = popcount_hwi (q);
+
+         if (rank > best_rank)
+           {
+             best_rank = rank;
+             best_qual = q;
+           }
+       }
+    }
+
+  return best_qual;
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
    entry that chains various modifiers in front of the given type.  */
 
 static dw_die_ref
-modified_type_die (tree type, int is_const_type, int is_volatile_type,
-                  dw_die_ref context_die)
+modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
 {
   enum tree_code code = TREE_CODE (type);
   dw_die_ref mod_type_die;
@@ -10332,16 +10722,28 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
   tree qualified_type;
   tree name, low, high;
   dw_die_ref mod_scope;
+  /* Only these cv-qualifiers are currently handled.  */
+  const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
+                           | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC);
 
   if (code == ERROR_MARK)
     return NULL;
 
+  cv_quals &= cv_qual_mask;
+
+  /* Don't emit DW_TAG_restrict_type for DWARFv2, since it is a type
+     tag modifier (and not an attribute) old consumers won't be able
+     to handle it.  */
+  if (dwarf_version < 3)
+    cv_quals &= ~TYPE_QUAL_RESTRICT;
+
+  /* Likewise for DW_TAG_atomic_type for DWARFv5.  */
+  if (dwarf_version < 5)
+    cv_quals &= ~TYPE_QUAL_ATOMIC;
+
   /* See if we already have the appropriately qualified variant of
      this type.  */
-  qualified_type
-    = get_qualified_type (type,
-                         ((is_const_type ? TYPE_QUAL_CONST : 0)
-                          | (is_volatile_type ? TYPE_QUAL_VOLATILE : 0)));
+  qualified_type = get_qualified_type (type, cv_quals);
 
   if (qualified_type == sizetype
       && TYPE_NAME (qualified_type)
@@ -10379,35 +10781,50 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
          gen_type_die (qualified_type, context_die);
          return lookup_type_die (qualified_type);
        }
-      else if (is_const_type < TYPE_READONLY (dtype)
-              || is_volatile_type < TYPE_VOLATILE (dtype)
-              || (is_const_type <= TYPE_READONLY (dtype)
-                  && is_volatile_type <= TYPE_VOLATILE (dtype)
-                  && DECL_ORIGINAL_TYPE (name) != type))
-       /* cv-unqualified version of named type.  Just use the unnamed
-          type to which it refers.  */
-       return modified_type_die (DECL_ORIGINAL_TYPE (name),
-                                 is_const_type, is_volatile_type,
-                                 context_die);
-      /* Else cv-qualified version of named type; fall through.  */
+      else
+       {
+         int dquals = TYPE_QUALS_NO_ADDR_SPACE (dtype);
+         dquals &= cv_qual_mask;
+         if ((dquals & ~cv_quals) != TYPE_UNQUALIFIED
+             || (cv_quals == dquals && DECL_ORIGINAL_TYPE (name) != type))
+           /* cv-unqualified version of named type.  Just use
+              the unnamed type to which it refers.  */
+           return modified_type_die (DECL_ORIGINAL_TYPE (name),
+                                     cv_quals, context_die);
+         /* Else cv-qualified version of named type; fall through.  */
+       }
     }
 
   mod_scope = scope_die_for (type, context_die);
 
-  if (is_const_type
-      /* If both is_const_type and is_volatile_type, prefer the path
-        which leads to a qualified type.  */
-      && (!is_volatile_type
-         || get_qualified_type (type, TYPE_QUAL_CONST) == NULL_TREE
-         || get_qualified_type (type, TYPE_QUAL_VOLATILE) != NULL_TREE))
-    {
-      mod_type_die = new_die (DW_TAG_const_type, mod_scope, type);
-      sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
-    }
-  else if (is_volatile_type)
+  if (cv_quals)
     {
-      mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type);
-      sub_die = modified_type_die (type, is_const_type, 0, context_die);
+      struct qual_info { int q; enum dwarf_tag t; };
+      static const struct qual_info qual_info[] =
+       {
+         { TYPE_QUAL_ATOMIC, DW_TAG_atomic_type },
+         { TYPE_QUAL_RESTRICT, DW_TAG_restrict_type },
+         { TYPE_QUAL_VOLATILE, DW_TAG_volatile_type },
+         { TYPE_QUAL_CONST, DW_TAG_const_type },
+       };
+      int sub_quals;
+      unsigned i;
+
+      /* Determine a lesser qualified type that most closely matches
+        this one.  Then generate DW_TAG_* entries for the remaining
+        qualifiers.  */
+      sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
+                                                 cv_qual_mask);
+      mod_type_die = modified_type_die (type, sub_quals, context_die);
+
+      for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
+       if (qual_info[i].q & cv_quals & ~sub_quals)
+         {
+           dw_die_ref d = new_die (qual_info[i].t, mod_scope, type);
+           if (mod_type_die)
+             add_AT_die_ref (d, DW_AT_type, mod_type_die);
+           mod_type_die = d;
+         }
     }
   else if (code == POINTER_TYPE)
     {
@@ -10468,7 +10885,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
   if (name
       && ((TREE_CODE (name) != TYPE_DECL
           && (qualified_type == TYPE_MAIN_VARIANT (type)
-              || (!is_const_type && !is_volatile_type)))
+              || (cv_quals == TYPE_UNQUALIFIED)))
          || (TREE_CODE (name) == TYPE_DECL
              && TREE_TYPE (name) == qualified_type
              && DECL_NAME (name))))
@@ -10483,10 +10900,7 @@ 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)
     {
-      name = TYPE_NAME (type);
-      if (name
-         && TREE_CODE (name) == TYPE_DECL)
-       name = DECL_NAME (name);
+      name = TYPE_IDENTIFIER (type);
       add_name_attribute (mod_type_die,
                          name ? IDENTIFIER_POINTER (name) : "__unknown__");
     }
@@ -10500,8 +10914,7 @@ modified_type_die (tree type, int is_const_type, int is_volatile_type,
        recursion will terminate even if the type is recursive.  Recursive
        types are possible in Ada.  */
     sub_die = modified_type_die (item_type,
-                                TYPE_READONLY (item_type),
-                                TYPE_VOLATILE (item_type),
+                                TYPE_QUALS_NO_ADDR_SPACE (item_type),
                                 context_die);
 
   if (sub_die != NULL)
@@ -10643,8 +11056,9 @@ generic_parameter_die (tree parm, tree arg,
             If PARM is a type generic parameter, TMPL_DIE should have a
             child DW_AT_type that is set to ARG.  */
          tmpl_type = TYPE_P (arg) ? arg : TREE_TYPE (arg);
-         add_type_attribute (tmpl_die, tmpl_type, 0,
-                             TREE_THIS_VOLATILE (tmpl_type),
+         add_type_attribute (tmpl_die, tmpl_type,
+                             (TREE_THIS_VOLATILE (tmpl_type)
+                              ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED),
                              parent_die);
        }
       else
@@ -10789,7 +11203,7 @@ reg_loc_descriptor (rtx rtl, enum var_init_status initialized)
 
   regs = targetm.dwarf_register_span (rtl);
 
-  if (hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)] > 1 || regs)
+  if (REG_NREGS (rtl) > 1 || regs)
     return multiple_reg_loc_descriptor (rtl, regs, initialized);
   else
     {
@@ -10846,7 +11260,7 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs,
 #endif
 
       gcc_assert ((unsigned) DBX_REGISTER_NUMBER (reg) == dbx_reg_number (rtl));
-      nregs = hard_regno_nregs[REGNO (rtl)][GET_MODE (rtl)];
+      nregs = REG_NREGS (rtl);
 
       size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs;
 
@@ -11224,7 +11638,7 @@ tls_mem_loc_descriptor (rtx mem)
       || !DECL_THREAD_LOCAL_P (base))
     return NULL;
 
-  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1);
+  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1, NULL);
   if (loc_result == NULL)
     return NULL;
 
@@ -11254,14 +11668,11 @@ expansion_failed (tree expr, rtx rtl, char const *reason)
     }
 }
 
-/* Helper function for const_ok_for_output, called either directly
-   or via for_each_rtx.  */
+/* Helper function for const_ok_for_output.  */
 
-static int
-const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
+static bool
+const_ok_for_output_1 (rtx rtl)
 {
-  rtx rtl = *rtlp;
-
   if (GET_CODE (rtl) == UNSPEC)
     {
       /* If delegitimize_address couldn't do anything with the UNSPEC, assume
@@ -11289,18 +11700,27 @@ const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
 #endif
       expansion_failed (NULL_TREE, rtl,
                        "UNSPEC hasn't been delegitimized.\n");
-      return 1;
+      return false;
     }
 
   if (targetm.const_not_ok_for_debug_p (rtl))
     {
       expansion_failed (NULL_TREE, rtl,
                        "Expression rejected for debug by the backend.\n");
-      return 1;
+      return false;
     }
 
+  /* FIXME: Refer to PR60655. It is possible for simplification
+     of rtl expressions in var tracking to produce such expressions.
+     We should really identify / validate expressions
+     enclosed in CONST that can be handled by assemblers on various
+     targets and only handle legitimate cases here.  */
   if (GET_CODE (rtl) != SYMBOL_REF)
-    return 0;
+    {
+      if (GET_CODE (rtl) == NOT)
+       return false;
+      return true;
+    }
 
   if (CONSTANT_POOL_ADDRESS_P (rtl))
     {
@@ -11312,12 +11732,12 @@ const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
        {
          expansion_failed (NULL_TREE, rtl,
                            "Constant was removed from constant pool.\n");
-         return 1;
+         return false;
        }
     }
 
   if (SYMBOL_REF_TLS_MODEL (rtl) != TLS_MODEL_NONE)
-    return 1;
+    return false;
 
   /* Avoid references to external symbols in debug info, on several targets
      the linker might even refuse to link when linking a shared library,
@@ -11332,11 +11752,11 @@ const_ok_for_output_1 (rtx *rtlp, void *data ATTRIBUTE_UNUSED)
        {
          expansion_failed (NULL_TREE, rtl,
                            "Symbol not defined in current TU.\n");
-         return 1;
+         return false;
        }
     }
 
-  return 0;
+  return true;
 }
 
 /* Return true if constant RTL can be emitted in DW_OP_addr or
@@ -11347,10 +11767,16 @@ static bool
 const_ok_for_output (rtx rtl)
 {
   if (GET_CODE (rtl) == SYMBOL_REF)
-    return const_ok_for_output_1 (&rtl, NULL) == 0;
+    return const_ok_for_output_1 (rtl);
 
   if (GET_CODE (rtl) == CONST)
-    return for_each_rtx (&XEXP (rtl, 0), const_ok_for_output_1, NULL) == 0;
+    {
+      subrtx_var_iterator::array_type array;
+      FOR_EACH_SUBRTX_VAR (iter, array, XEXP (rtl, 0), ALL)
+       if (!const_ok_for_output_1 (*iter))
+         return false;
+      return true;
+    }
 
   return true;
 }
@@ -11359,7 +11785,7 @@ const_ok_for_output (rtx rtl)
    if possible, NULL otherwise.  */
 
 static dw_die_ref
-base_type_for_mode (enum machine_mode mode, bool unsignedp)
+base_type_for_mode (machine_mode mode, bool unsignedp)
 {
   dw_die_ref type_die;
   tree type = lang_hooks.types.type_for_mode (mode, unsignedp);
@@ -11376,7 +11802,7 @@ base_type_for_mode (enum machine_mode mode, bool unsignedp)
     }
   type_die = lookup_type_die (type);
   if (!type_die)
-    type_die = modified_type_die (type, false, false, comp_unit_die ());
+    type_die = modified_type_die (type, TYPE_UNQUALIFIED, comp_unit_die ());
   if (type_die == NULL || type_die->die_tag != DW_TAG_base_type)
     return NULL;
   return type_die;
@@ -11388,9 +11814,9 @@ base_type_for_mode (enum machine_mode mode, bool unsignedp)
    possible.  */
 
 static dw_loc_descr_ref
-convert_descriptor_to_mode (enum machine_mode mode, dw_loc_descr_ref op)
+convert_descriptor_to_mode (machine_mode mode, dw_loc_descr_ref op)
 {
-  enum machine_mode outer_mode = mode;
+  machine_mode outer_mode = mode;
   dw_die_ref type_die;
   dw_loc_descr_ref cvt;
 
@@ -11431,9 +11857,9 @@ compare_loc_descriptor (enum dwarf_location_atom op, dw_loc_descr_ref op0,
 
 static dw_loc_descr_ref
 scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
-                        enum machine_mode mem_mode)
+                        machine_mode mem_mode)
 {
-  enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
+  machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
   dw_loc_descr_ref op0, op1;
   int shift;
 
@@ -11541,9 +11967,9 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
 
 static dw_loc_descr_ref
 ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
-                        enum machine_mode mem_mode)
+                        machine_mode mem_mode)
 {
-  enum machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
+  machine_mode op_mode = GET_MODE (XEXP (rtl, 0));
   dw_loc_descr_ref op0, op1;
 
   if (op_mode == VOIDmode)
@@ -11609,8 +12035,8 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
 /* Return location descriptor for {U,S}{MIN,MAX}.  */
 
 static dw_loc_descr_ref
-minmax_loc_descriptor (rtx rtl, enum machine_mode mode,
-                      enum machine_mode mem_mode)
+minmax_loc_descriptor (rtx rtl, machine_mode mode,
+                      machine_mode mem_mode)
 {
   enum dwarf_location_atom op;
   dw_loc_descr_ref op0, op1, ret;
@@ -11705,7 +12131,7 @@ minmax_loc_descriptor (rtx rtl, enum machine_mode mode,
 
 static dw_loc_descr_ref
 typed_binop (enum dwarf_location_atom op, rtx rtl, dw_die_ref type_die,
-            enum machine_mode mode, enum machine_mode mem_mode)
+            machine_mode mode, machine_mode mem_mode)
 {
   dw_loc_descr_ref cvt, op0, op1;
 
@@ -11761,8 +12187,8 @@ typed_binop (enum dwarf_location_atom op, rtx rtl, dw_die_ref type_die,
    L4: DW_OP_nop  */
 
 static dw_loc_descr_ref
-clz_loc_descriptor (rtx rtl, enum machine_mode mode,
-                   enum machine_mode mem_mode)
+clz_loc_descriptor (rtx rtl, machine_mode mode,
+                   machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
   HOST_WIDE_INT valv;
@@ -11773,9 +12199,7 @@ clz_loc_descriptor (rtx rtl, enum machine_mode mode,
   rtx msb;
 
   if (GET_MODE_CLASS (mode) != MODE_INT
-      || GET_MODE (XEXP (rtl, 0)) != mode
-      || (GET_CODE (rtl) == CLZ
-         && GET_MODE_BITSIZE (mode) > HOST_BITS_PER_DOUBLE_INT))
+      || GET_MODE (XEXP (rtl, 0)) != mode)
     return NULL;
 
   op0 = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
@@ -11819,9 +12243,9 @@ clz_loc_descriptor (rtx rtl, enum machine_mode mode,
     msb = GEN_INT ((unsigned HOST_WIDE_INT) 1
                   << (GET_MODE_BITSIZE (mode) - 1));
   else
-    msb = immed_double_const (0, (unsigned HOST_WIDE_INT) 1
-                                 << (GET_MODE_BITSIZE (mode)
-                                     - HOST_BITS_PER_WIDE_INT - 1), mode);
+    msb = immed_wide_int_const
+      (wi::set_bit_in_zero (GET_MODE_PRECISION (mode) - 1,
+                           GET_MODE_PRECISION (mode)), mode);
   if (GET_CODE (msb) == CONST_INT && INTVAL (msb) < 0)
     tmp = new_loc_descr (HOST_BITS_PER_WIDE_INT == 32
                         ? DW_OP_const4u : HOST_BITS_PER_WIDE_INT == 64
@@ -11875,8 +12299,8 @@ clz_loc_descriptor (rtx rtl, enum machine_mode mode,
    L2: DW_OP_drop  */
 
 static dw_loc_descr_ref
-popcount_loc_descriptor (rtx rtl, enum machine_mode mode,
-                        enum machine_mode mem_mode)
+popcount_loc_descriptor (rtx rtl, machine_mode mode,
+                        machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
   dw_loc_descr_ref l1jump, l1label;
@@ -11936,8 +12360,8 @@ popcount_loc_descriptor (rtx rtl, enum machine_mode mode,
    L2: DW_OP_drop DW_OP_swap DW_OP_drop  */
 
 static dw_loc_descr_ref
-bswap_loc_descriptor (rtx rtl, enum machine_mode mode,
-                     enum machine_mode mem_mode)
+bswap_loc_descriptor (rtx rtl, machine_mode mode,
+                     machine_mode mem_mode)
 {
   dw_loc_descr_ref op0, ret, tmp;
   dw_loc_descr_ref l1jump, l1label;
@@ -12021,8 +12445,8 @@ bswap_loc_descriptor (rtx rtl, enum machine_mode mode,
    [ DW_OP_swap constMASK DW_OP_and DW_OP_swap ] DW_OP_shr DW_OP_or  */
 
 static dw_loc_descr_ref
-rotate_loc_descriptor (rtx rtl, enum machine_mode mode,
-                      enum machine_mode mem_mode)
+rotate_loc_descriptor (rtx rtl, machine_mode mode,
+                      machine_mode mem_mode)
 {
   rtx rtlop1 = XEXP (rtl, 1);
   dw_loc_descr_ref op0, op1, ret, mask[2] = { NULL, NULL };
@@ -12136,8 +12560,8 @@ parameter_ref_descriptor (rtx rtl)
    Return 0 if we can't represent the location.  */
 
 dw_loc_descr_ref
-mem_loc_descriptor (rtx rtl, enum machine_mode mode,
-                   enum machine_mode mem_mode,
+mem_loc_descriptor (rtx rtl, machine_mode mode,
+                   machine_mode mem_mode,
                    enum var_init_status initialized)
 {
   dw_loc_descr_ref mem_loc_result = NULL;
@@ -12304,7 +12728,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
                  masking.  */
               && GET_MODE_SIZE (GET_MODE (XEXP (rtl, 0))) <= 4)
        {
-         enum machine_mode imode = GET_MODE (XEXP (rtl, 0));
+         machine_mode imode = GET_MODE (XEXP (rtl, 0));
          mem_loc_result = op0;
          add_loc_descr (&mem_loc_result,
                         int_loc_descriptor (GET_MODE_MASK (imode)));
@@ -12406,7 +12830,8 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
         pool.  */
     case CONST:
     case SYMBOL_REF:
-      if (GET_MODE_CLASS (mode) != MODE_INT
+      if ((GET_MODE_CLASS (mode) != MODE_INT
+          && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
          || (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
 #ifdef POINTERS_EXTEND_UNSIGNED
              && (mode != Pmode || mem_mode == VOIDmode)
@@ -12431,7 +12856,12 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
        }
 
       if (!const_ok_for_output (rtl))
-       break;
+       {
+         if (GET_CODE (rtl) == CONST)
+           mem_loc_result = mem_loc_descriptor (XEXP (rtl, 0), mode, mem_mode,
+                                                initialized);
+         break;
+       }
 
     symref:
       mem_loc_result = new_addr_loc_descr (rtl, dtprel_false);
@@ -12528,7 +12958,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
              op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode,
                                        VAR_INIT_STATUS_INITIALIZED);
              if (op1 == 0)
-               break;
+               return NULL;
              add_loc_descr (&mem_loc_result, op1);
              add_loc_descr (&mem_loc_result,
                             new_loc_descr (DW_OP_plus, 0, 0));
@@ -12704,7 +13134,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
              || GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT))
        {
          dw_die_ref type_die = base_type_for_mode (mode, 1);
-         enum machine_mode amode;
+         machine_mode amode;
          if (type_die == NULL)
            return NULL;
          amode = mode_for_size (DWARF2_ADDR_SIZE * BITS_PER_UNIT,
@@ -12747,10 +13177,14 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
        {
          dw_die_ref type_die;
 
-         /* Note that a CONST_DOUBLE rtx could represent either an integer
-            or a floating-point constant.  A CONST_DOUBLE is used whenever
-            the constant requires more than one word in order to be
-            adequately represented.  We output CONST_DOUBLEs as blocks.  */
+         /* Note that if TARGET_SUPPORTS_WIDE_INT == 0, a
+            CONST_DOUBLE rtx could represent either a large integer
+            or a floating-point constant.  If TARGET_SUPPORTS_WIDE_INT != 0,
+            the value is always a floating point constant.
+
+            When it is an integer, a CONST_DOUBLE is used whenever
+            the constant requires 2 HWIs to be adequately represented.
+            We output CONST_DOUBLEs as blocks.  */
          if (mode == VOIDmode
              || (GET_MODE (rtl) == VOIDmode
                  && GET_MODE_BITSIZE (mode) != HOST_BITS_PER_DOUBLE_INT))
@@ -12763,11 +13197,19 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
          mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
          mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
          mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
-         if (SCALAR_FLOAT_MODE_P (mode))
+#if TARGET_SUPPORTS_WIDE_INT == 0
+         if (!SCALAR_FLOAT_MODE_P (mode))
+           {
+             mem_loc_result->dw_loc_oprnd2.val_class
+               = dw_val_class_const_double;
+             mem_loc_result->dw_loc_oprnd2.v.val_double
+               = rtx_to_double_int (rtl);
+           }
+         else
+#endif
            {
              unsigned int length = GET_MODE_SIZE (mode);
-             unsigned char *array
-                 = (unsigned char*) ggc_alloc_atomic (length);
+             unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
              insert_float (rtl, array);
              mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
@@ -12775,13 +13217,26 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
              mem_loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4;
              mem_loc_result->dw_loc_oprnd2.v.val_vec.array = array;
            }
-         else
-           {
-             mem_loc_result->dw_loc_oprnd2.val_class
-               = dw_val_class_const_double;
-             mem_loc_result->dw_loc_oprnd2.v.val_double
-               = rtx_to_double_int (rtl);
-           }
+       }
+      break;
+
+    case CONST_WIDE_INT:
+      if (!dwarf_strict)
+       {
+         dw_die_ref type_die;
+
+         type_die = base_type_for_mode (mode,
+                                        GET_MODE_CLASS (mode) == MODE_INT);
+         if (type_die == NULL)
+           return NULL;
+         mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
+         mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
+         mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
+         mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
+         mem_loc_result->dw_loc_oprnd2.val_class
+           = dw_val_class_wide_int;
+         mem_loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<wide_int> ();
+         *mem_loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
        }
       break;
 
@@ -13025,7 +13480,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode,
       break;
 
     case CONST_STRING:
-      resolve_one_addr (&rtl, NULL);
+      resolve_one_addr (&rtl);
       goto symref;
 
     default:
@@ -13143,7 +13598,7 @@ implicit_ptr_descriptor (rtx rtl, HOST_WIDE_INT offset)
    If we don't know how to describe it, return 0.  */
 
 static dw_loc_descr_ref
-loc_descriptor (rtx rtl, enum machine_mode mode,
+loc_descriptor (rtx rtl, machine_mode mode,
                enum var_init_status initialized)
 {
   dw_loc_descr_ref loc_result = NULL;
@@ -13207,7 +13662,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
       {
        rtvec par_elems = XVEC (rtl, 0);
        int num_elem = GET_NUM_ELEM (par_elems);
-       enum machine_mode mode;
+       machine_mode mode;
        int i;
 
        /* Create the first one, so we have something to add to.  */
@@ -13252,11 +13707,18 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
             adequately represented.  We output CONST_DOUBLEs as blocks.  */
          loc_result = new_loc_descr (DW_OP_implicit_value,
                                      GET_MODE_SIZE (mode), 0);
-         if (SCALAR_FLOAT_MODE_P (mode))
+#if TARGET_SUPPORTS_WIDE_INT == 0
+         if (!SCALAR_FLOAT_MODE_P (mode))
+           {
+             loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
+             loc_result->dw_loc_oprnd2.v.val_double
+               = rtx_to_double_int (rtl);
+           }
+         else
+#endif
            {
              unsigned int length = GET_MODE_SIZE (mode);
-             unsigned char *array
-                  = (unsigned char*) ggc_alloc_atomic (length);
+             unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
              insert_float (rtl, array);
              loc_result->dw_loc_oprnd2.val_class = dw_val_class_vec;
@@ -13264,12 +13726,20 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
              loc_result->dw_loc_oprnd2.v.val_vec.elt_size = 4;
              loc_result->dw_loc_oprnd2.v.val_vec.array = array;
            }
-         else
-           {
-             loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
-             loc_result->dw_loc_oprnd2.v.val_double
-               = rtx_to_double_int (rtl);
-           }
+       }
+      break;
+
+    case CONST_WIDE_INT:
+      if (mode == VOIDmode)
+       mode = GET_MODE (rtl);
+
+      if (mode != VOIDmode && (dwarf_version >= 4 || !dwarf_strict))
+       {
+         loc_result = new_loc_descr (DW_OP_implicit_value,
+                                     GET_MODE_SIZE (mode), 0);
+         loc_result->dw_loc_oprnd2.val_class = dw_val_class_wide_int;
+         loc_result->dw_loc_oprnd2.v.val_wide = ggc_alloc<wide_int> ();
+         *loc_result->dw_loc_oprnd2.v.val_wide = std::make_pair (rtl, mode);
        }
       break;
 
@@ -13281,10 +13751,11 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
        {
          unsigned int elt_size = GET_MODE_UNIT_SIZE (GET_MODE (rtl));
          unsigned int length = CONST_VECTOR_NUNITS (rtl);
-         unsigned char *array = (unsigned char *)
-           ggc_alloc_atomic (length * elt_size);
+         unsigned char *array
+           = ggc_vec_alloc<unsigned char> (length * elt_size);
          unsigned int i;
          unsigned char *p;
+         machine_mode imode = GET_MODE_INNER (mode);
 
          gcc_assert (mode == GET_MODE (rtl) || VOIDmode == GET_MODE (rtl));
          switch (GET_MODE_CLASS (mode))
@@ -13293,15 +13764,7 @@ loc_descriptor (rtx rtl, enum machine_mode mode,
              for (i = 0, p = array; i < length; i++, p += elt_size)
                {
                  rtx elt = CONST_VECTOR_ELT (rtl, i);
-                 double_int val = rtx_to_double_int (elt);
-
-                 if (elt_size <= sizeof (HOST_WIDE_INT))
-                   insert_int (val.to_shwi (), elt_size, p);
-                 else
-                   {
-                     gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
-                     insert_double (val, p);
-                   }
+                 insert_wide_int (std::make_pair (elt, imode), p, elt_size);
                }
              break;
 
@@ -13393,16 +13856,12 @@ secname_for_decl (const_tree decl)
 {
   const char *secname;
 
-  if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
-    {
-      tree sectree = DECL_SECTION_NAME (decl);
-      secname = TREE_STRING_POINTER (sectree);
-    }
+  if (VAR_OR_FUNCTION_DECL_P (decl)
+      && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl) || TREE_STATIC (decl))
+      && DECL_SECTION_NAME (decl))
+    secname = DECL_SECTION_NAME (decl);
   else if (current_function_decl && DECL_SECTION_NAME (current_function_decl))
-    {
-      tree sectree = DECL_SECTION_NAME (current_function_decl);
-      secname = TREE_STRING_POINTER (sectree);
-    }
+    secname = DECL_SECTION_NAME (current_function_decl);
   else if (cfun && in_cold_section_p)
     secname = crtl->subsections.cold_section_label;
   else
@@ -13430,7 +13889,7 @@ dw_loc_list_1 (tree loc, rtx varloc, int want_address,
 {
   int have_address = 0;
   dw_loc_descr_ref descr;
-  enum machine_mode mode;
+  machine_mode mode;
 
   if (want_address != 2)
     {
@@ -13540,7 +13999,7 @@ static dw_loc_descr_ref
 dw_sra_loc_expr (tree decl, rtx loc)
 {
   rtx p;
-  unsigned int padsize = 0;
+  unsigned HOST_WIDE_INT padsize = 0;
   dw_loc_descr_ref descr, *descr_tail;
   unsigned HOST_WIDE_INT decl_size;
   rtx varloc;
@@ -13556,11 +14015,11 @@ dw_sra_loc_expr (tree decl, rtx loc)
 
   for (p = loc; p; p = XEXP (p, 1))
     {
-      unsigned int bitsize = decl_piece_bitsize (p);
+      unsigned HOST_WIDE_INT bitsize = decl_piece_bitsize (p);
       rtx loc_note = *decl_piece_varloc_ptr (p);
       dw_loc_descr_ref cur_descr;
       dw_loc_descr_ref *tail, last = NULL;
-      unsigned int opsize = 0;
+      unsigned HOST_WIDE_INT opsize = 0;
 
       if (loc_note == NULL_RTX
          || NOTE_VAR_LOCATION_LOC (loc_note) == NULL_RTX)
@@ -13838,12 +14297,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
   list = list->dw_loc_next;
   while (list)
     {
-      copy = ggc_alloc_dw_loc_descr_node ();
+      copy = ggc_alloc<dw_loc_descr_node> ();
       memcpy (copy, ref, sizeof (dw_loc_descr_node));
       add_loc_descr (&list->expr, copy);
       while (copy->dw_loc_next)
        {
-         dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
+         dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
          memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
          copy->dw_loc_next = new_copy;
          copy = new_copy;
@@ -13922,14 +14381,17 @@ cst_pool_loc_descr (tree loc)
 
 /* Return dw_loc_list representing address of addr_expr LOC
    by looking for inner INDIRECT_REF expression and turning
-   it into simple arithmetics.  */
+   it into simple arithmetics.
+
+   See loc_list_from_tree for the meaning of CONTEXT.  */
 
 static dw_loc_list_ref
-loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
+loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
+                                                  const loc_descr_context *context)
 {
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
-  enum machine_mode mode;
+  machine_mode mode;
   int unsignedp, volatilep = 0;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
 
@@ -13949,18 +14411,19 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
       return 0;
     }
   if (!offset && !bitpos)
-    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
+    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1,
+                                  context);
   else if (toplev
           && int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
           && (dwarf_version >= 4 || !dwarf_strict))
     {
-      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0, context);
       if (!list_ret)
        return 0;
       if (offset)
        {
          /* Variable offset.  */
-         list_ret1 = loc_list_from_tree (offset, 0);
+         list_ret1 = loc_list_from_tree (offset, 0, context);
          if (list_ret1 == 0)
            return 0;
          add_loc_list (&list_ret, list_ret1);
@@ -13983,15 +14446,36 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
 }
 
 
+/* Helper structure for location descriptions generation.  */
+struct loc_descr_context
+{
+  /* The type that is implicitly referenced by DW_OP_push_object_address, or
+     NULL_TREE if DW_OP_push_object_address in invalid for this location
+     description.  This is used when processing PLACEHOLDER_EXPR nodes.  */
+  tree context_type;
+  /* The ..._DECL node that should be translated as a
+     DW_OP_push_object_address operation.  */
+  tree base_decl;
+};
+
 /* Generate Dwarf location list representing LOC.
    If WANT_ADDRESS is false, expression computing LOC will be computed
    If WANT_ADDRESS is 1, expression computing address of LOC will be returned
    if WANT_ADDRESS is 2, expression computing address useable in location
      will be returned (i.e. DW_OP_reg can be used
-     to refer to register values).  */
+     to refer to register values).
+
+   CONTEXT provides information to customize the location descriptions
+   generation.  Its context_type field specifies what type is implicitly
+   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
+   will not be generated.
+
+   If CONTEXT is NULL, the behavior is the same as if both context_type and
+   base_decl fields were NULL_TREE.  */
 
 static dw_loc_list_ref
-loc_list_from_tree (tree loc, int want_address)
+loc_list_from_tree (tree loc, int want_address,
+                   const struct loc_descr_context *context)
 {
   dw_loc_descr_ref ret = NULL, ret1 = NULL;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
@@ -14002,6 +14486,17 @@ loc_list_from_tree (tree loc, int want_address)
      extending the values properly.  Hopefully this won't be a real
      problem...  */
 
+  if (context != NULL
+      && context->base_decl == loc
+      && want_address == 0)
+    {
+      if (dwarf_version >= 3 || !dwarf_strict)
+       return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
+                            NULL, NULL, NULL);
+      else
+       return NULL;
+    }
+
   switch (TREE_CODE (loc))
     {
     case ERROR_MARK:
@@ -14010,11 +14505,26 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-        position of other fields.  We don't try to encode this here.  The
-        only user of this is Ada, which encodes the needed information using
-        the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+        position of other fields. It is supposed to appear only as the first
+         operand of COMPONENT_REF nodes and to reference precisely the type
+         that the context allows.  */
+      if (context != NULL
+          && TREE_TYPE (loc) == context->context_type
+         && want_address >= 1)
+       {
+         if (dwarf_version >= 3 || !dwarf_strict)
+           {
+             ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+             have_address = 1;
+             break;
+           }
+         else
+           return NULL;
+       }
+      else
+       expansion_failed (loc, NULL_RTX,
+                         "PLACEHOLDER_EXPR for an unexpected type");
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -14035,7 +14545,7 @@ loc_list_from_tree (tree loc, int want_address)
       if (want_address)
        {
          list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
-                      (loc, want_address == 2);
+                      (loc, want_address == 2, context);
          if (list_ret)
            have_address = 1;
          else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
@@ -14044,7 +14554,7 @@ loc_list_from_tree (tree loc, int want_address)
        }
         /* Otherwise, process the argument and look for the address.  */
       if (!list_ret && !ret)
-        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1, context);
       else
        {
          if (want_address)
@@ -14114,7 +14624,7 @@ loc_list_from_tree (tree loc, int want_address)
     case RESULT_DECL:
       if (DECL_HAS_VALUE_EXPR_P (loc))
        return loc_list_from_tree (DECL_VALUE_EXPR (loc),
-                                  want_address);
+                                  want_address, context);
       /* FALLTHRU */
 
     case FUNCTION_DECL:
@@ -14150,7 +14660,7 @@ loc_list_from_tree (tree loc, int want_address)
           ret = new_addr_loc_descr (rtl, dtprel_false);
        else
          {
-           enum machine_mode mode, mem_mode;
+           machine_mode mode, mem_mode;
 
            /* Certain constructs can only be represented at top-level.  */
            if (want_address == 2)
@@ -14181,23 +14691,30 @@ loc_list_from_tree (tree loc, int want_address)
       break;
 
     case MEM_REF:
-      /* ??? FIXME.  */
       if (!integer_zerop (TREE_OPERAND (loc, 1)))
-       return 0;
+       {
+         have_address = 1;
+         goto do_plus;
+       }
       /* Fallthru.  */
     case INDIRECT_REF:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       have_address = 1;
       break;
 
+    case TARGET_MEM_REF:
+    case SSA_NAME:
+    case DEBUG_EXPR_DECL:
+      return NULL;
+
     case COMPOUND_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address, context);
 
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
     case MODIFY_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address, context);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -14208,7 +14725,7 @@ loc_list_from_tree (tree loc, int want_address)
       {
        tree obj, offset;
        HOST_WIDE_INT bitsize, bitpos, bytepos;
-       enum machine_mode mode;
+       machine_mode mode;
        int unsignedp, volatilep = 0;
 
        obj = get_inner_reference (loc, &bitsize, &bitpos, &offset, &mode,
@@ -14218,7 +14735,8 @@ loc_list_from_tree (tree loc, int want_address)
 
        list_ret = loc_list_from_tree (obj,
                                       want_address == 2
-                                      && !bitpos && !offset ? 2 : 1);
+                                      && !bitpos && !offset ? 2 : 1,
+                                      context);
        /* TODO: We can extract value of the small expression via shifting even
           for nonzero bitpos.  */
        if (list_ret == 0)
@@ -14233,7 +14751,7 @@ loc_list_from_tree (tree loc, int want_address)
        if (offset != NULL_TREE)
          {
            /* Variable offset.  */
-           list_ret1 = loc_list_from_tree (offset, 0);
+           list_ret1 = loc_list_from_tree (offset, 0, context);
            if (list_ret1 == 0)
              return 0;
            add_loc_list (&list_ret, list_ret1);
@@ -14323,8 +14841,8 @@ loc_list_from_tree (tree loc, int want_address)
          op = DW_OP_mod;
          goto do_binop;
        }
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
        return 0;
 
@@ -14352,9 +14870,10 @@ loc_list_from_tree (tree loc, int want_address)
 
     case POINTER_PLUS_EXPR:
     case PLUS_EXPR:
+    do_plus:
       if (tree_fits_shwi_p (TREE_OPERAND (loc, 1)))
        {
-         list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+         list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
          if (list_ret == 0)
            return 0;
 
@@ -14402,8 +14921,8 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_binop;
 
     do_binop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
        return 0;
 
@@ -14427,7 +14946,7 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_unop;
 
     do_unop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       if (list_ret == 0)
        return 0;
 
@@ -14451,12 +14970,12 @@ loc_list_from_tree (tree loc, int want_address)
     case COND_EXPR:
       {
        dw_loc_descr_ref lhs
-         = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+         = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0, context);
        dw_loc_list_ref rhs
-         = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
+         = loc_list_from_tree (TREE_OPERAND (loc, 2), 0, context);
        dw_loc_descr_ref bra_node, jump_node, tmp;
 
-       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+       list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
        if (list_ret == 0 || lhs == 0 || rhs == 0)
          return 0;
 
@@ -14562,9 +15081,10 @@ loc_list_from_tree (tree loc, int want_address)
 
 /* Same as above but return only single location expression.  */
 static dw_loc_descr_ref
-loc_descriptor_from_tree (tree loc, int want_address)
+loc_descriptor_from_tree (tree loc, int want_address,
+                         const struct loc_descr_context *context)
 {
-  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
+  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address, context);
   if (!ret)
     return NULL;
   if (ret->dw_loc_next)
@@ -14623,15 +15143,10 @@ simple_decl_align_in_bits (const_tree decl)
 
 /* Return the result of rounding T up to ALIGN.  */
 
-static inline double_int
-round_up_to_align (double_int t, unsigned int align)
+static inline offset_int
+round_up_to_align (const offset_int &t, unsigned int align)
 {
-  double_int alignd = double_int::from_uhwi (align);
-  t += alignd;
-  t += double_int_minus_one;
-  t = t.div (alignd, true, TRUNC_DIV_EXPR);
-  t *= alignd;
-  return t;
+  return wi::udiv_trunc (t + align - 1, align) * align;
 }
 
 /* Given a pointer to a FIELD_DECL, compute and return the byte offset of the
@@ -14644,9 +15159,9 @@ round_up_to_align (double_int t, unsigned int align)
 static HOST_WIDE_INT
 field_byte_offset (const_tree decl)
 {
-  double_int object_offset_in_bits;
-  double_int object_offset_in_bytes;
-  double_int bitpos_int;
+  offset_int object_offset_in_bits;
+  offset_int object_offset_in_bytes;
+  offset_int bitpos_int;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return 0;
@@ -14659,21 +15174,20 @@ field_byte_offset (const_tree decl)
   if (TREE_CODE (bit_position (decl)) != INTEGER_CST)
     return 0;
 
-  bitpos_int = tree_to_double_int (bit_position (decl));
+  bitpos_int = wi::to_offset (bit_position (decl));
 
-#ifdef PCC_BITFIELD_TYPE_MATTERS
   if (PCC_BITFIELD_TYPE_MATTERS)
     {
       tree type;
       tree field_size_tree;
-      double_int deepest_bitpos;
-      double_int field_size_in_bits;
+      offset_int deepest_bitpos;
+      offset_int field_size_in_bits;
       unsigned int type_align_in_bits;
       unsigned int decl_align_in_bits;
-      double_int type_size_in_bits;
+      offset_int type_size_in_bits;
 
       type = field_type (decl);
-      type_size_in_bits = double_int_type_size_in_bits (type);
+      type_size_in_bits = offset_int_type_size_in_bits (type);
       type_align_in_bits = simple_type_align_in_bits (type);
 
       field_size_tree = DECL_SIZE (decl);
@@ -14685,7 +15199,7 @@ field_byte_offset (const_tree decl)
 
       /* If the size of the field is not constant, use the type size.  */
       if (TREE_CODE (field_size_tree) == INTEGER_CST)
-       field_size_in_bits = tree_to_double_int (field_size_tree);
+       field_size_in_bits = wi::to_offset (field_size_tree);
       else
        field_size_in_bits = type_size_in_bits;
 
@@ -14749,7 +15263,7 @@ field_byte_offset (const_tree decl)
       object_offset_in_bits
        = round_up_to_align (object_offset_in_bits, type_align_in_bits);
 
-      if (object_offset_in_bits.ugt (bitpos_int))
+      if (wi::gtu_p (object_offset_in_bits, bitpos_int))
        {
          object_offset_in_bits = deepest_bitpos - type_size_in_bits;
 
@@ -14759,12 +15273,10 @@ field_byte_offset (const_tree decl)
        }
     }
   else
-#endif /* PCC_BITFIELD_TYPE_MATTERS */
     object_offset_in_bits = bitpos_int;
 
   object_offset_in_bytes
-    = object_offset_in_bits.div (double_int::from_uhwi (BITS_PER_UNIT),
-                                true, TRUNC_DIV_EXPR);
+    = wi::lrshift (object_offset_in_bits, LOG2_BITS_PER_UNIT);
   return object_offset_in_bytes.to_shwi ();
 }
 \f
@@ -14940,22 +15452,36 @@ extract_int (const unsigned char *src, unsigned int size)
   return val;
 }
 
-/* Writes double_int values to dw_vec_const array.  */
+/* Writes wide_int values to dw_vec_const array.  */
 
 static void
-insert_double (double_int val, unsigned char *dest)
+insert_wide_int (const wide_int &val, unsigned char *dest, int elt_size)
 {
-  unsigned char *p0 = dest;
-  unsigned char *p1 = dest + sizeof (HOST_WIDE_INT);
+  int i;
 
-  if (WORDS_BIG_ENDIAN)
+  if (elt_size <= HOST_BITS_PER_WIDE_INT/BITS_PER_UNIT)
     {
-      p0 = p1;
-      p1 = dest;
+      insert_int ((HOST_WIDE_INT) val.elt (0), elt_size, dest);
+      return;
     }
 
-  insert_int ((HOST_WIDE_INT) val.low, sizeof (HOST_WIDE_INT), p0);
-  insert_int ((HOST_WIDE_INT) val.high, sizeof (HOST_WIDE_INT), p1);
+  /* We'd have to extend this code to support odd sizes.  */
+  gcc_assert (elt_size % (HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT) == 0);
+
+  int n = elt_size / (HOST_BITS_PER_WIDE_INT / BITS_PER_UNIT);
+
+  if (WORDS_BIG_ENDIAN)
+    for (i = n - 1; i >= 0; i--)
+      {
+       insert_int ((HOST_WIDE_INT) val.elt (i), sizeof (HOST_WIDE_INT), dest);
+       dest += sizeof (HOST_WIDE_INT);
+      }
+  else
+    for (i = 0; i < n; i++)
+      {
+       insert_int ((HOST_WIDE_INT) val.elt (i), sizeof (HOST_WIDE_INT), dest);
+       dest += sizeof (HOST_WIDE_INT);
+      }
 }
 
 /* Writes floating point values to dw_vec_const array.  */
@@ -15000,37 +15526,43 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       }
       return true;
 
+    case CONST_WIDE_INT:
+      add_AT_wide (die, DW_AT_const_value,
+                  std::make_pair (rtl, GET_MODE (rtl)));
+      return true;
+
     case CONST_DOUBLE:
       /* Note that a CONST_DOUBLE rtx could represent either an integer or a
         floating-point constant.  A CONST_DOUBLE is used whenever the
         constant requires more than one word in order to be adequately
         represented.  */
       {
-       enum machine_mode mode = GET_MODE (rtl);
+       machine_mode mode = GET_MODE (rtl);
 
-       if (SCALAR_FLOAT_MODE_P (mode))
+       if (TARGET_SUPPORTS_WIDE_INT == 0 && !SCALAR_FLOAT_MODE_P (mode))
+         add_AT_double (die, DW_AT_const_value,
+                        CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
+       else
          {
            unsigned int length = GET_MODE_SIZE (mode);
-           unsigned char *array = (unsigned char *) ggc_alloc_atomic (length);
+           unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
            insert_float (rtl, array);
            add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
          }
-       else
-         add_AT_double (die, DW_AT_const_value,
-                        CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
       }
       return true;
 
     case CONST_VECTOR:
       {
-       enum machine_mode mode = GET_MODE (rtl);
+       machine_mode mode = GET_MODE (rtl);
        unsigned int elt_size = GET_MODE_UNIT_SIZE (mode);
        unsigned int length = CONST_VECTOR_NUNITS (rtl);
-       unsigned char *array = (unsigned char *) ggc_alloc_atomic
-         (length * elt_size);
+       unsigned char *array
+         = ggc_vec_alloc<unsigned char> (length * elt_size);
        unsigned int i;
        unsigned char *p;
+       machine_mode imode = GET_MODE_INNER (mode);
 
        switch (GET_MODE_CLASS (mode))
          {
@@ -15038,15 +15570,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
            for (i = 0, p = array; i < length; i++, p += elt_size)
              {
                rtx elt = CONST_VECTOR_ELT (rtl, i);
-               double_int val = rtx_to_double_int (elt);
-
-               if (elt_size <= sizeof (HOST_WIDE_INT))
-                 insert_int (val.to_shwi (), elt_size, p);
-               else
-                 {
-                   gcc_assert (elt_size == 2 * sizeof (HOST_WIDE_INT));
-                   insert_double (val, p);
-                 }
+               insert_wide_int (std::make_pair (elt, imode), p, elt_size);
              }
            break;
 
@@ -15070,7 +15594,7 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
       if (dwarf_version >= 4 || !dwarf_strict)
        {
          dw_loc_descr_ref loc_result;
-         resolve_one_addr (&rtl, NULL);
+         resolve_one_addr (&rtl);
        rtl_addr:
           loc_result = new_addr_loc_descr (rtl, dtprel_false);
          add_loc_descr (&loc_result, new_loc_descr (DW_OP_stack_value, 0, 0));
@@ -15143,12 +15667,12 @@ reference_to_unused (tree * tp, int * walk_subtrees,
   /* ???  The C++ FE emits debug information for using decls, so
      putting gcc_unreachable here falls over.  See PR31899.  For now
      be conservative.  */
-  else if (!cgraph_global_info_ready
+  else if (!symtab->global_info_ready
           && (TREE_CODE (*tp) == VAR_DECL || TREE_CODE (*tp) == FUNCTION_DECL))
     return *tp;
   else if (TREE_CODE (*tp) == VAR_DECL)
     {
-      varpool_node *node = varpool_get_node (*tp);
+      varpool_node *node = varpool_node::get (*tp);
       if (!node || !node->definition)
        return *tp;
     }
@@ -15159,7 +15683,7 @@ reference_to_unused (tree * tp, int * walk_subtrees,
          optimizing and gimplifying the CU by now.
         So if *TP has no call graph node associated
         to it, it means *TP will not be emitted.  */
-      if (!cgraph_get_node (*tp))
+      if (!cgraph_node::get (*tp))
        return *tp;
     }
   else if (TREE_CODE (*tp) == STRING_CST && !TREE_ASM_WRITTEN (*tp))
@@ -15184,7 +15708,7 @@ rtl_for_decl_init (tree init, tree type)
     {
       tree enttype = TREE_TYPE (type);
       tree domain = TYPE_DOMAIN (type);
-      enum machine_mode mode = TYPE_MODE (enttype);
+      machine_mode mode = TYPE_MODE (enttype);
 
       if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
          && domain
@@ -15374,8 +15898,8 @@ rtl_for_decl_location (tree decl)
        {
          tree declared_type = TREE_TYPE (decl);
          tree passed_type = DECL_ARG_TYPE (decl);
-         enum machine_mode dmode = TYPE_MODE (declared_type);
-         enum machine_mode pmode = TYPE_MODE (passed_type);
+         machine_mode dmode = TYPE_MODE (declared_type);
+         machine_mode pmode = TYPE_MODE (passed_type);
 
          /* This decl represents a formal parameter which was optimized out.
             Note that DECL_INCOMING_RTL may be NULL in here, but we handle
@@ -15428,7 +15952,7 @@ rtl_for_decl_location (tree decl)
               && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)))
                   < UNITS_PER_WORD))
        {
-         enum machine_mode addr_mode = get_address_mode (rtl);
+         machine_mode addr_mode = get_address_mode (rtl);
          int offset = (UNITS_PER_WORD
                        - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl))));
 
@@ -15442,7 +15966,7 @@ rtl_for_decl_location (tree decl)
           && GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl))
           && BYTES_BIG_ENDIAN)
     {
-      enum machine_mode addr_mode = get_address_mode (rtl);
+      machine_mode addr_mode = get_address_mode (rtl);
       int rsize = GET_MODE_SIZE (GET_MODE (rtl));
       int dsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (decl)));
 
@@ -15502,7 +16026,7 @@ static tree
 fortran_common (tree decl, HOST_WIDE_INT *value)
 {
   tree val_expr, cvar;
-  enum machine_mode mode;
+  machine_mode mode;
   HOST_WIDE_INT bitsize, bitpos;
   tree offset;
   int unsignedp, volatilep = 0;
@@ -15567,7 +16091,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
   dw_loc_list_ref list;
   var_loc_list *loc_list;
   cached_dw_loc_list *cache;
-  void **slot;
 
   if (TREE_CODE (decl) == ERROR_MARK)
     return false;
@@ -15611,21 +16134,23 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
     cache_p = false;
   if (cache_p)
     {
-      cache = (cached_dw_loc_list *)
-       htab_find_with_hash (cached_dw_loc_list_table, decl, DECL_UID (decl));
+      cache = cached_dw_loc_list_table->find_with_hash (decl, DECL_UID (decl));
       if (cache)
        list = cache->loc_list;
     }
   if (list == NULL)
     {
-      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2,
+                                NULL);
       /* It is usually worth caching this result if the decl is from
         BLOCK_NONLOCALIZED_VARS and if the list has at least two elements.  */
       if (cache_p && list && list->dw_loc_next)
        {
-         slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
-                                          DECL_UID (decl), INSERT);
-         cache = ggc_alloc_cleared_cached_dw_loc_list ();
+         cached_dw_loc_list **slot
+           = cached_dw_loc_list_table->find_slot_with_hash (decl,
+                                                            DECL_UID (decl),
+                                                            INSERT);
+         cache = ggc_cleared_alloc<cached_dw_loc_list> ();
          cache->decl_id = DECL_UID (decl);
          cache->loc_list = list;
          *slot = cache;
@@ -15641,17 +16166,6 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
   return tree_add_const_value_attribute_for_decl (die, decl);
 }
 
-/* Add VARIABLE and DIE into deferred locations list.  */
-
-static void
-defer_location (tree variable, dw_die_ref die)
-{
-  deferred_locations entry;
-  entry.variable = variable;
-  entry.die = die;
-  vec_safe_push (deferred_locations_list, entry);
-}
-
 /* Helper function for tree_add_const_value_attribute.  Natively encode
    initializer INIT into an array.  Return true if successful.  */
 
@@ -15671,7 +16185,7 @@ native_encode_initializer (tree init, unsigned char *array, int size)
       if (TREE_CODE (type) == ARRAY_TYPE)
        {
          tree enttype = TREE_TYPE (type);
-         enum machine_mode mode = TYPE_MODE (enttype);
+         machine_mode mode = TYPE_MODE (enttype);
 
          if (GET_MODE_CLASS (mode) != MODE_INT || GET_MODE_SIZE (mode) != 1)
            return false;
@@ -15821,8 +16335,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
       HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (init));
       if (size > 0 && (int) size == size)
        {
-         unsigned char *array = (unsigned char *)
-           ggc_alloc_cleared_atomic (size);
+         unsigned char *array = ggc_cleared_vec_alloc<unsigned char> (size);
 
          if (native_encode_initializer (init, array, size))
            {
@@ -15851,12 +16364,12 @@ tree_add_const_value_attribute_for_decl (dw_die_ref var_die, tree decl)
          && !TREE_STATIC (decl)))
     return false;
 
-    if (TREE_READONLY (decl)
-       && ! TREE_THIS_VOLATILE (decl)
-       && DECL_INITIAL (decl))
-      /* OK */;
-    else
-      return false;
+  if (TREE_READONLY (decl)
+      && ! TREE_THIS_VOLATILE (decl)
+      && DECL_INITIAL (decl))
+    /* OK */;
+  else
+    return false;
 
   /* Don't add DW_AT_const_value if abstract origin already has one.  */
   if (get_AT (var_die, DW_AT_const_value))
@@ -16090,7 +16603,7 @@ comp_dir_string (void)
       int wdlen;
 
       wdlen = strlen (wd);
-      wd1 = (char *) ggc_alloc_atomic (wdlen + 2);
+      wd1 = ggc_vec_alloc<char> (wdlen + 2);
       strcpy (wd1, wd);
       wd1 [wdlen] = DIR_SEPARATOR;
       wd1 [wdlen + 1] = 0;
@@ -16111,6 +16624,143 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  See
+   loc_list_from_tree for the meaning of CONTEXT.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+                int forms, const struct loc_descr_context *context)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool strip_conversions = true;
+
+  while (strip_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+       return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+       value = TREE_OPERAND (value, 0);
+       break;
+
+      default:
+       strip_conversions = false;
+       break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+        a constant value.  We need to choose a form based on
+        whether the type is signed or unsigned.  We cannot just
+        call add_AT_unsigned if the value itself is positive
+        (add_AT_unsigned might add the unsigned value encoded as
+        DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+        bounds type and then sign extend any unsigned values found
+        for signed types.  This is needed only for
+        DW_AT_{lower,upper}_bound, since for most other attributes,
+        consumers will treat DW_FORM_data[1248] as unsigned values,
+        regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+         || tree_fits_uhwi_p (value))
+       {
+         if (TYPE_UNSIGNED (TREE_TYPE (value)))
+           add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+         else
+           add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+       }
+      else
+       /* Otherwise represent the bound as an unsigned value with
+          the precision of its type.  The precision and signedness
+          of the type will be necessary to re-interpret it
+          unambiguously.  */
+       add_AT_wide (die, attr, value);
+      return;
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+        bound of an array may reference an embedding record (this happens in
+        Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+         && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+         && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+       decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+              || TREE_CODE (value) == PARM_DECL
+              || TREE_CODE (value) == RESULT_DECL)
+       decl = value;
+
+      if (decl != NULL_TREE)
+       {
+         dw_die_ref decl_die = lookup_decl_die (decl);
+
+         /* ??? Can this happen, or should the variable have been bound
+            first?  Probably it can, since I imagine that we try to create
+            the types of parameters in the order in which they exist in
+            the list, and won't have created a forward reference to a
+            later parameter.  */
+         if (decl_die != NULL)
+           {
+             add_AT_die_ref (die, attr, decl_die);
+             return;
+           }
+       }
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2, context);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+        a DWARF expression rather than location description.  For that
+        loc_list_from_tree (value, 0, &context) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0, context);
+      if (list2 && single_element_loc_list_p (list2))
+       {
+         add_AT_loc (die, attr, list2->expr);
+         return;
+       }
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16122,7 +16772,10 @@ lower_bound_default (void)
     case DW_LANG_C:
     case DW_LANG_C89:
     case DW_LANG_C99:
+    case DW_LANG_C11:
     case DW_LANG_C_plus_plus:
+    case DW_LANG_C_plus_plus_11:
+    case DW_LANG_C_plus_plus_14:
     case DW_LANG_ObjC:
     case DW_LANG_ObjC_plus_plus:
     case DW_LANG_Java:
@@ -16130,6 +16783,8 @@ lower_bound_default (void)
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
+    case DW_LANG_Fortran03:
+    case DW_LANG_Fortran08:
       return 1;
     case DW_LANG_UPC:
     case DW_LANG_D:
@@ -16152,125 +16807,57 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+               tree bound, const struct loc_descr_context *context)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-       unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-       int dflt;
+      /* Strip all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+       bound = TREE_OPERAND (bound, 0);
+       break;
 
-       /* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+        are even omitted when they are the default.  */
+      case INTEGER_CST:
+       /* If the value for this bound is the default one, we can even omit the
+          attribute.  */
        if (bound_attr == DW_AT_lower_bound
            && tree_fits_shwi_p (bound)
            && (dflt = lower_bound_default ()) != -1
            && tree_to_shwi (bound) == dflt)
-         ;
-
-       /* Otherwise represent the bound as an unsigned value with the
-          precision of its type.  The precision and signedness of the
-          type will be necessary to re-interpret it unambiguously.  */
-       else if (prec < HOST_BITS_PER_WIDE_INT)
-         {
-           unsigned HOST_WIDE_INT mask
-             = ((unsigned HOST_WIDE_INT) 1 << prec) - 1;
-           add_AT_unsigned (subrange_die, bound_attr,
-                            TREE_INT_CST_LOW (bound) & mask);
-         }
-       else if (prec == HOST_BITS_PER_WIDE_INT
-                || TREE_INT_CST_HIGH (bound) == 0)
-         add_AT_unsigned (subrange_die, bound_attr,
-                          TREE_INT_CST_LOW (bound));
-       else
-         add_AT_double (subrange_die, bound_attr, TREE_INT_CST_HIGH (bound),
-                        TREE_INT_CST_LOW (bound));
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-       dw_die_ref decl_die = lookup_decl_die (bound);
-
-       /* ??? Can this happen, or should the variable have been bound
-          first?  Probably it can, since I imagine that we try to create
-          the types of parameters in the order in which they exist in
-          the list, and won't have created a forward reference to a
-          later parameter.  */
-       if (decl_die != NULL)
-         {
-           add_AT_die_ref (subrange_die, bound_attr, decl_die);
-           break;
-         }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-       /* Otherwise try to create a stack operation procedure to
-          evaluate the value of the array bound.  */
-
-       dw_die_ref ctx, decl_die;
-       dw_loc_list_ref list;
-
-       list = loc_list_from_tree (bound, 2);
-       if (list == NULL || single_element_loc_list_p (list))
-         {
-           /* If DW_AT_*bound is not a reference nor constant, it is
-              a DWARF expression rather than location description.
-              For that loc_list_from_tree (bound, 0) is needed.
-              If that fails to give a single element list,
-              fall back to outputting this as a reference anyway.  */
-           dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-           if (list2 && single_element_loc_list_p (list2))
-             {
-               add_AT_loc (subrange_die, bound_attr, list2->expr);
-               break;
-             }
-         }
-       if (list == NULL)
-         break;
+         return;
 
-       if (current_function_decl == 0)
-         ctx = comp_unit_die ();
-       else
-         ctx = lookup_decl_die (current_function_decl);
+       /* FALLTHRU */
 
-       decl_die = new_die (DW_TAG_variable, ctx, bound);
-       add_AT_flag (decl_die, DW_AT_artificial, 1);
-       add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
-       add_AT_location_description (decl_die, DW_AT_location, list);
-       add_AT_die_ref (subrange_die, bound_attr, decl_die);
-       break;
+      default:
+       add_scalar_info (subrange_die, bound_attr, bound,
+                        dw_scalar_form_constant
+                        | dw_scalar_form_exprloc
+                        | dw_scalar_form_reference,
+                        context);
+       return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
    possibly nested array subscripts in a flat sequence if COLLAPSE_P is true.
    Note that the block of subscript information for an array type also
-   includes information about the element type of the given array type.  */
+   includes information about the element type of the given array type.
+
+   This function reuses previously set type and bound information if
+   available.  */
 
 static void
 add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 {
   unsigned dimension_number;
   tree lower, upper;
-  dw_die_ref subrange_die;
+  dw_die_ref child = type_die->die_child;
 
   for (dimension_number = 0;
        TREE_CODE (type) == ARRAY_TYPE && (dimension_number == 0 || collapse_p);
@@ -16284,7 +16871,37 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
       /* Arrays come in three flavors: Unspecified bounds, fixed bounds,
         and (in GNU C only) variable bounds.  Handle all three forms
         here.  */
-      subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
+      /* Find and reuse a previously generated DW_TAG_subrange_type if
+        available.
+
+         For multi-dimensional arrays, as we iterate through the
+         various dimensions in the enclosing for loop above, we also
+         iterate through the DIE children and pick at each
+         DW_TAG_subrange_type previously generated (if available).
+         Each child DW_TAG_subrange_type DIE describes the range of
+         the current dimension.  At this point we should have as many
+         DW_TAG_subrange_type's as we have dimensions in the
+         array.  */
+      dw_die_ref subrange_die = NULL;
+      if (child)
+       while (1)
+         {
+           child = child->die_sib;
+           if (child->die_tag == DW_TAG_subrange_type)
+             subrange_die = child;
+           if (child == type_die->die_child)
+             {
+               /* If we wrapped around, stop looking next time.  */
+               child = NULL;
+               break;
+             }
+           if (child->die_tag == DW_TAG_subrange_type)
+             break;
+         }
+      if (!subrange_die)
+       subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL);
+
       if (domain)
        {
          /* We have an array type with specified bounds.  */
@@ -16292,7 +16909,8 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
          upper = TYPE_MAX_VALUE (domain);
 
          /* Define the index type.  */
-         if (TREE_TYPE (domain))
+         if (TREE_TYPE (domain)
+             && !get_AT (subrange_die, DW_AT_type))
            {
              /* ??? This is probably an Ada unnamed subrange type.  Ignore the
                 TREE_TYPE field.  We can't emit debug info for this
@@ -16303,8 +16921,8 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
                  && TYPE_NAME (TREE_TYPE (domain)) == NULL_TREE)
                ;
              else
-               add_type_attribute (subrange_die, TREE_TYPE (domain), 0, 0,
-                                   type_die);
+               add_type_attribute (subrange_die, TREE_TYPE (domain),
+                                   TYPE_UNQUALIFIED, type_die);
            }
 
          /* ??? If upper is NULL, the array has unspecified length,
@@ -16314,9 +16932,10 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
             to produce useful results, go ahead and output the lower
             bound solo, and hope the debugger can cope.  */
 
-         add_bound_info (subrange_die, DW_AT_lower_bound, lower);
-         if (upper)
-           add_bound_info (subrange_die, DW_AT_upper_bound, upper);
+         if (!get_AT (subrange_die, DW_AT_lower_bound))
+           add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
+         if (upper && !get_AT (subrange_die, DW_AT_upper_bound))
+           add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
        }
 
       /* Otherwise we have an array type with an unspecified length.  The
@@ -16452,9 +17071,19 @@ add_bit_size_attribute (dw_die_ref die, tree decl)
 static inline void
 add_prototyped_attribute (dw_die_ref die, tree func_type)
 {
-  if (get_AT_unsigned (comp_unit_die (), DW_AT_language) == DW_LANG_C89
-      && prototype_p (func_type))
-    add_AT_flag (die, DW_AT_prototyped, 1);
+  switch (get_AT_unsigned (comp_unit_die (), DW_AT_language))
+    {
+    case DW_LANG_C:
+    case DW_LANG_C89:
+    case DW_LANG_C99:
+    case DW_LANG_C11:
+    case DW_LANG_ObjC:
+      if (prototype_p (func_type))
+       add_AT_flag (die, DW_AT_prototyped, 1);
+      break;
+    default:
+      break;
+    }
 }
 
 /* Add an 'abstract_origin' attribute below a given DIE.  The DIE is found
@@ -16564,10 +17193,9 @@ add_src_coords_attributes (dw_die_ref die, tree decl)
 static void
 add_linkage_name (dw_die_ref die, tree decl)
 {
-  if (debug_info_level > DINFO_LEVEL_TERSE
+  if (debug_info_level > DINFO_LEVEL_NONE
       && (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
       && TREE_PUBLIC (decl)
-      && !DECL_ABSTRACT (decl)
       && !(TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
       && die->die_tag != DW_TAG_member)
     {
@@ -16576,7 +17204,7 @@ add_linkage_name (dw_die_ref die, tree decl)
        {
          limbo_die_node *asm_name;
 
-         asm_name = ggc_alloc_cleared_limbo_die_node ();
+         asm_name = ggc_cleared_alloc<limbo_die_node> ();
          asm_name->die = die;
          asm_name->created_for = decl;
          asm_name->next = deferred_asm_name;
@@ -16629,7 +17257,7 @@ dwarf2out_vms_debug_main_pointer (void)
   dw_die_ref die;
 
   /* Allocate the VMS debug main subprogram die.  */
-  die = ggc_alloc_cleared_die_node ();
+  die = ggc_cleared_alloc<die_node> ();
   die->die_tag = DW_TAG_subprogram;
   add_name_attribute (die, VMS_DEBUG_MAIN_POINTER);
   ASM_GENERATE_INTERNAL_LABEL (label, PROLOGUE_END_LABEL,
@@ -16796,11 +17424,12 @@ class_or_namespace_scope_p (dw_die_ref context_die)
 
 /* Many forms of DIEs require a "type description" attribute.  This
    routine locates the proper "type descriptor" die for the type given
-   by 'type', and adds a DW_AT_type attribute below the given die.  */
+   by 'type' plus any additional qualifiers given by 'cv_quals', and
+   adds a DW_AT_type attribute below the given die.  */
 
 static void
-add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
-                   int decl_volatile, dw_die_ref context_die)
+add_type_attribute (dw_die_ref object_die, tree type, int cv_quals,
+                   dw_die_ref context_die)
 {
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
@@ -16821,8 +17450,7 @@ add_type_attribute (dw_die_ref object_die, tree type, int decl_const,
     return;
 
   type_die = modified_type_die (type,
-                               decl_const || TYPE_READONLY (type),
-                               decl_volatile || TYPE_VOLATILE (type),
+                               cv_quals | TYPE_QUALS_NO_ADDR_SPACE (type),
                                context_die);
 
   if (type_die != NULL)
@@ -16933,6 +17561,25 @@ decl_start_label (tree decl)
 }
 #endif
 \f
+/* For variable-length arrays that have been previously generated, but
+   may be incomplete due to missing subscript info, fill the subscript
+   info.  Return TRUE if this is one of those cases.  */
+static bool
+fill_variable_array_bounds (tree type)
+{
+  if (TREE_ASM_WRITTEN (type)
+      && TREE_CODE (type) == ARRAY_TYPE
+      && variably_modified_type_p (type, NULL))
+    {
+      dw_die_ref array_die = lookup_type_die (type);
+      if (!array_die)
+       return false;
+      add_subscript_info (array_die, type, !is_ada ());
+      return true;
+    }
+  return false;
+}
+
 /* These routines generate the internal representation of the DIE's for
    the compilation unit.  Debugging information is collected by walking
    the declaration trees passed in from dwarf2out_decl().  */
@@ -16940,7 +17587,6 @@ decl_start_label (tree decl)
 static void
 gen_array_type_die (tree type, dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
   dw_die_ref array_die;
 
   /* GNU compilers represent multidimensional array types as sequences of one
@@ -16954,6 +17600,11 @@ gen_array_type_die (tree type, dw_die_ref context_die)
      flexibilty wrt arrays of variable size.  */
 
   bool collapse_nested_arrays = !is_ada ();
+
+  if (fill_variable_array_bounds (type))
+    return;
+
+  dw_die_ref scope_die = scope_die_for (type, context_die);
   tree element_type;
 
   /* Emit DW_TAG_string_type for Fortran character types (with kind 1 only, as
@@ -16976,7 +17627,7 @@ gen_array_type_die (tree type, dw_die_ref context_die)
               && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
        {
          tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
-         dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
+         dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL);
 
          size = int_size_in_bytes (TREE_TYPE (szdecl));
          if (loc && size > 0)
@@ -17018,9 +17669,9 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     {
       /* For VECTOR_TYPEs we use an array die with appropriate bounds.  */
       dw_die_ref subrange_die = new_die (DW_TAG_subrange_type, array_die, NULL);
-      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node);
+      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node, NULL);
       add_bound_info (subrange_die, DW_AT_upper_bound,
-                     size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+                     size_int (TYPE_VECTOR_SUBPARTS (type) - 1), NULL);
     }
   else
     add_subscript_info (array_die, type, collapse_nested_arrays);
@@ -17036,7 +17687,7 @@ gen_array_type_die (tree type, dw_die_ref context_die)
        element_type = TREE_TYPE (element_type);
       }
 
-  add_type_attribute (array_die, element_type, 0, 0, context_die);
+  add_type_attribute (array_die, element_type, TYPE_UNQUALIFIED, context_die);
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
   if (TYPE_ARTIFICIAL (type))
@@ -17046,99 +17697,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-       return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-       break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-       break;
-      if (size == DWARF2_ADDR_SIZE)
-       add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-       add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-         && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-       {
-         loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-         if (!loc)
-           break;
-         loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-       }
-      else
-       {
-         op = DW_OP_plus;
-       do_binop:
-         loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-         if (!loc)
-           break;
-         loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-         if (!loc2)
-           break;
-         add_loc_descr (&loc, loc2);
-         add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-       }
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-                     tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17146,60 +17704,73 @@ static void
 gen_descr_array_type_die (tree type, struct array_descr_info *info,
                          dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
-  dw_die_ref array_die;
+  const dw_die_ref scope_die = scope_die_for (type, context_die);
+  const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
+  const struct loc_descr_context context = { type, info->base_decl };
   int dim;
 
-  array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
   equate_type_number_to_die (type, array_die);
 
-  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
-  if (is_fortran ()
-      && info->ndimensions >= 2)
-    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+  if (info->ndimensions > 1)
+    switch (info->ordering)
+      {
+      case array_descr_ordering_row_major:
+       add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
+       break;
+      case array_descr_ordering_column_major:
+       add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+       break;
+      default:
+       break;
+      }
+
+  if (dwarf_version >= 3 || !dwarf_strict)
+    {
+      if (info->data_location)
+       add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+                        dw_scalar_form_exprloc, &context);
+      if (info->associated)
+       add_scalar_info (array_die, DW_AT_associated, info->associated,
+                        dw_scalar_form_constant
+                        | dw_scalar_form_exprloc
+                        | dw_scalar_form_reference, &context);
+      if (info->allocated)
+       add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+                        dw_scalar_form_constant
+                        | dw_scalar_form_exprloc
+                        | dw_scalar_form_reference, &context);
+    }
 
-  if (info->data_location)
-    add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
-                         info->base_decl);
-  if (info->associated)
-    add_descr_info_field (array_die, DW_AT_associated, info->associated,
-                         info->base_decl);
-  if (info->allocated)
-    add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-                         info->base_decl);
+  add_gnat_descriptive_type_attribute (array_die, type, context_die);
 
   for (dim = 0; dim < info->ndimensions; dim++)
     {
       dw_die_ref subrange_die
        = new_die (DW_TAG_subrange_type, array_die, NULL);
 
+      if (info->dimen[dim].bounds_type)
+       add_type_attribute (subrange_die,
+                           info->dimen[dim].bounds_type, 0,
+                           context_die);
       if (info->dimen[dim].lower_bound)
-       {
-         /* If it is the default value, omit it.  */
-         int dflt;
-
-         if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-             && (dflt = lower_bound_default ()) != -1
-             && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-           ;
-         else
-           add_descr_info_field (subrange_die, DW_AT_lower_bound,
-                                 info->dimen[dim].lower_bound,
-                                 info->base_decl);
-       }
+       add_bound_info (subrange_die, DW_AT_lower_bound,
+                       info->dimen[dim].lower_bound, &context);
       if (info->dimen[dim].upper_bound)
-       add_descr_info_field (subrange_die, DW_AT_upper_bound,
-                             info->dimen[dim].upper_bound,
-                             info->base_decl);
-      if (info->dimen[dim].stride)
-       add_descr_info_field (subrange_die, DW_AT_byte_stride,
-                             info->dimen[dim].stride,
-                             info->base_decl);
+       add_bound_info (subrange_die, DW_AT_upper_bound,
+                       info->dimen[dim].upper_bound, &context);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+       add_scalar_info (subrange_die, DW_AT_byte_stride,
+                        info->dimen[dim].stride,
+                        dw_scalar_form_constant
+                        | dw_scalar_form_exprloc
+                        | dw_scalar_form_reference,
+                        &context);
     }
 
   gen_type_die (info->element_type, context_die);
-  add_type_attribute (array_die, info->element_type, 0, 0, context_die);
+  add_type_attribute (array_die, info->element_type, TYPE_UNQUALIFIED,
+                     context_die);
 
   if (get_AT (array_die, DW_AT_name))
     add_pubtype (type, array_die);
@@ -17218,10 +17789,10 @@ gen_entry_point_die (tree decl, dw_die_ref context_die)
     {
       add_name_and_src_coords_attributes (decl_die, decl);
       add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)),
-                         0, 0, context_die);
+                         TYPE_UNQUALIFIED, context_die);
     }
 
-  if (DECL_ABSTRACT (decl))
+  if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, decl_die);
   else
     add_AT_lbl_id (decl_die, DW_AT_low_pc, decl_start_label (decl));
@@ -17305,6 +17876,12 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
 
       TREE_ASM_WRITTEN (type) = 1;
       add_byte_size_attribute (type_die, type);
+      if (dwarf_version >= 3 || !dwarf_strict)
+       {
+         tree underlying = lang_hooks.types.enum_underlying_base_type (type);
+         add_type_attribute (type_die, underlying, TYPE_UNQUALIFIED,
+                             context_die);
+       }
       if (TYPE_STUB_DECL (type) != NULL_TREE)
        {
          add_src_coords_attributes (type_die, TYPE_STUB_DECL (type));
@@ -17330,24 +17907,24 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
 
          if (simple_type_size_in_bits (TREE_TYPE (value))
              <= HOST_BITS_PER_WIDE_INT || tree_fits_shwi_p (value))
-           /* DWARF2 does not provide a way of indicating whether or
-              not enumeration constants are signed or unsigned.  GDB
-              always assumes the values are signed, so we output all
-              values as if they were signed.  That means that
-              enumeration constants with very large unsigned values
-              will appear to have negative values in the debugger.
-
-              TODO: the above comment is wrong, DWARF2 does provide
-              DW_FORM_sdata/DW_FORM_udata to represent signed/unsigned data.
-              This should be re-worked to use correct signed/unsigned
-              int/double tags for all cases, instead of always treating as
-              signed.  */
-           add_AT_int (enum_die, DW_AT_const_value, TREE_INT_CST_LOW (value));
+           {
+             /* For constant forms created by add_AT_unsigned DWARF
+                consumers (GDB, elfutils, etc.) always zero extend
+                the value.  Only when the actual value is negative
+                do we need to use add_AT_int to generate a constant
+                form that can represent negative values.  */
+             HOST_WIDE_INT val = TREE_INT_CST_LOW (value);
+             if (TYPE_UNSIGNED (TREE_TYPE (value)) || val >= 0)
+               add_AT_unsigned (enum_die, DW_AT_const_value,
+                                (unsigned HOST_WIDE_INT) val);
+             else
+               add_AT_int (enum_die, DW_AT_const_value, val);
+           }
          else
            /* Enumeration constants may be wider than HOST_WIDE_INT.  Handle
-              that here.  */
-           add_AT_double (enum_die, DW_AT_const_value,
-                          TREE_INT_CST_HIGH (value), TREE_INT_CST_LOW (value));
+              that here.  TODO: This should be re-worked to use correct
+              signed/unsigned double tags for all cases.  */
+           add_AT_wide (enum_die, DW_AT_const_value, value);
        }
 
       add_gnat_descriptive_type_attribute (type_die, type, context_die);
@@ -17383,8 +17960,71 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 {
   tree node_or_origin = node ? node : origin;
   tree ultimate_origin;
-  dw_die_ref parm_die
-    = new_die (DW_TAG_formal_parameter, context_die, node);
+  dw_die_ref parm_die = NULL;
+  
+  if (TREE_CODE_CLASS (TREE_CODE (node_or_origin)) == tcc_declaration)
+    {
+      parm_die = lookup_decl_die (node);
+
+      /* If the contexts differ, we may not be talking about the same
+        thing.  */
+      if (parm_die && parm_die->die_parent != context_die)
+       {
+         if (!DECL_ABSTRACT_P (node))
+           {
+             /* This can happen when creating an inlined instance, in
+                which case we need to create a new DIE that will get
+                annotated with DW_AT_abstract_origin.  */
+             parm_die = NULL;
+           }
+         else
+           {
+             /* FIXME: Reuse DIE even with a differing context.
+
+                This happens when called through
+                dwarf2out_abstract_function for formal parameter
+                packs.  The issue is that we're calling
+                dwarf2out_abstract_function to build debug info for
+                the abstract instance of a function for which we have
+                already generated a DIE in
+                dwarf2out_early_global_decl.
+
+                Once we remove dwarf2out_abstract_function, this
+                gcc_assert should be a gcc_unreachable.  */
+             gcc_assert (parm_die->die_parent->die_tag
+                         == DW_TAG_GNU_formal_parameter_pack);
+           }
+       }
+
+      if (parm_die && parm_die->die_parent == NULL)
+       {
+         /* Check that parm_die already has the right attributes that
+            we would have added below.  If any attributes are
+            missing, fall through to add them.  */
+         if (! DECL_ABSTRACT_P (node_or_origin)
+             && !get_AT (parm_die, DW_AT_location)
+             && !get_AT (parm_die, DW_AT_const_value))
+           /* We are missing  location info, and are about to add it.  */
+           ;
+         else
+           {
+             add_child_die (context_die, parm_die);
+             return parm_die;
+           }
+       }
+    }
+
+  /* If we have a previously generated DIE, use it, unless this is an
+     concrete instance (origin != NULL), in which case we need a new
+     DIE with a corresponding DW_AT_abstract_origin.  */
+  bool reusing_die;
+  if (parm_die && origin == NULL)
+    reusing_die = true;
+  else
+    {
+      parm_die = new_die (DW_TAG_formal_parameter, context_die, node);
+      reusing_die = false;
+    }
 
   switch (TREE_CODE_CLASS (TREE_CODE (node_or_origin)))
     {
@@ -17392,32 +18032,36 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
       ultimate_origin = decl_ultimate_origin (node_or_origin);
       if (node || ultimate_origin)
        origin = ultimate_origin;
+
+      if (reusing_die)
+       goto add_location;
+
       if (origin != NULL)
        add_abstract_origin_attribute (parm_die, origin);
       else if (emit_name_p)
        add_name_and_src_coords_attributes (parm_die, node);
       if (origin == NULL
-         || (! DECL_ABSTRACT (node_or_origin)
+         || (! DECL_ABSTRACT_P (node_or_origin)
              && variably_modified_type_p (TREE_TYPE (node_or_origin),
                                           decl_function_context
                                                            (node_or_origin))))
        {
          tree type = TREE_TYPE (node_or_origin);
          if (decl_by_reference_p (node_or_origin))
-           add_type_attribute (parm_die, TREE_TYPE (type), 0, 0,
-                               context_die);
+           add_type_attribute (parm_die, TREE_TYPE (type),
+                               TYPE_UNQUALIFIED, context_die);
          else
            add_type_attribute (parm_die, type,
-                               TREE_READONLY (node_or_origin),
-                               TREE_THIS_VOLATILE (node_or_origin),
+                               decl_quals (node_or_origin),
                                context_die);
        }
+    add_location:
       if (origin == NULL && DECL_ARTIFICIAL (node))
        add_AT_flag (parm_die, DW_AT_artificial, 1);
 
       if (node && node != origin)
         equate_decl_number_to_die (node, parm_die);
-      if (! DECL_ABSTRACT (node_or_origin))
+      if (! DECL_ABSTRACT_P (node_or_origin))
        add_location_or_const_value_attribute (parm_die, node_or_origin,
                                               node == NULL, DW_AT_location);
 
@@ -17425,7 +18069,8 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
 
     case tcc_type:
       /* We were called with some kind of a ..._TYPE node.  */
-      add_type_attribute (parm_die, node_or_origin, 0, 0, context_die);
+      add_type_attribute (parm_die, node_or_origin, TYPE_UNQUALIFIED,
+                         context_die);
       break;
 
     default:
@@ -17519,18 +18164,21 @@ gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die)
        break;
 
       /* Output a (nameless) DIE to represent the formal parameter itself.  */
-      parm_die = gen_formal_parameter_die (formal_type, NULL,
-                                          true /* Emit name attribute.  */,
-                                          context_die);
-      if (TREE_CODE (function_or_method_type) == METHOD_TYPE
-         && link == first_parm_type)
+      if (!POINTER_BOUNDS_TYPE_P (formal_type))
        {
-         add_AT_flag (parm_die, DW_AT_artificial, 1);
-         if (dwarf_version >= 3 || !dwarf_strict)
-           add_AT_die_ref (context_die, DW_AT_object_pointer, parm_die);
+         parm_die = gen_formal_parameter_die (formal_type, NULL,
+                                              true /* Emit name attribute.  */,
+                                              context_die);
+         if (TREE_CODE (function_or_method_type) == METHOD_TYPE
+             && link == first_parm_type)
+           {
+             add_AT_flag (parm_die, DW_AT_artificial, 1);
+             if (dwarf_version >= 3 || !dwarf_strict)
+               add_AT_die_ref (context_die, DW_AT_object_pointer, parm_die);
+           }
+         else if (arg && DECL_ARTIFICIAL (arg))
+           add_AT_flag (parm_die, DW_AT_artificial, 1);
        }
-      else if (arg && DECL_ARTIFICIAL (arg))
-       add_AT_flag (parm_die, DW_AT_artificial, 1);
 
       link = TREE_CHAIN (link);
       if (arg)
@@ -17596,7 +18244,7 @@ gen_type_die_for_member (tree type, tree member, dw_die_ref context_die)
 /* Forward declare these functions, because they are mutually recursive
   with their set_block_* pairing functions.  */
 static void set_decl_origin_self (tree);
-static void set_decl_abstract_flags (tree, int);
+static void set_decl_abstract_flags (tree, vec<tree> &);
 
 /* Given a pointer to some BLOCK node, if the BLOCK_ABSTRACT_ORIGIN for the
    given BLOCK node is NULL, set the BLOCK_ABSTRACT_ORIGIN for the node so
@@ -17621,8 +18269,11 @@ set_block_origin_self (tree stmt)
        for (local_decl = BLOCK_VARS (stmt);
             local_decl != NULL_TREE;
             local_decl = DECL_CHAIN (local_decl))
-         if (! DECL_EXTERNAL (local_decl))
-           set_decl_origin_self (local_decl);  /* Potential recursion.  */
+         /* Do not recurse on nested functions since the inlining status
+            of parent and child can be different as per the DWARF spec.  */
+         if (TREE_CODE (local_decl) != FUNCTION_DECL
+             && !DECL_EXTERNAL (local_decl))
+           set_decl_origin_self (local_decl);
       }
 
       {
@@ -17666,64 +18317,86 @@ set_decl_origin_self (tree decl)
     }
 }
 \f
-/* Given a pointer to some BLOCK node, and a boolean value to set the
-   "abstract" flags to, set that value into the BLOCK_ABSTRACT flag for
-   the given block, and for all local decls and all local sub-blocks
-   (recursively) which are contained therein.  */
+/* Given a pointer to some BLOCK node, set the BLOCK_ABSTRACT flag to 1
+   and if it wasn't 1 before, push it to abstract_vec vector.
+   For all local decls and all local sub-blocks (recursively) do it
+   too.  */
 
 static void
-set_block_abstract_flags (tree stmt, int setting)
+set_block_abstract_flags (tree stmt, vec<tree> &abstract_vec)
 {
   tree local_decl;
   tree subblock;
   unsigned int i;
 
-  BLOCK_ABSTRACT (stmt) = setting;
+  if (!BLOCK_ABSTRACT (stmt))
+    {
+      abstract_vec.safe_push (stmt);
+      BLOCK_ABSTRACT (stmt) = 1;
+    }
 
   for (local_decl = BLOCK_VARS (stmt);
        local_decl != NULL_TREE;
        local_decl = DECL_CHAIN (local_decl))
     if (! DECL_EXTERNAL (local_decl))
-      set_decl_abstract_flags (local_decl, setting);
+      set_decl_abstract_flags (local_decl, abstract_vec);
 
   for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++)
     {
       local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i);
       if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl))
          || TREE_CODE (local_decl) == PARM_DECL)
-       set_decl_abstract_flags (local_decl, setting);
+       set_decl_abstract_flags (local_decl, abstract_vec);
     }
 
   for (subblock = BLOCK_SUBBLOCKS (stmt);
        subblock != NULL_TREE;
        subblock = BLOCK_CHAIN (subblock))
-    set_block_abstract_flags (subblock, setting);
+    set_block_abstract_flags (subblock, abstract_vec);
 }
 
-/* Given a pointer to some ..._DECL node, and a boolean value to set the
-   "abstract" flags to, set that value into the DECL_ABSTRACT flag for the
-   given decl, and (in the case where the decl is a FUNCTION_DECL) also
-   set the abstract flags for all of the parameters, local vars, local
-   blocks and sub-blocks (recursively) to the same setting.  */
+/* Given a pointer to some ..._DECL node, set DECL_ABSTRACT_P flag on it
+   to 1 and if it wasn't 1 before, push to abstract_vec vector.
+   In the case where the decl is a FUNCTION_DECL also set the abstract
+   flags for all of the parameters, local vars, local
+   blocks and sub-blocks (recursively).  */
 
 static void
-set_decl_abstract_flags (tree decl, int setting)
+set_decl_abstract_flags (tree decl, vec<tree> &abstract_vec)
 {
-  DECL_ABSTRACT (decl) = setting;
+  if (!DECL_ABSTRACT_P (decl))
+    {
+      abstract_vec.safe_push (decl);
+      DECL_ABSTRACT_P (decl) = 1;
+    }
+
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
       tree arg;
 
       for (arg = DECL_ARGUMENTS (decl); arg; arg = DECL_CHAIN (arg))
-       DECL_ABSTRACT (arg) = setting;
+       if (!DECL_ABSTRACT_P (arg))
+         {
+           abstract_vec.safe_push (arg);
+           DECL_ABSTRACT_P (arg) = 1;
+         }
       if (DECL_INITIAL (decl) != NULL_TREE
          && DECL_INITIAL (decl) != error_mark_node)
-       set_block_abstract_flags (DECL_INITIAL (decl), setting);
+       set_block_abstract_flags (DECL_INITIAL (decl), abstract_vec);
     }
 }
 
 /* Generate the DWARF2 info for the "abstract" instance of a function which we
-   may later generate inlined and/or out-of-line instances of.  */
+   may later generate inlined and/or out-of-line instances of.
+
+   FIXME: In the early-dwarf world, this function, and most of the
+          DECL_ABSTRACT code should be obsoleted.  The early DIE _is_
+          the abstract instance.  All we would need to do is annotate
+          the early DIE with the appropriate DW_AT_inline in late
+          dwarf (perhaps in gen_inlined_subroutine_die).
+
+         However, we can't do this yet, because LTO streaming of DIEs
+         has not been implemented yet.  */
 
 static void
 dwarf2out_abstract_function (tree decl)
@@ -17731,9 +18404,8 @@ dwarf2out_abstract_function (tree decl)
   dw_die_ref old_die;
   tree save_fn;
   tree context;
-  int was_abstract;
-  htab_t old_decl_loc_table;
-  htab_t old_cached_dw_loc_list_table;
+  hash_table<decl_loc_hasher> *old_decl_loc_table;
+  hash_table<dw_loc_list_hasher> *old_cached_dw_loc_list_table;
   int old_call_site_count, old_tail_call_site_count;
   struct call_arg_loc_node *old_call_arg_locations;
 
@@ -17760,7 +18432,7 @@ dwarf2out_abstract_function (tree decl)
   tail_call_site_count = -1;
 
   /* Be sure we've emitted the in-class declaration DIE (if any) first, so
-     we don't get confused by DECL_ABSTRACT.  */
+     we don't get confused by DECL_ABSTRACT_P.  */
   if (debug_info_level > DINFO_LEVEL_TERSE)
     {
       context = decl_class_context (decl);
@@ -17773,11 +18445,16 @@ dwarf2out_abstract_function (tree decl)
   save_fn = current_function_decl;
   current_function_decl = decl;
 
-  was_abstract = DECL_ABSTRACT (decl);
-  set_decl_abstract_flags (decl, 1);
+  auto_vec<tree, 64> abstract_vec;
+  set_decl_abstract_flags (decl, abstract_vec);
   dwarf2out_decl (decl);
-  if (! was_abstract)
-    set_decl_abstract_flags (decl, 0);
+  unsigned int i;
+  tree t;
+  FOR_EACH_VEC_ELT (abstract_vec, i, t)
+    if (TREE_CODE (t) == BLOCK)
+      BLOCK_ABSTRACT (t) = 0;
+    else
+      DECL_ABSTRACT_P (t) = 0;
 
   current_function_decl = save_fn;
   decl_loc_table = old_decl_loc_table;
@@ -17793,17 +18470,15 @@ dwarf2out_abstract_function (tree decl)
    Marks the DIE of a given type in *SLOT as perennial, so it never gets
    marked as unused by prune_unused_types.  */
 
-static int
-premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
+bool
+premark_used_types_helper (tree const &type, void *)
 {
-  tree type;
   dw_die_ref die;
 
-  type = (tree) *slot;
   die = lookup_type_die (type);
   if (die != NULL)
     die->die_perennial_p = 1;
-  return 1;
+  return true;
 }
 
 /* Helper function of premark_types_used_by_global_vars which gets called
@@ -17813,9 +18488,9 @@ premark_used_types_helper (void **slot, void *data ATTRIBUTE_UNUSED)
    marked as unused by prune_unused_types. The DIE of the type is marked
    only if the global variable using the type will actually be emitted.  */
 
-static int
-premark_types_used_by_global_vars_helper (void **slot,
-                                         void *data ATTRIBUTE_UNUSED)
+int
+premark_types_used_by_global_vars_helper (types_used_by_vars_entry **slot,
+                                         void *)
 {
   struct types_used_by_vars_entry *entry;
   dw_die_ref die;
@@ -17828,7 +18503,7 @@ premark_types_used_by_global_vars_helper (void **slot,
     {
       /* Ask cgraph if the global variable really is to be emitted.
          If yes, then we'll keep the DIE of ENTRY->TYPE.  */
-      varpool_node *node = varpool_get_node (entry->var_decl);
+      varpool_node *node = varpool_node::get (entry->var_decl);
       if (node && node->definition)
        {
          die->die_perennial_p = 1;
@@ -17846,7 +18521,7 @@ static void
 premark_used_types (struct function *fun)
 {
   if (fun && fun->used_types_hash)
-    htab_traverse (fun->used_types_hash, premark_used_types_helper, NULL);
+    fun->used_types_hash->traverse<void *, premark_used_types_helper> (NULL);
 }
 
 /* Mark all members of types_used_by_vars_entry as perennial.  */
@@ -17855,8 +18530,8 @@ static void
 premark_types_used_by_global_vars (void)
 {
   if (types_used_by_vars_hash)
-    htab_traverse (types_used_by_vars_hash,
-                  premark_types_used_by_global_vars_helper, NULL);
+    types_used_by_vars_hash
+      ->traverse<void *, premark_types_used_by_global_vars_helper> (NULL);
 }
 
 /* Generate a DW_TAG_GNU_call_site DIE in function DECL under SUBR_DIE
@@ -17873,8 +18548,7 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
         && block != DECL_INITIAL (decl)
         && TREE_CODE (block) == BLOCK)
     {
-      if (block_map.length () > BLOCK_NUMBER (block))
-       stmt_die = block_map[BLOCK_NUMBER (block)];
+      stmt_die = BLOCK_DIE (block);
       if (stmt_die)
        break;
       block = BLOCK_SUPERCONTEXT (block);
@@ -17904,26 +18578,94 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
   dw_die_ref subr_die;
-  tree outer_scope;
   dw_die_ref old_die = lookup_decl_die (decl);
+
+  /* This function gets called multiple times for different stages of
+     the debug process.  For example, for func() in this code:
+
+       namespace S
+       {
+         void func() { ... }
+       }
+
+     ...we get called 4 times.  Twice in early debug and twice in
+     late debug:
+
+     Early debug
+     -----------
+
+       1. Once while generating func() within the namespace.  This is
+          the declaration.  The declaration bit below is set, as the
+          context is the namespace.
+
+         A new DIE will be generated with DW_AT_declaration set.
+
+       2. Once for func() itself.  This is the specification.  The
+          declaration bit below is clear as the context is the CU.
+
+         We will use the cached DIE from (1) to create a new DIE with
+         DW_AT_specification pointing to the declaration in (1).
+
+     Late debug via rest_of_handle_final()
+     -------------------------------------
+
+       3. Once generating func() within the namespace.  This is also the
+          declaration, as in (1), but this time we will early exit below
+          as we have a cached DIE and a declaration needs no additional
+          annotations (no locations), as the source declaration line
+          info is enough.
+
+       4. Once for func() itself.  As in (2), this is the specification,
+          but this time we will re-use the cached DIE, and just annotate
+          it with the location information that should now be available.
+
+     For something without namespaces, but with abstract instances, we
+     are also called a multiple times:
+
+        class Base
+       {
+       public:
+         Base ();        // constructor declaration (1)
+       };
+
+       Base::Base () { } // constructor specification (2)
+
+    Early debug
+    -----------
+
+       1. Once for the Base() constructor by virtue of it being a
+          member of the Base class.  This is done via
+          rest_of_type_compilation.
+
+         This is a declaration, so a new DIE will be created with
+         DW_AT_declaration.
+
+       2. Once for the Base() constructor definition, but this time
+          while generating the abstract instance of the base
+          constructor (__base_ctor) which is being generated via early
+          debug of reachable functions.
+
+         Even though we have a cached version of the declaration (1),
+         we will create a DW_AT_specification of the declaration DIE
+         in (1).
+
+       3. Once for the __base_ctor itself, but this time, we generate
+          an DW_AT_abstract_origin version of the DW_AT_specification in
+         (2).
+
+    Late debug via rest_of_handle_final
+    -----------------------------------
+
+       4. One final time for the __base_ctor (which will have a cached
+          DIE with DW_AT_abstract_origin created in (3).  This time,
+          we will just annotate the location information now
+          available.
+  */
   int declaration = (current_function_decl != decl
                     || class_or_namespace_scope_p (context_die));
 
   premark_used_types (DECL_STRUCT_FUNCTION (decl));
 
-  /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we
-     started to generate the abstract instance of an inline, decided to output
-     its containing class, and proceeded to emit the declaration of the inline
-     from the member list for the class.  If so, DECLARATION takes priority;
-     we'll get back to the abstract instance when done with the class.  */
-
-  /* The class-scope declaration DIE must be the primary DIE.  */
-  if (origin && declaration && class_or_namespace_scope_p (context_die))
-    {
-      origin = NULL;
-      gcc_assert (!old_die);
-    }
-
   /* Now that the C++ front end lazily declares artificial member fns, we
      might need to retrofit the declaration into its class.  */
   if (!declaration && !origin && !old_die
@@ -17932,6 +18674,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       && debug_info_level > DINFO_LEVEL_TERSE)
     old_die = force_decl_die (decl);
 
+  /* An inlined instance, tag a new DIE with DW_AT_abstract_origin.  */
   if (origin != NULL)
     {
       gcc_assert (!declaration || local_scope_p (context_die));
@@ -17941,19 +18684,32 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (old_die && old_die->die_parent == NULL)
        add_child_die (context_die, old_die);
 
-      subr_die = new_die (DW_TAG_subprogram, context_die, decl);
-      add_abstract_origin_attribute (subr_die, origin);
-      /*  This is where the actual code for a cloned function is.
-         Let's emit linkage name attribute for it.  This helps
-         debuggers to e.g, set breakpoints into
-         constructors/destructors when the user asks "break
-         K::K".  */
-      add_linkage_name (subr_die, decl);
+      if (old_die && get_AT_ref (old_die, DW_AT_abstract_origin))
+       {
+         /* If we have a DW_AT_abstract_origin we have a working
+            cached version.  */
+         subr_die = old_die;
+       }
+      else
+       {
+         subr_die = new_die (DW_TAG_subprogram, context_die, decl);
+         add_abstract_origin_attribute (subr_die, origin);
+         /*  This is where the actual code for a cloned function is.
+             Let's emit linkage name attribute for it.  This helps
+             debuggers to e.g, set breakpoints into
+             constructors/destructors when the user asks "break
+             K::K".  */
+         add_linkage_name (subr_die, decl);
+       }
     }
+  /* A cached copy, possibly from early dwarf generation.  Reuse as
+     much as possible.  */
   else if (old_die)
     {
-      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
-      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      /* A declaration that has been previously dumped needs no
+        additional information.  */
+      if (declaration)
+       return;
 
       if (!get_AT_flag (old_die, DW_AT_declaration)
          /* We can have a normal definition following an inline one in the
@@ -17963,7 +18719,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          /* Detect and ignore this case, where we are trying to output
             something we have already output.  */
-         return;
+         if (get_AT (old_die, DW_AT_low_pc)
+             || get_AT (old_die, DW_AT_ranges))
+           return;
+
+         /* If we have no location information, this must be a
+            partially generated DIE from early dwarf generation.
+            Fall through and generate it.  */
        }
 
       /* If the definition comes from the same place as the declaration,
@@ -17973,23 +18735,43 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
         instances of inlines, since the spec requires the out-of-line copy
         to have the same parent.  For local class methods, this doesn't
         apply; we just use the old DIE.  */
-      if ((is_cu_die (old_die->die_parent) || context_die == NULL)
-         && (DECL_ARTIFICIAL (decl)
-             || (get_AT_file (old_die, DW_AT_decl_file) == file_index
-                 && (get_AT_unsigned (old_die, DW_AT_decl_line)
-                     == (unsigned) s.line))))
+      expanded_location s = expand_location (DECL_SOURCE_LOCATION (decl));
+      struct dwarf_file_data * file_index = lookup_filename (s.file);
+      if ((is_cu_die (old_die->die_parent)
+          /* This condition fixes the inconsistency/ICE with the
+             following Fortran test (or some derivative thereof) while
+             building libgfortran:
+
+                module some_m
+                contains
+                   logical function funky (FLAG)
+                     funky = .true.
+                  end function
+                end module
+          */
+          || old_die->die_parent->die_tag == DW_TAG_module
+          || context_die == NULL)
+          && (DECL_ARTIFICIAL (decl)
+              || (get_AT_file (old_die, DW_AT_decl_file) == file_index
+                  && (get_AT_unsigned (old_die, DW_AT_decl_line)
+                      == (unsigned) s.line))))
        {
          subr_die = old_die;
 
-         /* Clear out the declaration attribute and the formal parameters.
-            Do not remove all children, because it is possible that this
-            declaration die was forced using force_decl_die(). In such
-            cases die that forced declaration die (e.g. TAG_imported_module)
-            is one of the children that we do not want to remove.  */
-         remove_AT (subr_die, DW_AT_declaration);
-         remove_AT (subr_die, DW_AT_object_pointer);
-         remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+         /* Clear out the declaration attribute, but leave the
+            parameters so they can be augmented with location
+            information later.  Unless this was a declaration, in
+            which case, wipe out the nameless parameters and recreate
+            them further down.  */
+         if (remove_AT (subr_die, DW_AT_declaration))
+           {
+
+             remove_AT (subr_die, DW_AT_object_pointer);
+             remove_child_TAG (subr_die, DW_TAG_formal_parameter);
+           }
        }
+      /* Make a specification pointing to the previously built
+        declaration.  */
       else
        {
          subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -17999,8 +18781,19 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            add_AT_file (subr_die, DW_AT_decl_file, file_index);
          if (get_AT_unsigned (old_die, DW_AT_decl_line) != (unsigned) s.line)
            add_AT_unsigned (subr_die, DW_AT_decl_line, s.line);
+
+         /* If the prototype had an 'auto' or 'decltype(auto)' return type,
+            emit the real type on the definition die.  */
+         if (is_cxx() && debug_info_level > DINFO_LEVEL_TERSE)
+           {
+             dw_die_ref die = get_AT_ref (old_die, DW_AT_type);
+             if (die == auto_die || die == decltype_auto_die)
+               add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
+                                   TYPE_UNQUALIFIED, context_die);
+           }
        }
     }
+  /* Create a fresh DIE for anything else.  */
   else
     {
       subr_die = new_die (DW_TAG_subprogram, context_die, decl);
@@ -18014,16 +18807,24 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        {
          add_prototyped_attribute (subr_die, TREE_TYPE (decl));
          add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
-                             0, 0, context_die);
+                             TYPE_UNQUALIFIED, context_die);
        }
 
       add_pure_or_virtual_attribute (subr_die, decl);
       if (DECL_ARTIFICIAL (decl))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
 
+      if (TREE_THIS_VOLATILE (decl) && (dwarf_version >= 5 || !dwarf_strict))
+       add_AT_flag (subr_die, DW_AT_noreturn, 1);
+
       add_accessibility_attribute (subr_die, decl);
     }
 
+  /* Unless we have an existing non-declaration DIE, equate the new
+     DIE.  */
+  if (!old_die || is_declaration_die (old_die))
+    equate_decl_number_to_die (decl, subr_die);
+
   if (declaration)
     {
       if (!old_die || !get_AT (old_die, DW_AT_inline))
@@ -18036,17 +18837,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
              && (dwarf_version >= 3 || !dwarf_strict))
            add_AT_flag (subr_die, DW_AT_explicit, 1);
 
-         /* The first time we see a member function, it is in the context of
-            the class to which it belongs.  We make sure of this by emitting
-            the class first.  The next time is the definition, which is
-            handled above.  The two may come from the same source text.
-
-            Note that force_decl_die() forces function declaration die. It is
-            later reused to represent definition.  */
-         equate_decl_number_to_die (decl, subr_die);
+         /* If this is a C++11 deleted special function member then generate
+            a DW_AT_GNU_deleted attribute.  */
+         if (lang_hooks.decls.function_decl_deleted_p (decl)
+             && (! dwarf_strict))
+           add_AT_flag (subr_die, DW_AT_GNU_deleted, 1);
        }
     }
-  else if (DECL_ABSTRACT (decl))
+  /* Tag abstract instances with DW_AT_inline.  */
+  else if (DECL_ABSTRACT_P (decl))
     {
       if (DECL_DECLARED_INLINE_P (decl))
        {
@@ -18066,18 +18865,15 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_DECLARED_INLINE_P (decl)
          && lookup_attribute ("artificial", DECL_ATTRIBUTES (decl)))
        add_AT_flag (subr_die, DW_AT_artificial, 1);
-
-      equate_decl_number_to_die (decl, subr_die);
     }
-  else if (!DECL_EXTERNAL (decl))
+  /* For non DECL_EXTERNALs, if range information is available, fill
+     the DIE with it.  */
+  else if (!DECL_EXTERNAL (decl) && !early_dwarf)
     {
       HOST_WIDE_INT cfa_fb_offset;
-      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      if (!old_die || !get_AT (old_die, DW_AT_inline))
-       equate_decl_number_to_die (decl, subr_die);
+      struct function *fun = DECL_STRUCT_FUNCTION (decl);
 
-      gcc_checking_assert (fun);
       if (!flag_reorder_blocks_and_partition)
        {
          dw_fde_ref fde = fun->fde;
@@ -18231,12 +19027,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       compute_frame_pointer_to_fb_displacement (cfa_fb_offset);
 
       if (fun->static_chain_decl)
-       add_AT_location_description (subr_die, DW_AT_static_link,
-                loc_list_from_tree (fun->static_chain_decl, 2));
+       add_AT_location_description
+         (subr_die, DW_AT_static_link,
+          loc_list_from_tree (fun->static_chain_decl, 2, NULL));
     }
 
   /* Generate child dies for template paramaters.  */
-  if (debug_info_level > DINFO_LEVEL_TERSE)
+  if (early_dwarf && debug_info_level > DINFO_LEVEL_TERSE)
     gen_generic_params_dies (decl);
 
   /* Now output descriptions of the arguments for this function. This gets
@@ -18260,7 +19057,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
     {
       /* Generate DIEs to represent all known formal parameters.  */
       tree parm = DECL_ARGUMENTS (decl);
-      tree generic_decl = lang_hooks.decls.get_generic_function_decl (decl);
+      tree generic_decl = early_dwarf
+       ? lang_hooks.decls.get_generic_function_decl (decl) : NULL;
       tree generic_decl_parm = generic_decl
                                ? DECL_ARGUMENTS (generic_decl)
                                : NULL;
@@ -18290,7 +19088,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
            gen_formal_parameter_pack_die (generic_decl_parm,
                                           parm, subr_die,
                                           &parm);
-         else if (parm)
+         else if (parm && !POINTER_BOUNDS_P (parm))
            {
              dw_die_ref parm_die = gen_decl_die (parm, NULL, subr_die);
 
@@ -18302,6 +19100,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
              parm = DECL_CHAIN (parm);
            }
+         else if (parm)
+           parm = DECL_CHAIN (parm);
 
          if (generic_decl_parm)
            generic_decl_parm = DECL_CHAIN (generic_decl_parm);
@@ -18323,11 +19123,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
        gen_unspecified_parameters_die (decl, subr_die);
     }
 
+  if (subr_die != old_die)
+    /* Add the calling convention attribute if requested.  */
+    add_calling_convention_attribute (subr_die, decl);
+
   /* Output Dwarf info for all of the stuff within the body of the function
-     (if it has one - it may be just a declaration).  */
-  outer_scope = DECL_INITIAL (decl);
+     (if it has one - it may be just a declaration).
 
-  /* OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
+     OUTER_SCOPE is a pointer to the outermost BLOCK node created to represent
      a function.  This BLOCK actually represents the outermost binding contour
      for the function, i.e. the contour in which the function's formal
      parameters and labels get declared. Curiously, it appears that the front
@@ -18341,6 +19144,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
      a BLOCK node representing the function's outermost pair of curly braces,
      and any blocks used for the base and member initializers of a C++
      constructor function.  */
+  tree outer_scope = DECL_INITIAL (decl);
   if (! declaration && outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
     {
       int call_site_note_count = 0;
@@ -18350,8 +19154,10 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       if (DECL_NAME (DECL_RESULT (decl)))
        gen_decl_die (DECL_RESULT (decl), NULL, subr_die);
 
-      current_function_has_inlines = 0;
-      decls_for_scope (outer_scope, subr_die, 0);
+      /* The first time through decls_for_scope we will generate the
+        DIEs for the locals.  The second time, we fill in the
+        location info.  */
+      decls_for_scope (outer_scope, subr_die);
 
       if (call_arg_locations && !dwarf_strict)
        {
@@ -18366,7 +19172,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
                   arg; arg = next_arg)
                {
                  dw_loc_descr_ref reg, val;
-                 enum machine_mode mode = GET_MODE (XEXP (XEXP (arg, 0), 1));
+                 machine_mode mode = GET_MODE (XEXP (XEXP (arg, 0), 1));
                  dw_die_ref cdie, tdie = NULL;
 
                  next_arg = XEXP (arg, 1);
@@ -18502,29 +19308,50 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
       call_site_count = -1;
       tail_call_site_count = -1;
     }
-  /* Add the calling convention attribute if requested.  */
-  add_calling_convention_attribute (subr_die, decl);
-
 }
 
 /* Returns a hash value for X (which really is a die_struct).  */
 
-static hashval_t
-common_block_die_table_hash (const void *x)
+hashval_t
+block_die_hasher::hash (die_struct *d)
 {
-  const_dw_die_ref d = (const_dw_die_ref) x;
   return (hashval_t) d->decl_id ^ htab_hash_pointer (d->die_parent);
 }
 
 /* Return nonzero if decl_id and die_parent of die_struct X is the same
    as decl_id and die_parent of die_struct Y.  */
 
-static int
-common_block_die_table_eq (const void *x, const void *y)
+bool
+block_die_hasher::equal (die_struct *x, die_struct *y)
+{
+  return x->decl_id == y->decl_id && x->die_parent == y->die_parent;
+}
+
+/* Return TRUE if DECL, which may have been previously generated as
+   OLD_DIE, is a candidate for a DW_AT_specification.  DECLARATION is
+   true if decl (or its origin) is either an extern declaration or a
+   class/namespace scoped declaration.
+
+   The declare_in_namespace support causes us to get two DIEs for one
+   variable, both of which are declarations.  We want to avoid
+   considering one to be a specification, so we must test for
+   DECLARATION and DW_AT_declaration.  */
+static inline bool
+decl_will_get_specification_p (dw_die_ref old_die, tree decl, bool declaration)
 {
-  const_dw_die_ref d = (const_dw_die_ref) x;
-  const_dw_die_ref e = (const_dw_die_ref) y;
-  return d->decl_id == e->decl_id && d->die_parent == e->die_parent;
+  return (old_die && TREE_STATIC (decl) && !declaration
+         && get_AT_flag (old_die, DW_AT_declaration) == 1);
+}
+
+/* Return true if DECL is a local static.  */
+
+static inline bool
+local_function_static (tree decl)
+{
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  return TREE_STATIC (decl)
+    && DECL_CONTEXT (decl)
+    && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL;
 }
 
 /* Generate a DIE to represent a declared data object.
@@ -18539,7 +19366,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   tree ultimate_origin;
   dw_die_ref var_die;
   dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
-  dw_die_ref origin_die;
+  dw_die_ref origin_die = NULL;
   bool declaration = (DECL_EXTERNAL (decl_or_origin)
                      || class_or_namespace_scope_p (context_die));
   bool specialization_p = false;
@@ -18562,7 +19389,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
        {
          if (get_AT (var_die, DW_AT_location) == NULL)
            {
-             loc = loc_list_from_tree (com_decl, off ? 1 : 2);
+             loc = loc_list_from_tree (com_decl, off ? 1 : 2, NULL);
              if (loc)
                {
                  if (off)
@@ -18589,19 +19416,17 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
        }
 
       if (common_block_die_table == NULL)
-       common_block_die_table
-         = htab_create_ggc (10, common_block_die_table_hash,
-                            common_block_die_table_eq, NULL);
+       common_block_die_table = hash_table<block_die_hasher>::create_ggc (10);
 
       com_die_arg.decl_id = DECL_UID (com_decl);
       com_die_arg.die_parent = context_die;
-      com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
-      loc = loc_list_from_tree (com_decl, 2);
+      com_die = common_block_die_table->find (&com_die_arg);
+      loc = loc_list_from_tree (com_decl, 2, NULL);
       if (com_die == NULL)
        {
          const char *cnam
            = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (com_decl));
-         void **slot;
+         die_node **slot;
 
          com_die = new_die (DW_TAG_common_block, context_die, decl);
          add_name_and_src_coords_attributes (com_die, com_decl);
@@ -18610,26 +19435,26 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
              add_AT_location_description (com_die, DW_AT_location, loc);
              /* Avoid sharing the same loc descriptor between
                 DW_TAG_common_block and DW_TAG_variable.  */
-             loc = loc_list_from_tree (com_decl, 2);
+             loc = loc_list_from_tree (com_decl, 2, NULL);
            }
           else if (DECL_EXTERNAL (decl))
            add_AT_flag (com_die, DW_AT_declaration, 1);
          if (want_pubnames ())
            add_pubname_string (cnam, com_die); /* ??? needed? */
          com_die->decl_id = DECL_UID (com_decl);
-         slot = htab_find_slot (common_block_die_table, com_die, INSERT);
-         *slot = (void *) com_die;
+         slot = common_block_die_table->find_slot (com_die, INSERT);
+         *slot = com_die;
        }
       else if (get_AT (com_die, DW_AT_location) == NULL && loc)
        {
          add_AT_location_description (com_die, DW_AT_location, loc);
-         loc = loc_list_from_tree (com_decl, 2);
+         loc = loc_list_from_tree (com_decl, 2, NULL);
          remove_AT (com_die, DW_AT_declaration);
        }
       var_die = new_die (DW_TAG_variable, com_die, decl);
       add_name_and_src_coords_attributes (var_die, decl);
-      add_type_attribute (var_die, TREE_TYPE (decl), TREE_READONLY (decl),
-                         TREE_THIS_VOLATILE (decl), context_die);
+      add_type_attribute (var_die, TREE_TYPE (decl), decl_quals (decl),
+                         context_die);
       add_AT_flag (var_die, DW_AT_external, 1);
       if (loc)
        {
@@ -18656,12 +19481,38 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       return;
     }
 
-  /* If the compiler emitted a definition for the DECL declaration
-     and if we already emitted a DIE for it, don't emit a second
-     DIE for it again. Allow re-declarations of DECLs that are
-     inside functions, though.  */
-  if (old_die && declaration && !local_scope_p (context_die))
-    return;
+  if (old_die)
+    {
+      if (declaration)
+       {
+         /* A declaration that has been previously dumped, needs no
+            further annotations, since it doesn't need location on
+            the second pass.  */
+         return;
+       }
+      else if (decl_will_get_specification_p (old_die, decl, declaration)
+              && !get_AT (old_die, DW_AT_specification))
+       {
+         /* Fall-thru so we can make a new variable die along with a
+            DW_AT_specification.  */
+       }
+      else if (origin && old_die->die_parent != context_die)
+       {
+         /* If we will be creating an inlined instance, we need a
+            new DIE that will get annotated with
+            DW_AT_abstract_origin.  Clear things so we can get a
+            new DIE.  */
+         gcc_assert (!DECL_ABSTRACT_P (decl));
+         old_die = NULL;
+       }
+      else
+       {
+         /* If a DIE was dumped early, it still needs location info.
+            Skip to where we fill the location bits.  */
+         var_die = old_die;
+         goto gen_variable_die_location;
+       }
+    }
 
   /* For static data members, the declaration in the class is supposed
      to have DW_TAG_member tag; the specification should still be
@@ -18671,7 +19522,6 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   else
     var_die = new_die (DW_TAG_variable, context_die, decl);
 
-  origin_die = NULL;
   if (origin != NULL)
     origin_die = add_abstract_origin_attribute (var_die, origin);
 
@@ -18679,17 +19529,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
      static variable, so we must test for the DW_AT_declaration flag.
 
      ??? Loop unrolling/reorder_blocks should perhaps be rewritten to
-     copy decls and set the DECL_ABSTRACT flag on them instead of
+     copy decls and set the DECL_ABSTRACT_P flag on them instead of
      sharing them.
 
-     ??? Duplicated blocks have been rewritten to use .debug_ranges.
-
-     ??? The declare_in_namespace support causes us to get two DIEs for one
-     variable, both of which are declarations.  We want to avoid considering
-     one to be a specification, so we must test that this DIE is not a
-     declaration.  */
-  else if (old_die && TREE_STATIC (decl) && ! declaration
-          && get_AT_flag (old_die, DW_AT_declaration) == 1)
+     ??? Duplicated blocks have been rewritten to use .debug_ranges.  */
+  else if (decl_will_get_specification_p (old_die, decl, declaration))
     {
       /* This is a definition of a C++ class level static.  */
       add_AT_specification (var_die, old_die);
@@ -18714,7 +19558,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 
   if ((origin == NULL && !specialization_p)
       || (origin != NULL
-         && !DECL_ABSTRACT (decl_or_origin)
+         && !DECL_ABSTRACT_P (decl_or_origin)
          && variably_modified_type_p (TREE_TYPE (decl_or_origin),
                                       decl_function_context
                                                        (decl_or_origin))))
@@ -18722,10 +19566,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       tree type = TREE_TYPE (decl_or_origin);
 
       if (decl_by_reference_p (decl_or_origin))
-       add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die);
+       add_type_attribute (var_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+                           context_die);
       else
-       add_type_attribute (var_die, type, TREE_READONLY (decl_or_origin),
-                           TREE_THIS_VOLATILE (decl_or_origin), context_die);
+       add_type_attribute (var_die, type, decl_quals (decl_or_origin),
+                           context_die);
     }
 
   if (origin == NULL && !specialization_p)
@@ -18742,11 +19587,13 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
   if (declaration)
     add_AT_flag (var_die, DW_AT_declaration, 1);
 
-  if (decl && (DECL_ABSTRACT (decl) || declaration || old_die == NULL))
+  if (decl && (DECL_ABSTRACT_P (decl)
+              || !old_die || is_declaration_die (old_die)))
     equate_decl_number_to_die (decl, var_die);
 
+ gen_variable_die_location:
   if (! declaration
-      && (! DECL_ABSTRACT (decl_or_origin)
+      && (! DECL_ABSTRACT_P (decl_or_origin)
          /* Local static vars are shared between all clones/inlines,
             so emit DW_AT_location on the abstract DIE if DECL_RTL is
             already set.  */
@@ -18757,13 +19604,11 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
         to add it again.  */
       && (origin_die == NULL || get_AT (origin_die, DW_AT_location) == NULL))
     {
-      if (TREE_CODE (decl_or_origin) == VAR_DECL && TREE_STATIC (decl_or_origin)
-          && !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl_or_origin)))
-       defer_location (decl_or_origin, var_die);
+      if (early_dwarf)
+       add_pubname (decl_or_origin, var_die);
       else
-        add_location_or_const_value_attribute (var_die, decl_or_origin,
+       add_location_or_const_value_attribute (var_die, decl_or_origin,
                                               decl == NULL, DW_AT_location);
-      add_pubname (decl_or_origin, var_die);
     }
   else
     tree_add_const_value_attribute_for_decl (var_die, decl_or_origin);
@@ -18777,9 +19622,14 @@ gen_const_die (tree decl, dw_die_ref context_die)
   dw_die_ref const_die;
   tree type = TREE_TYPE (decl);
 
+  const_die = lookup_decl_die (decl);
+  if (const_die)
+    return;
+
   const_die = new_die (DW_TAG_constant, context_die, decl);
+  equate_decl_number_to_die (decl, const_die);
   add_name_and_src_coords_attributes (const_die, decl);
-  add_type_attribute (const_die, type, 1, 0, context_die);
+  add_type_attribute (const_die, type, TYPE_QUAL_CONST, context_die);
   if (TREE_PUBLIC (decl))
     add_AT_flag (const_die, DW_AT_external, 1);
   if (DECL_ARTIFICIAL (decl))
@@ -18793,16 +19643,22 @@ static void
 gen_label_die (tree decl, dw_die_ref context_die)
 {
   tree origin = decl_ultimate_origin (decl);
-  dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl);
+  dw_die_ref lbl_die = lookup_decl_die (decl);
   rtx insn;
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  if (origin != NULL)
-    add_abstract_origin_attribute (lbl_die, origin);
-  else
-    add_name_and_src_coords_attributes (lbl_die, decl);
+  if (!lbl_die)
+    {
+      lbl_die = new_die (DW_TAG_label, context_die, decl);
+      equate_decl_number_to_die (decl, lbl_die);
+
+      if (origin != NULL)
+       add_abstract_origin_attribute (lbl_die, origin);
+      else
+       add_name_and_src_coords_attributes (lbl_die, decl);
+    }
 
-  if (DECL_ABSTRACT (decl))
+  if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, lbl_die);
   else
     {
@@ -18821,7 +19677,7 @@ gen_label_die (tree decl, dw_die_ref context_die)
             represent source-level labels which were explicitly declared by
             the user.  This really shouldn't be happening though, so catch
             it if it ever does happen.  */
-         gcc_assert (!INSN_DELETED_P (insn));
+         gcc_assert (!as_a<rtx_insn *> (insn)->deleted ());
 
          ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (insn));
           add_AT_lbl_id (lbl_die, DW_AT_low_pc, label);
@@ -18952,27 +19808,66 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
 /* Generate a DIE for a lexical block.  */
 
 static void
-gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth)
+gen_lexical_block_die (tree stmt, dw_die_ref context_die)
 {
-  dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+  dw_die_ref old_die = BLOCK_DIE (stmt);
+  dw_die_ref stmt_die = NULL;
+  if (!old_die)
+    {
+      stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+      BLOCK_DIE (stmt) = stmt_die;
+    }
 
-  if (call_arg_locations)
+  if (BLOCK_ABSTRACT (stmt))
     {
-      if (block_map.length () <= BLOCK_NUMBER (stmt))
-       block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
-      block_map[BLOCK_NUMBER (stmt)] = stmt_die;
+      if (old_die)
+       {
+#ifdef ENABLE_CHECKING
+         /* This must have been generated early and it won't even
+            need location information since it's a DW_AT_inline
+            function.  */
+         for (dw_die_ref c = context_die; c; c = c->die_parent)
+           if (c->die_tag == DW_TAG_inlined_subroutine
+               || c->die_tag == DW_TAG_subprogram)
+             {
+               gcc_assert (get_AT (c, DW_AT_inline));
+               break;
+             }
+#endif
+         return;
+       }
+    }
+  else if (BLOCK_ABSTRACT_ORIGIN (stmt))
+    {
+      /* If this is an inlined instance, create a new lexical die for
+        anything below to attach DW_AT_abstract_origin to.  */
+      if (old_die)
+       {
+         stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt);
+         BLOCK_DIE (stmt) = stmt_die;
+         old_die = NULL;
+       }
     }
 
-  if (! BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
-    add_high_low_attributes (stmt, stmt_die);
+  if (old_die)
+    stmt_die = old_die;
 
-  decls_for_scope (stmt, stmt_die, depth);
+  /* A non abstract block whose blocks have already been reordered
+     should have the instruction range for this block.  If so, set the
+     high/low attributes.  */
+  if (!early_dwarf && !BLOCK_ABSTRACT (stmt) && TREE_ASM_WRITTEN (stmt))
+    {
+      gcc_assert (stmt_die);
+      add_high_low_attributes (stmt, stmt_die);
+    }
+
+  decls_for_scope (stmt, stmt_die);
 }
 
 /* Generate a DIE for an inlined subprogram.  */
 
 static void
-gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth)
+gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die)
 {
   tree decl;
 
@@ -18994,18 +19889,13 @@ gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth)
        = new_die (DW_TAG_inlined_subroutine, context_die, stmt);
 
       if (call_arg_locations)
-       {
-         if (block_map.length () <= BLOCK_NUMBER (stmt))
-           block_map.safe_grow_cleared (BLOCK_NUMBER (stmt) + 1);
-         block_map[BLOCK_NUMBER (stmt)] = subr_die;
-       }
+       BLOCK_DIE (stmt) = subr_die;
       add_abstract_origin_attribute (subr_die, decl);
       if (TREE_ASM_WRITTEN (stmt))
         add_high_low_attributes (stmt, subr_die);
       add_call_src_coords_attributes (stmt, subr_die);
 
-      decls_for_scope (stmt, subr_die, depth);
-      current_function_has_inlines = 1;
+      decls_for_scope (stmt, subr_die);
     }
 }
 
@@ -19022,8 +19912,7 @@ gen_field_die (tree decl, dw_die_ref context_die)
   decl_die = new_die (DW_TAG_member, context_die, decl);
   add_name_and_src_coords_attributes (decl_die, decl);
   add_type_attribute (decl_die, member_declared_type (decl),
-                     TREE_READONLY (decl), TREE_THIS_VOLATILE (decl),
-                     context_die);
+                     decl_quals (decl), context_die);
 
   if (DECL_BIT_FIELD_TYPE (decl))
     {
@@ -19057,7 +19946,8 @@ gen_pointer_type_die (tree type, dw_die_ref context_die)
     = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
-  add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+                     context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
 
@@ -19077,7 +19967,8 @@ gen_reference_type_die (tree type, dw_die_ref context_die)
     ref_die = new_die (DW_TAG_reference_type, scope_die, type);
 
   equate_type_number_to_die (type, ref_die);
-  add_type_attribute (ref_die, TREE_TYPE (type), 0, 0, context_die);
+  add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+                     context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
 #endif
@@ -19094,7 +19985,8 @@ gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
   equate_type_number_to_die (type, ptr_die);
   add_AT_die_ref (ptr_die, DW_AT_containing_type,
                  lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
-  add_type_attribute (ptr_die, TREE_TYPE (type), 0, 0, context_die);
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+                     context_die);
 }
 
 typedef const char *dchar_p; /* For DEF_VEC_P.  */
@@ -19148,6 +20040,9 @@ gen_producer_string (void)
       case OPT__sysroot_:
       case OPT_nostdinc:
       case OPT_nostdinc__:
+      case OPT_fpreprocessed:
+      case OPT_fltrans_output_list_:
+      case OPT_fresolution_:
        /* Ignore these.  */
        continue;
       default:
@@ -19192,6 +20087,30 @@ gen_producer_string (void)
   return producer;
 }
 
+/* Given a C and/or C++ language/version string return the "highest".
+   C++ is assumed to be "higher" than C in this case.  Used for merging
+   LTO translation unit languages.  */
+static const char *
+highest_c_language (const char *lang1, const char *lang2)
+{
+  if (strcmp ("GNU C++14", lang1) == 0 || strcmp ("GNU C++14", lang2) == 0)
+    return "GNU C++14";
+  if (strcmp ("GNU C++11", lang1) == 0 || strcmp ("GNU C++11", lang2) == 0)
+    return "GNU C++11";
+  if (strcmp ("GNU C++98", lang1) == 0 || strcmp ("GNU C++98", lang2) == 0)
+    return "GNU C++98";
+
+  if (strcmp ("GNU C11", lang1) == 0 || strcmp ("GNU C11", lang2) == 0)
+    return "GNU C11";
+  if (strcmp ("GNU C99", lang1) == 0 || strcmp ("GNU C99", lang2) == 0)
+    return "GNU C99";
+  if (strcmp ("GNU C89", lang1) == 0 || strcmp ("GNU C89", lang2) == 0)
+    return "GNU C89";
+
+  gcc_unreachable ();
+}
+
+
 /* Generate the DIE for the compilation unit.  */
 
 static dw_die_ref
@@ -19232,7 +20151,8 @@ gen_compile_unit_die (const char *filename)
          else if (strncmp (common_lang, "GNU C", 5) == 0
                    && strncmp (TRANSLATION_UNIT_LANGUAGE (t), "GNU C", 5) == 0)
            /* Mixing C and C++ is ok, use C++ in that case.  */
-           common_lang = "GNU C++";
+           common_lang = highest_c_language (common_lang,
+                                             TRANSLATION_UNIT_LANGUAGE (t));
          else
            {
              /* Fall back to C.  */
@@ -19245,9 +20165,32 @@ gen_compile_unit_die (const char *filename)
        language_string = common_lang;
     }
 
-  language = DW_LANG_C89;
-  if (strcmp (language_string, "GNU C++") == 0)
-    language = DW_LANG_C_plus_plus;
+  language = DW_LANG_C;
+  if (strncmp (language_string, "GNU C", 5) == 0
+      && ISDIGIT (language_string[5]))
+    {
+      language = DW_LANG_C89;
+      if (dwarf_version >= 3 || !dwarf_strict)
+       {
+         if (strcmp (language_string, "GNU C89") != 0)
+           language = DW_LANG_C99;
+
+         if (dwarf_version >= 5 /* || !dwarf_strict */)
+           if (strcmp (language_string, "GNU C11") == 0)
+             language = DW_LANG_C11;
+       }
+    }
+  else if (strncmp (language_string, "GNU C++", 7) == 0)
+    {
+      language = DW_LANG_C_plus_plus;
+      if (dwarf_version >= 5 /* || !dwarf_strict */)
+       {
+         if (strcmp (language_string, "GNU C++11") == 0)
+           language = DW_LANG_C_plus_plus_11;
+         else if (strcmp (language_string, "GNU C++14") == 0)
+           language = DW_LANG_C_plus_plus_14;
+       }
+    }
   else if (strcmp (language_string, "GNU F77") == 0)
     language = DW_LANG_Fortran77;
   else if (strcmp (language_string, "GNU Pascal") == 0)
@@ -19256,8 +20199,17 @@ gen_compile_unit_die (const char *filename)
     {
       if (strcmp (language_string, "GNU Ada") == 0)
        language = DW_LANG_Ada95;
-      else if (strcmp (language_string, "GNU Fortran") == 0)
-       language = DW_LANG_Fortran95;
+      else if (strncmp (language_string, "GNU Fortran", 11) == 0)
+       {
+         language = DW_LANG_Fortran95;
+         if (dwarf_version >= 5 /* || !dwarf_strict */)
+           {
+             if (strcmp (language_string, "GNU Fortran2003") == 0)
+               language = DW_LANG_Fortran03;
+             else if (strcmp (language_string, "GNU Fortran2008") == 0)
+               language = DW_LANG_Fortran08;
+           }
+       }
       else if (strcmp (language_string, "GNU Java") == 0)
        language = DW_LANG_Java;
       else if (strcmp (language_string, "GNU Objective-C") == 0)
@@ -19271,7 +20223,7 @@ gen_compile_unit_die (const char *filename)
        }
     }
   /* Use a degraded Fortran setting in strict DWARF2 so is_fortran works.  */
-  else if (strcmp (language_string, "GNU Fortran") == 0)
+  else if (strncmp (language_string, "GNU Fortran", 11) == 0)
     language = DW_LANG_Fortran90;
 
   add_AT_unsigned (die, DW_AT_language, language);
@@ -19281,6 +20233,8 @@ gen_compile_unit_die (const char *filename)
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
+    case DW_LANG_Fortran03:
+    case DW_LANG_Fortran08:
       /* Fortran has case insensitive identifiers and the front-end
         lowercases everything.  */
       add_AT_unsigned (die, DW_AT_identifier_case, DW_ID_down_case);
@@ -19299,7 +20253,7 @@ gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die)
 {
   dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
 
-  add_type_attribute (die, BINFO_TYPE (binfo), 0, 0, context_die);
+  add_type_attribute (die, BINFO_TYPE (binfo), TYPE_UNQUALIFIED, context_die);
   add_data_member_location_attribute (die, binfo);
 
   if (BINFO_VIRTUAL_P (binfo))
@@ -19370,19 +20324,26 @@ gen_member_die (tree type, dw_die_ref context_die)
        gen_decl_die (member, NULL, context_die);
     }
 
+  /* We do not keep type methods in type variants.  */
+  gcc_assert (TYPE_MAIN_VARIANT (type) == type);
   /* Now output info about the function members (if any).  */
-  for (member = TYPE_METHODS (type); member; member = DECL_CHAIN (member))
-    {
-      /* Don't include clones in the member list.  */
-      if (DECL_ABSTRACT_ORIGIN (member))
-       continue;
+  if (TYPE_METHODS (type) != error_mark_node)
+    for (member = TYPE_METHODS (type); member; member = DECL_CHAIN (member))
+      {
+       /* Don't include clones in the member list.  */
+       if (DECL_ABSTRACT_ORIGIN (member))
+         continue;
+       /* Nor constructors for anonymous classes.  */
+       if (DECL_ARTIFICIAL (member)
+           && dwarf2_name (member, 0) == NULL)
+         continue;
 
-      child = lookup_decl_die (member);
-      if (child)
-       splice_child_die (context_die, child);
-      else
-       gen_decl_die (member, NULL, context_die);
-    }
+       child = lookup_decl_die (member);
+       if (child)
+         splice_child_die (context_die, child);
+       else
+         gen_decl_die (member, NULL, context_die);
+      }
 }
 
 /* Generate a DIE for a structure or union type.  If TYPE_DECL_SUPPRESS_DEBUG
@@ -19393,6 +20354,18 @@ static void
 gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
                                enum debug_info_usage usage)
 {
+  /* Fill in the bound of variable-length fields in late dwarf if
+     still incomplete.  */
+  if (TREE_ASM_WRITTEN (type)
+      && variably_modified_type_p (type, NULL)
+      && !early_dwarf)
+    {
+      tree member;
+      for (member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
+       fill_variable_array_bounds (TREE_TYPE (member));
+      return;
+    }
+
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref scope_die = 0;
   int nested = 0;
@@ -19496,7 +20469,7 @@ gen_subroutine_type_die (tree type, dw_die_ref context_die)
 
   equate_type_number_to_die (type, subr_die);
   add_prototyped_attribute (subr_die, type);
-  add_type_attribute (subr_die, return_type, 0, 0, context_die);
+  add_type_attribute (subr_die, return_type, TYPE_UNQUALIFIED, context_die);
   gen_formal_types_die (type, subr_die);
 
   if (get_AT (subr_die, DW_AT_name))
@@ -19512,7 +20485,11 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
   tree origin;
 
   if (TREE_ASM_WRITTEN (decl))
-    return;
+    {
+      if (DECL_ORIGINAL_TYPE (decl))
+       fill_variable_array_bounds (DECL_ORIGINAL_TYPE (decl));
+      return;
+    }
 
   TREE_ASM_WRITTEN (decl) = 1;
   type_die = new_die (DW_TAG_typedef, context_die, decl);
@@ -19528,6 +20505,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = DECL_ORIGINAL_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          gcc_assert (type != TREE_TYPE (decl));
          equate_type_number_to_die (TREE_TYPE (decl), type_die);
        }
@@ -19535,6 +20515,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
        {
          type = TREE_TYPE (decl);
 
+         if (type == error_mark_node)
+           return;
+
          if (is_naming_typedef_decl (TYPE_NAME (type)))
            {
              /* Here, we are in the case of decl being a typedef naming
@@ -19564,8 +20547,7 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
            }
        }
 
-      add_type_attribute (type_die, type, TREE_READONLY (decl),
-                         TREE_THIS_VOLATILE (decl), context_die);
+      add_type_attribute (type_die, type, decl_quals (decl), context_die);
 
       if (is_naming_typedef_decl (decl))
        /* We want that all subsequent calls to lookup_type_die with
@@ -19576,7 +20558,7 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
       add_accessibility_attribute (type_die, decl);
     }
 
-  if (DECL_ABSTRACT (decl))
+  if (DECL_ABSTRACT_P (decl))
     equate_decl_number_to_die (decl, type_die);
 
   if (get_AT (type_die, DW_AT_name))
@@ -19596,13 +20578,15 @@ gen_tagged_type_die (tree type,
       || !is_tagged_type (type))
     return;
 
+  if (TREE_ASM_WRITTEN (type))
+    need_pop = 0;
   /* If this is a nested type whose containing class hasn't been written
      out yet, writing it out will cover this one, too.  This does not apply
      to instantiations of member class templates; they need to be added to
      the containing class as they are generated.  FIXME: This hurts the
      idea of combining type decls from multiple TUs, since we can't predict
      what set of template instantiations we'll get.  */
-  if (TYPE_CONTEXT (type)
+  else if (TYPE_CONTEXT (type)
       && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
       && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
     {
@@ -19664,6 +20648,11 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (type == NULL_TREE || type == error_mark_node)
     return;
 
+#ifdef ENABLE_CHECKING
+  if (type)
+     verify_type (type);
+#endif
+
   if (TYPE_NAME (type) != NULL_TREE
       && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
       && is_redundant_typedef (TYPE_NAME (type))
@@ -19707,17 +20696,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       return;
     }
 
-  /* If this is an array type with hidden descriptor, handle it first.  */
-  if (!TREE_ASM_WRITTEN (type)
-      && lang_hooks.types.get_array_descr_info
-      && lang_hooks.types.get_array_descr_info (type, &info)
-      && (dwarf_version >= 3 || !dwarf_strict))
-    {
-      gen_descr_array_type_die (type, &info, context_die);
-      TREE_ASM_WRITTEN (type) = 1;
-      return;
-    }
-
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
@@ -19726,8 +20704,32 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (TREE_CODE (type) != VECTOR_TYPE)
     type = type_main_variant (type);
 
+  /* If this is an array type with hidden descriptor, handle it first.  */
+  if (!TREE_ASM_WRITTEN (type)
+      && lang_hooks.types.get_array_descr_info)
+    {
+      memset (&info, 0, sizeof (info));
+      if (lang_hooks.types.get_array_descr_info (type, &info))
+       {
+         gen_descr_array_type_die (type, &info, context_die);
+         TREE_ASM_WRITTEN (type) = 1;
+         return;
+       }
+    }
+
   if (TREE_ASM_WRITTEN (type))
-    return;
+    {
+      /* Variable-length types may be incomplete even if
+        TREE_ASM_WRITTEN.  For such types, fall through to
+        gen_array_type_die() and possibly fill in
+        DW_AT_{upper,lower}_bound attributes.  */
+      if ((TREE_CODE (type) != ARRAY_TYPE
+          && TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE
+          && TREE_CODE (type) != QUAL_UNION_TYPE)
+         || !variably_modified_type_p (type, NULL))
+       return;
+    }
 
   switch (TREE_CODE (type))
     {
@@ -19779,9 +20781,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     case ARRAY_TYPE:
-      gen_array_type_die (type, context_die);
-      break;
-
     case VECTOR_TYPE:
       gen_array_type_die (type, context_die);
       break;
@@ -19799,6 +20798,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     case FIXED_POINT_TYPE:
     case COMPLEX_TYPE:
     case BOOLEAN_TYPE:
+    case POINTER_BOUNDS_TYPE:
       /* No DIEs needed for fundamental types.  */
       break;
 
@@ -19809,10 +20809,9 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
         dw_die_ref type_die = lookup_type_die (type);
         if (type_die == NULL)
           {
-           tree name = TYPE_NAME (type);
-           if (TREE_CODE (name) == TYPE_DECL)
-             name = DECL_NAME (name);
-            type_die = new_die (DW_TAG_unspecified_type, comp_unit_die (), type);
+           tree name = TYPE_IDENTIFIER (type);
+            type_die = new_die (DW_TAG_unspecified_type, comp_unit_die (),
+                               type);
             add_name_attribute (type_die, IDENTIFIER_POINTER (name));
             equate_type_number_to_die (type, type_die);
           }
@@ -19820,6 +20819,20 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       break;
 
     default:
+      if (is_cxx_auto (type))
+       {
+         tree name = TYPE_IDENTIFIER (type);
+         dw_die_ref *die = (name == get_identifier ("auto")
+                            ? &auto_die : &decltype_auto_die);
+         if (!*die)
+           {
+             *die = new_die (DW_TAG_unspecified_type,
+                             comp_unit_die (), NULL_TREE);
+             add_name_attribute (*die, IDENTIFIER_POINTER (name));
+           }
+         equate_type_number_to_die (type, *die);
+         break;
+       }
       gcc_unreachable ();
     }
 
@@ -19836,7 +20849,7 @@ gen_type_die (tree type, dw_die_ref context_die)
    things which are local to the given block.  */
 
 static void
-gen_block_die (tree stmt, dw_die_ref context_die, int depth)
+gen_block_die (tree stmt, dw_die_ref context_die)
 {
   int must_output_die = 0;
   bool inlined_func;
@@ -19855,7 +20868,7 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
       tree sub;
 
       for (sub = BLOCK_SUBBLOCKS (stmt); sub; sub = BLOCK_CHAIN (sub))
-       gen_block_die (sub, context_die, depth + 1);
+       gen_block_die (sub, context_die);
 
       return;
     }
@@ -19910,13 +20923,13 @@ gen_block_die (tree stmt, dw_die_ref context_die, int depth)
             the concrete instance of STMT got inlined, the later will lead
             to the generation of a DW_TAG_inlined_subroutine DIE.  */
          if (! BLOCK_ABSTRACT (stmt))
-           gen_inlined_subroutine_die (stmt, context_die, depth);
+           gen_inlined_subroutine_die (stmt, context_die);
        }
       else
-       gen_lexical_block_die (stmt, context_die, depth);
+       gen_lexical_block_die (stmt, context_die);
     }
   else
-    decls_for_scope (stmt, context_die, depth);
+    decls_for_scope (stmt, context_die);
 }
 
 /* Process variable DECL (or variable with origin ORIGIN) within
@@ -19938,8 +20951,11 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
   if (die != NULL && die->die_parent == NULL)
     add_child_die (context_die, die);
   else if (TREE_CODE (decl_or_origin) == IMPORTED_DECL)
-    dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
-                                        stmt, context_die);
+    {
+      if (early_dwarf)
+       dwarf2out_imported_module_or_decl_1 (decl_or_origin, DECL_NAME (decl_or_origin),
+                                            stmt, context_die);
+    }
   else
     gen_decl_die (decl, origin, context_die);
 }
@@ -19948,7 +20964,7 @@ process_scope_var (tree stmt, tree decl, tree origin, dw_die_ref context_die)
    all of its sub-blocks.  */
 
 static void
-decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
+decls_for_scope (tree stmt, dw_die_ref context_die)
 {
   tree decl;
   unsigned int i;
@@ -19980,7 +20996,7 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
   for (subblocks = BLOCK_SUBBLOCKS (stmt);
        subblocks != NULL;
        subblocks = BLOCK_CHAIN (subblocks))
-    gen_block_die (subblocks, context_die, depth + 1);
+    gen_block_die (subblocks, context_die);
 }
 
 /* Is this a typedef we can avoid emitting?  */
@@ -20032,6 +21048,28 @@ is_naming_typedef_decl (const_tree decl)
              != TYPE_NAME (TREE_TYPE (decl))));
 }
 
+/* Looks up the DIE for a context.  */
+
+static inline dw_die_ref
+lookup_context_die (tree context)
+{
+  if (context)
+    {
+      /* Find die that represents this context.  */
+      if (TYPE_P (context))
+       {
+         context = TYPE_MAIN_VARIANT (context);
+         dw_die_ref ctx = lookup_type_die (context);
+         if (!ctx)
+           return NULL;
+         return strip_naming_typedef (context, ctx);
+       }
+      else
+       return lookup_decl_die (context);
+    }
+  return comp_unit_die ();
+}
+
 /* Returns the DIE for a context.  */
 
 static inline dw_die_ref
@@ -20127,8 +21165,8 @@ force_type_die (tree type)
     {
       dw_die_ref context_die = get_context_die (TYPE_CONTEXT (type));
 
-      type_die = modified_type_die (type, TYPE_READONLY (type),
-                                   TYPE_VOLATILE (type), context_die);
+      type_die = modified_type_die (type, TYPE_QUALS_NO_ADDR_SPACE (type),
+                                   context_die);
       gcc_assert (type_die);
     }
   return type_die;
@@ -20153,7 +21191,9 @@ setup_namespace_context (tree thing, dw_die_ref context_die)
    type) within its namespace, if appropriate.
 
    For compatibility with older debuggers, namespace DIEs only contain
-   declarations; all definitions are emitted at CU scope.  */
+   declarations; all definitions are emitted at CU scope, with
+   DW_AT_specification pointing to the declaration (like with class
+   members).  */
 
 static dw_die_ref
 declare_in_namespace (tree thing, dw_die_ref context_die)
@@ -20163,6 +21203,26 @@ declare_in_namespace (tree thing, dw_die_ref context_die)
   if (debug_info_level <= DINFO_LEVEL_TERSE)
     return context_die;
 
+  /* External declarations in the local scope only need to be emitted
+     once, not once in the namespace and once in the scope.
+
+     This avoids declaring the `extern' below in the
+     namespace DIE as well as in the innermost scope:
+
+          namespace S
+         {
+            int i=5;
+            int foo()
+           {
+              int i=8;
+              extern int i;
+             return i;
+           }
+          }
+  */
+  if (DECL_P (thing) && DECL_EXTERNAL (thing) && local_scope_p (context_die))
+    return context_die;
+
   /* If this decl is from an inlined function, then don't try to emit it in its
      namespace, as we will get confused.  It would have already been emitted
      when the abstract instance of the inline function was emitted anyways.  */
@@ -20247,6 +21307,12 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   if (DECL_P (decl_or_origin) && DECL_IGNORED_P (decl_or_origin))
     return NULL;
 
+  /* Ignore pointer bounds decls.  */
+  if (DECL_P (decl_or_origin)
+      && TREE_TYPE (decl_or_origin)
+      && POINTER_BOUNDS_P (decl_or_origin))
+    return NULL;
+
   switch (TREE_CODE (decl_or_origin))
     {
     case ERROR_MARK:
@@ -20295,7 +21361,7 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
       /* If we're emitting an out-of-line copy of an inline function,
         emit info for the abstract instance and set up to refer to it.  */
       else if (cgraph_function_possibly_inlined_p (decl)
-              && ! DECL_ABSTRACT (decl)
+              && ! DECL_ABSTRACT_P (decl)
               && ! class_or_namespace_scope_p (context_die)
               /* dwarf2out_abstract_function won't emit a die if this is just
                  a declaration.  We must avoid setting DECL_ABSTRACT_ORIGIN in
@@ -20444,17 +21510,67 @@ gen_decl_die (tree decl, tree origin, dw_die_ref context_die)
   return NULL;
 }
 \f
-/* Output debug information for global decl DECL.  Called from toplev.c after
-   compilation proper has finished.  */
+/* Output initial debug information for global DECL.  Called at the
+   end of the parsing process.
+
+   This is the initial debug generation process.  As such, the DIEs
+   generated may be incomplete.  A later debug generation pass
+   (dwarf2out_late_global_decl) will augment the information generated
+   in this pass (e.g., with complete location info).  */
+
+static void
+dwarf2out_early_global_decl (tree decl)
+{
+  set_early_dwarf s;
+
+  /* gen_decl_die() will set DECL_ABSTRACT because
+     cgraph_function_possibly_inlined_p() returns true.  This is in
+     turn will cause DW_AT_inline attributes to be set.
+
+     This happens because at early dwarf generation, there is no
+     cgraph information, causing cgraph_function_possibly_inlined_p()
+     to return true.  Trick cgraph_function_possibly_inlined_p()
+     while we generate dwarf early.  */
+  bool save = symtab->global_info_ready;
+  symtab->global_info_ready = true;
+
+  /* We don't handle TYPE_DECLs.  If required, they'll be reached via
+     other DECLs and they can point to template types or other things
+     that dwarf2out can't handle when done via dwarf2out_decl.  */
+  if (TREE_CODE (decl) != TYPE_DECL
+      && TREE_CODE (decl) != PARM_DECL)
+    {
+      tree save_fndecl = current_function_decl;
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         /* No cfun means the symbol has no body, so there's nothing
+            to emit.  */
+         if (!DECL_STRUCT_FUNCTION (decl))
+           goto early_decl_exit;
+
+         current_function_decl = decl;
+       }
+      dwarf2out_decl (decl);
+      if (TREE_CODE (decl) == FUNCTION_DECL)
+       current_function_decl = save_fndecl;
+    }
+ early_decl_exit:
+  symtab->global_info_ready = save;
+}
+
+/* Output debug information for global decl DECL.  Called from
+   toplev.c after compilation proper has finished.  */
 
 static void
-dwarf2out_global_decl (tree decl)
+dwarf2out_late_global_decl (tree decl)
 {
-  /* Output DWARF2 information for file-scope tentative data object
-     declarations, file-scope (extern) function declarations (which
-     had no corresponding body) and file-scope tagged type declarations
-     and definitions which have not yet been forced out.  */
-  if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+  /* Output any global decls we missed or fill-in any location
+     information we were unable to determine on the first pass.
+
+     Skip over functions because they were handled by the
+     debug_hooks->function_decl() call in rest_of_handle_final.  */
+  if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl))
+      && !POINTER_BOUNDS_P (decl))
     dwarf2out_decl (decl);
 }
 
@@ -20464,7 +21580,10 @@ static void
 dwarf2out_type_decl (tree decl, int local)
 {
   if (!local)
-    dwarf2out_decl (decl);
+    {
+      set_early_dwarf s;
+      dwarf2out_decl (decl);
+    }
 }
 
 /* Output debug information for imported module or decl DECL.
@@ -20572,6 +21691,8 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   gcc_assert (decl);
 
+  set_early_dwarf s;
+
   /* To emit DW_TAG_imported_module or DW_TAG_imported_decl, we need two DIEs.
      We need decl DIE for reference and scope die. First, get DIE for the decl
      itself.  */
@@ -20598,7 +21719,6 @@ dwarf2out_imported_module_or_decl (tree decl, tree name, tree context,
 
   /* OK, now we have DIEs for decl as well as scope. Emit imported die.  */
   dwarf2out_imported_module_or_decl_1 (decl, name, context, scope_die);
-
 }
 
 /* Output debug information for namelists.   */
@@ -20638,9 +21758,9 @@ gen_namelist_decl (tree name, dw_die_ref scope_die, tree item_decls)
 }
 
 
-/* Write the debugging output for DECL.  */
+/* Write the debugging output for DECL and return the DIE.  */
 
-void
+static void
 dwarf2out_decl (tree decl)
 {
   dw_die_ref context_die = comp_unit_die ();
@@ -20684,7 +21804,7 @@ dwarf2out_decl (tree decl)
         where the inlined function is output in a different LTRANS unit
         or not at all.  */
       if (DECL_INITIAL (decl) == NULL_TREE
-         && ! DECL_ABSTRACT (decl))
+         && ! DECL_ABSTRACT_P (decl))
        return;
 
       /* If we're a nested function, initially use a parent of NULL; if we're
@@ -20697,21 +21817,8 @@ dwarf2out_decl (tree decl)
       break;
 
     case VAR_DECL:
-      /* Ignore this VAR_DECL if it refers to a file-scope extern data object
-        declaration and if the declaration was never even referenced from
-        within this entire compilation unit.  We suppress these DIEs in
-        order to save space in the .debug section (by eliminating entries
-        which are probably useless).  Note that we must not suppress
-        block-local extern declarations (whether used or not) because that
-        would screw-up the debugger's name lookup mechanism and cause it to
-        miss things which really ought to be in scope at a given point.  */
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
-       return;
-
       /* For local statics lookup proper context die.  */
-      if (TREE_STATIC (decl)
-         && DECL_CONTEXT (decl)
-         && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+      if (local_function_static (decl))
        context_die = lookup_decl_die (DECL_CONTEXT (decl));
 
       /* If we are in terse mode, don't generate any DIEs to represent any
@@ -20766,6 +21873,10 @@ dwarf2out_decl (tree decl)
     }
 
   gen_decl_die (decl, NULL, context_die);
+
+  dw_die_ref die = lookup_decl_die (decl);
+  if (die)
+    check_die (die);
 }
 
 /* Write the debugging output for DECL.  */
@@ -20778,9 +21889,8 @@ dwarf2out_function_decl (tree decl)
   call_arg_loc_last = NULL;
   call_site_count = -1;
   tail_call_site_count = -1;
-  block_map.release ();
-  htab_empty (decl_loc_table);
-  htab_empty (cached_dw_loc_list_table);
+  decl_loc_table->empty ();
+  cached_dw_loc_list_table->empty ();
 }
 
 /* Output a marker (i.e. a label) for the beginning of the generated code for
@@ -20834,19 +21944,15 @@ dwarf2out_ignore_block (const_tree block)
 
 /* Hash table routines for file_hash.  */
 
-static int
-file_table_eq (const void *p1_p, const void *p2_p)
+bool
+dwarf_file_hasher::equal (dwarf_file_data *p1, const char *p2)
 {
-  const struct dwarf_file_data *const p1 =
-    (const struct dwarf_file_data *) p1_p;
-  const char *const p2 = (const char *) p2_p;
   return filename_cmp (p1->filename, p2) == 0;
 }
 
-static hashval_t
-file_table_hash (const void *p_p)
+hashval_t
+dwarf_file_hasher::hash (dwarf_file_data *p)
 {
-  const struct dwarf_file_data *const p = (const struct dwarf_file_data *) p_p;
   return htab_hash_string (p->filename);
 }
 
@@ -20857,30 +21963,23 @@ file_table_hash (const void *p_p)
    section) and references to those files numbers (in the .debug_srcinfo
    and.debug_macinfo sections).  If the filename given as an argument is not
    found in our current list, add it to the list and assign it the next
-   available unique index number.  In order to speed up searches, we remember
-   the index of the filename was looked up last.  This handles the majority of
-   all searches.  */
+   available unique index number.  */
 
 static struct dwarf_file_data *
 lookup_filename (const char *file_name)
 {
-  void ** slot;
   struct dwarf_file_data * created;
 
-  /* Check to see if the file name that was searched on the previous
-     call matches this file name.  If so, return the index.  */
-  if (file_table_last_lookup
-      && (file_name == file_table_last_lookup->filename
-         || filename_cmp (file_table_last_lookup->filename, file_name) == 0))
-    return file_table_last_lookup;
+  if (!file_name)
+    return NULL;
 
-  /* Didn't match the previous lookup, search the table.  */
-  slot = htab_find_slot_with_hash (file_table, file_name,
-                                  htab_hash_string (file_name), INSERT);
+  dwarf_file_data **slot
+    = file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
+                                      INSERT);
   if (*slot)
-    return (struct dwarf_file_data *) *slot;
+    return *slot;
 
-  created = ggc_alloc_dwarf_file_data ();
+  created = ggc_alloc<dwarf_file_data> ();
   created->filename = file_name;
   created->emitted_number = 0;
   *slot = created;
@@ -21044,15 +22143,15 @@ static unsigned int first_loclabel_num_not_at_text_label;
    our lookup table.  */
 
 static void
-dwarf2out_var_location (rtx loc_note)
+dwarf2out_var_location (rtx_insn *loc_note)
 {
   char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
-  rtx next_real, next_note;
+  rtx_insn *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;
+  static rtx_insn *expected_next_loc_note;
   tree decl;
   bool var_loc_p;
 
@@ -21079,16 +22178,16 @@ dwarf2out_var_location (rtx loc_note)
   if (next_real)
     {
       if (expected_next_loc_note != loc_note)
-       next_real = NULL_RTX;
+       next_real = NULL;
     }
 
   next_note = NEXT_INSN (loc_note);
   if (! next_note
-      || INSN_DELETED_P (next_note)
+      || next_note->deleted ()
       || ! NOTE_P (next_note)
       || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION
          && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION))
-    next_note = NULL_RTX;
+    next_note = NULL;
 
   if (! next_real)
     next_real = next_real_insn (loc_note);
@@ -21099,7 +22198,7 @@ dwarf2out_var_location (rtx loc_note)
       cached_next_real_insn = next_real;
     }
   else
-    cached_next_real_insn = NULL_RTX;
+    cached_next_real_insn = NULL;
 
   /* If there are no instructions which would be affected by this note,
      don't do anything.  */
@@ -21152,8 +22251,8 @@ dwarf2out_var_location (rtx loc_note)
          && in_first_function_p
          && maybe_at_text_label_p)
        {
-         static rtx last_start;
-         rtx insn;
+         static rtx_insn *last_start;
+         rtx_insn *insn;
          for (insn = loc_note; insn; insn = previous_insn (insn))
            if (insn == last_start)
              break;
@@ -21190,8 +22289,9 @@ dwarf2out_var_location (rtx loc_note)
   if (!var_loc_p)
     {
       struct call_arg_loc_node *ca_loc
-       = ggc_alloc_cleared_call_arg_loc_node ();
-      rtx prev = prev_real_insn (loc_note), x;
+       = ggc_cleared_alloc<call_arg_loc_node> ();
+      rtx_insn *prev = prev_real_insn (loc_note);
+      rtx x;
       ca_loc->call_arg_loc_note = loc_note;
       ca_loc->next = NULL;
       ca_loc->label = last_label;
@@ -21201,7 +22301,7 @@ dwarf2out_var_location (rtx loc_note)
                          && GET_CODE (PATTERN (prev)) == SEQUENCE
                          && CALL_P (XVECEXP (PATTERN (prev), 0, 0)))));
       if (!CALL_P (prev))
-       prev = XVECEXP (PATTERN (prev), 0, 0);
+       prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
       ca_loc->tail_call_p = SIBLING_CALL_P (prev);
       x = get_call_rtx_from (PATTERN (prev));
       if (x)
@@ -21237,10 +22337,10 @@ dwarf2out_var_location (rtx loc_note)
 
 /* Note in one location list that text section has changed.  */
 
-static int
-var_location_switch_text_section_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+int
+var_location_switch_text_section_1 (var_loc_list **slot, void *)
 {
-  var_loc_list *list = (var_loc_list *) *slot;
+  var_loc_list *list = *slot;
   if (list->first)
     list->last_before_switch
       = list->last->next ? list->last->next : list->last;
@@ -21255,7 +22355,7 @@ var_location_switch_text_section (void)
   if (decl_loc_table == NULL)
     return;
 
-  htab_traverse (decl_loc_table, var_location_switch_text_section_1, NULL);
+  decl_loc_table->traverse<void *, var_location_switch_text_section_1> (NULL);
 }
 
 /* Create a new line number table.  */
@@ -21265,7 +22365,7 @@ new_line_info_table (void)
 {
   dw_line_info_table *table;
 
-  table = ggc_alloc_cleared_dw_line_info_table_struct ();
+  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
   table->file_num = 1;
   table->line_num = 1;
   table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
@@ -21364,13 +22464,12 @@ dwarf2out_begin_function (tree fun)
    Set have_multiple_function_sections to true in that case and
    terminate htab traversal.  */
 
-static int
-find_empty_loc_ranges_at_text_label (void **slot, void *)
+int
+find_empty_loc_ranges_at_text_label (var_loc_list **slot, int)
 {
-  var_loc_list *entry;
+  var_loc_list *entry = *slot;
   struct var_loc_node *node;
 
-  entry = (var_loc_list *) *slot;
   node = entry->first;
   if (node && node->next && node->next->label)
     {
@@ -21401,8 +22500,7 @@ dwarf2out_end_function (unsigned int)
       && !have_multiple_function_sections
       && first_loclabel_num_not_at_text_label
       && decl_loc_table)
-    htab_traverse (decl_loc_table, find_empty_loc_ranges_at_text_label,
-                  NULL);
+    decl_loc_table->traverse<int, find_empty_loc_ranges_at_text_label> (0);
   in_first_function_p = false;
   maybe_at_text_label_p = false;
 }
@@ -21617,26 +22715,26 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
 
 struct macinfo_entry_hasher : typed_noop_remove <macinfo_entry>
 {
-  typedef macinfo_entry value_type;
-  typedef macinfo_entry compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef macinfo_entry *value_type;
+  typedef macinfo_entry *compare_type;
+  static inline hashval_t hash (const macinfo_entry *);
+  static inline bool equal (const macinfo_entry *, const macinfo_entry *);
 };
 
 inline hashval_t
-macinfo_entry_hasher::hash (const value_type *entry)
+macinfo_entry_hasher::hash (const macinfo_entry *entry)
 {
   return htab_hash_string (entry->info);
 }
 
 inline bool
-macinfo_entry_hasher::equal (const value_type *entry1,
-                            const compare_type *entry2)
+macinfo_entry_hasher::equal (const macinfo_entry *entry1,
+                            const macinfo_entry *entry2)
 {
   return !strcmp (entry1->info, entry2->info);
 }
 
-typedef hash_table <macinfo_entry_hasher> macinfo_hash_type;
+typedef hash_table<macinfo_entry_hasher> macinfo_hash_type;
 
 /* Output a single .debug_macinfo entry.  */
 
@@ -21726,7 +22824,7 @@ output_macinfo_op (macinfo_entry *ref)
 
 static unsigned
 optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
-                       macinfo_hash_type *macinfo_htab)
+                       macinfo_hash_type **macinfo_htab)
 {
   macinfo_entry *first, *second, *cur, *inc;
   char linebuf[sizeof (HOST_WIDE_INT) * 3 + 1];
@@ -21813,10 +22911,10 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
   inc->code = DW_MACRO_GNU_transparent_include;
   inc->lineno = 0;
   inc->info = ggc_strdup (grp_name);
-  if (!macinfo_htab->is_created ())
-    macinfo_htab->create (10);
+  if (!*macinfo_htab)
+    *macinfo_htab = new macinfo_hash_type (10);
   /* Avoid emitting duplicates.  */
-  slot = macinfo_htab->find_slot (inc, INSERT);
+  slot = (*macinfo_htab)->find_slot (inc, INSERT);
   if (*slot != NULL)
     {
       inc->code = 0;
@@ -21836,7 +22934,7 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
   else
     {
       *slot = inc;
-      inc->lineno = macinfo_htab->elements ();
+      inc->lineno = (*macinfo_htab)->elements ();
       output_macinfo_op (inc);
     }
   return count;
@@ -21887,7 +22985,7 @@ output_macinfo (void)
   unsigned long length = vec_safe_length (macinfo_table);
   macinfo_entry *ref;
   vec<macinfo_entry, va_gc> *files = NULL;
-  macinfo_hash_type macinfo_htab;
+  macinfo_hash_type *macinfo_htab = NULL;
 
   if (! length)
     return;
@@ -21960,10 +23058,11 @@ output_macinfo (void)
       ref->code = 0;
     }
 
-  if (!macinfo_htab.is_created ())
+  if (!macinfo_htab)
     return;
 
-  macinfo_htab.dispose ();
+  delete macinfo_htab;
+  macinfo_htab = NULL;
 
   /* If any DW_MACRO_GNU_transparent_include were used, on those
      DW_MACRO_GNU_transparent_include entries terminate the
@@ -22013,28 +23112,31 @@ output_macinfo (void)
 static void
 dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
 {
+  /* This option is currently broken, see (PR53118 and PR46102).  */
+  if (flag_eliminate_dwarf2_dups
+      && strstr (lang_hooks.name, "C++"))
+    {
+      warning (0, "-feliminate-dwarf2-dups is broken for C++, ignoring");
+      flag_eliminate_dwarf2_dups = 0;
+    }
+
   /* Allocate the file_table.  */
-  file_table = htab_create_ggc (50, file_table_hash,
-                               file_table_eq, NULL);
+  file_table = hash_table<dwarf_file_hasher>::create_ggc (50);
 
   /* Allocate the decl_die_table.  */
-  decl_die_table = htab_create_ggc (10, decl_die_table_hash,
-                                   decl_die_table_eq, NULL);
+  decl_die_table = hash_table<decl_die_hasher>::create_ggc (10);
 
   /* Allocate the decl_loc_table.  */
-  decl_loc_table = htab_create_ggc (10, decl_loc_table_hash,
-                                   decl_loc_table_eq, NULL);
+  decl_loc_table = hash_table<decl_loc_hasher>::create_ggc (10);
 
   /* Allocate the cached_dw_loc_list_table.  */
-  cached_dw_loc_list_table
-    = htab_create_ggc (10, cached_dw_loc_list_table_hash,
-                      cached_dw_loc_list_table_eq, NULL);
+  cached_dw_loc_list_table = hash_table<dw_loc_list_hasher>::create_ggc (10);
 
   /* Allocate the initial hunk of the decl_scope_table.  */
   vec_alloc (decl_scope_table, 256);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
-  abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
+  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
     (ABBREV_DIE_TABLE_INCREMENT);
   abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
   /* Zero-th entry is allocated, but unused.  */
@@ -22161,11 +23263,10 @@ dwarf2out_assembly_start (void)
    because the indexing code relies on htab_traverse to traverse nodes
    in the same order for each run. */
 
-static int
-index_string (void **h, void *v)
+int
+index_string (indirect_string_node **h, unsigned int *index)
 {
-  struct indirect_string_node *node = (struct indirect_string_node *) *h;
-  unsigned int *index = (unsigned int *) v;
+  indirect_string_node *node = *h;
 
   find_string_form (node);
   if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
@@ -22181,11 +23282,10 @@ index_string (void **h, void *v)
    htab_traverse.  Output the offset to a string and update the
    current offset.  */
 
-static int
-output_index_string_offset (void **h, void *v)
+int
+output_index_string_offset (indirect_string_node **h, unsigned int *offset)
 {
-  struct indirect_string_node *node = (struct indirect_string_node *) *h;
-  unsigned int *offset = (unsigned int *) v;
+  indirect_string_node *node = *h;
 
   if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
     {
@@ -22202,11 +23302,10 @@ output_index_string_offset (void **h, void *v)
 /* A helper function for dwarf2out_finish called through
    htab_traverse.  Output the indexed string.  */
 
-static int
-output_index_string (void **h, void *v)
+int
+output_index_string (indirect_string_node **h, unsigned int *cur_idx)
 {
-  struct indirect_string_node *node = (struct indirect_string_node *) *h;
-  unsigned int *cur_idx = (unsigned int *) v;
+  struct indirect_string_node *node = *h;
 
   if (node->form == DW_FORM_GNU_str_index && node->refcount > 0)
     {
@@ -22222,10 +23321,10 @@ output_index_string (void **h, void *v)
 /* A helper function for dwarf2out_finish called through
    htab_traverse.  Emit one queued .debug_str string.  */
 
-static int
-output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED)
+int
+output_indirect_string (indirect_string_node **h, void *)
 {
-  struct indirect_string_node *node = (struct indirect_string_node *) *h;
+  struct indirect_string_node *node = *h;
 
   node->form = find_string_form (node);
   if (node->form == DW_FORM_strp && node->refcount > 0)
@@ -22244,33 +23343,30 @@ output_indirect_strings (void)
 {
   switch_to_section (debug_str_section);
   if (!dwarf_split_debug_info)
-    htab_traverse (debug_str_hash, output_indirect_string, NULL);
+    debug_str_hash->traverse<void *, output_indirect_string> (NULL);
   else
     {
       unsigned int offset = 0;
       unsigned int cur_idx = 0;
 
-      htab_traverse (skeleton_debug_str_hash, output_indirect_string, NULL);
+      skeleton_debug_str_hash->traverse<void *, output_indirect_string> (NULL);
 
       switch_to_section (debug_str_offsets_section);
-      htab_traverse_noresize (debug_str_hash,
-                              output_index_string_offset,
-                              &offset);
+      debug_str_hash->traverse_noresize
+       <unsigned int *, output_index_string_offset> (&offset);
       switch_to_section (debug_str_dwo_section);
-      htab_traverse_noresize (debug_str_hash,
-                              output_index_string,
-                              &cur_idx);
+      debug_str_hash->traverse_noresize<unsigned int *, output_index_string>
+       (&cur_idx);
     }
 }
 
 /* Callback for htab_traverse to assign an index to an entry in the
    table, and to write that entry to the .debug_addr section.  */
 
-static int
-output_addr_table_entry (void **slot, void *data)
+int
+output_addr_table_entry (addr_table_entry **slot, unsigned int *cur_index)
 {
-  addr_table_entry *entry = (addr_table_entry *) *slot;
-  unsigned int *cur_index = (unsigned int *)data;
+  addr_table_entry *entry = *slot;
 
   if (entry->refcount == 0)
     {
@@ -22311,11 +23407,12 @@ static void
 output_addr_table (void)
 {
   unsigned int index = 0;
-  if (addr_index_table == NULL || htab_size (addr_index_table) == 0)
+  if (addr_index_table == NULL || addr_index_table->size () == 0)
     return;
 
   switch_to_section (debug_addr_section);
-  htab_traverse_noresize (addr_index_table, output_addr_table_entry, &index);
+  addr_index_table
+    ->traverse_noresize<unsigned int *, output_addr_table_entry> (&index);
 }
 
 #if ENABLE_ASSERT_CHECKING
@@ -22570,10 +23667,10 @@ prune_unused_types_update_strings (dw_die_ref die)
        if (s->refcount
            == ((DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) ? 1 : 2))
          {
-           void ** slot;
-           slot = htab_find_slot_with_hash (debug_str_hash, s->str,
-                                            htab_hash_string (s->str),
-                                            INSERT);
+           indirect_string_node **slot
+             = debug_str_hash->find_slot_with_hash (s->str,
+                                                    htab_hash_string (s->str),
+                                                    INSERT);
            gcc_assert (*slot == NULL);
            *slot = s;
          }
@@ -22661,9 +23758,9 @@ prune_unused_types (void)
     prune_unused_types_mark (base_type, 1);
 
   if (debug_str_hash)
-    htab_empty (debug_str_hash);
+    debug_str_hash->empty ();
   if (skeleton_debug_str_hash)
-    htab_empty (skeleton_debug_str_hash);
+    skeleton_debug_str_hash->empty ();
   prune_unused_types_prune (comp_unit_die ());
   for (node = limbo_die_list; node; node = node->next)
     prune_unused_types_prune (node->die);
@@ -22680,11 +23777,10 @@ prune_unused_types (void)
 
 /* Set the parameter to true if there are any relative pathnames in
    the file table.  */
-static int
-file_table_relative_p (void ** slot, void *param)
+int
+file_table_relative_p (dwarf_file_data **slot, bool *p)
 {
-  bool *p = (bool *) param;
-  struct dwarf_file_data *d = (struct dwarf_file_data *) *slot;
+  struct dwarf_file_data *d = *slot;
   if (!IS_ABSOLUTE_PATH (d->filename))
     {
       *p = true;
@@ -22697,14 +23793,14 @@ file_table_relative_p (void ** slot, void *param)
 
 struct comdat_type_hasher : typed_noop_remove <comdat_type_node>
 {
-  typedef comdat_type_node value_type;
-  typedef comdat_type_node compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef comdat_type_node *value_type;
+  typedef comdat_type_node *compare_type;
+  static inline hashval_t hash (const comdat_type_node *);
+  static inline bool equal (const comdat_type_node *, const comdat_type_node *);
 };
 
 inline hashval_t
-comdat_type_hasher::hash (const value_type *type_node)
+comdat_type_hasher::hash (const comdat_type_node *type_node)
 {
   hashval_t h;
   memcpy (&h, type_node->signature, sizeof (h));
@@ -22712,8 +23808,8 @@ comdat_type_hasher::hash (const value_type *type_node)
 }
 
 inline bool
-comdat_type_hasher::equal (const value_type *type_node_1,
-                          const compare_type *type_node_2)
+comdat_type_hasher::equal (const comdat_type_node *type_node_1,
+                          const comdat_type_node *type_node_2)
 {
   return (! memcmp (type_node_1->signature, type_node_2->signature,
                     DWARF_TYPE_SIGNATURE_SIZE));
@@ -22865,11 +23961,11 @@ move_marked_base_types (void)
 }
 
 /* Helper function for resolve_addr, attempt to resolve
-   one CONST_STRING, return non-zero if not successful.  Similarly verify that
+   one CONST_STRING, return true if successful.  Similarly verify that
    SYMBOL_REFs refer to variables emitted in the current CU.  */
 
-static int
-resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
+static bool
+resolve_one_addr (rtx *addr)
 {
   rtx rtl = *addr;
 
@@ -22882,15 +23978,15 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
        = build_array_type (char_type_node, build_index_type (tlen));
       rtl = lookup_constant_def (t);
       if (!rtl || !MEM_P (rtl))
-       return 1;
+       return false;
       rtl = XEXP (rtl, 0);
       if (GET_CODE (rtl) == SYMBOL_REF
          && SYMBOL_REF_DECL (rtl)
          && !TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl)))
-       return 1;
+       return false;
       vec_safe_push (used_rtx_array, rtl);
       *addr = rtl;
-      return 0;
+      return true;
     }
 
   if (GET_CODE (rtl) == SYMBOL_REF
@@ -22899,17 +23995,21 @@ resolve_one_addr (rtx *addr, void *data ATTRIBUTE_UNUSED)
       if (TREE_CONSTANT_POOL_ADDRESS_P (rtl))
        {
          if (!TREE_ASM_WRITTEN (DECL_INITIAL (SYMBOL_REF_DECL (rtl))))
-           return 1;
+           return false;
        }
       else if (!TREE_ASM_WRITTEN (SYMBOL_REF_DECL (rtl)))
-       return 1;
+       return false;
     }
 
-  if (GET_CODE (rtl) == CONST
-      && for_each_rtx (&XEXP (rtl, 0), resolve_one_addr, NULL))
-    return 1;
+  if (GET_CODE (rtl) == CONST)
+    {
+      subrtx_ptr_iterator::array_type array;
+      FOR_EACH_SUBRTX_PTR (iter, array, &XEXP (rtl, 0), ALL)
+       if (!resolve_one_addr (*iter))
+         return false;
+    }
 
-  return 0;
+  return true;
 }
 
 /* For STRING_CST, return SYMBOL_REF of its constant pool entry,
@@ -22939,7 +24039,7 @@ string_cst_pool_decl (tree t)
       len = TREE_STRING_LENGTH (t);
       vec_safe_push (used_rtx_array, rtl);
       ref = new_die (DW_TAG_dwarf_procedure, comp_unit_die (), decl);
-      array = (unsigned char *) ggc_alloc_atomic (len);
+      array = ggc_vec_alloc<unsigned char> (len);
       memcpy (array, TREE_STRING_POINTER (t), len);
       l = new_loc_descr (DW_OP_implicit_value, len, 0);
       l->dw_loc_oprnd2.val_class = dw_val_class_vec;
@@ -23021,7 +24121,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
     switch (loc->dw_loc_opc)
       {
       case DW_OP_addr:
-       if (resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL))
+       if (!resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr))
          {
            if ((prev == NULL
                 || prev->dw_loc_opc == DW_OP_piece
@@ -23036,16 +24136,21 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
        break;
       case DW_OP_GNU_addr_index:
       case DW_OP_GNU_const_index:
-       if ((loc->dw_loc_opc == DW_OP_GNU_addr_index
-            || (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel))
-           && resolve_one_addr (&loc->dw_loc_oprnd1.val_entry->addr.rtl,
-                                NULL))
-         return false;
+       if (loc->dw_loc_opc == DW_OP_GNU_addr_index
+            || (loc->dw_loc_opc == DW_OP_GNU_const_index && loc->dtprel))
+          {
+            rtx rtl = loc->dw_loc_oprnd1.val_entry->addr.rtl;
+            if (!resolve_one_addr (&rtl))
+              return false;
+            remove_addr_table_entry (loc->dw_loc_oprnd1.val_entry);
+            loc->dw_loc_oprnd1.val_entry =
+                add_addr_table_entry (rtl, ate_kind_rtx);
+          }
        break;
       case DW_OP_const4u:
       case DW_OP_const8u:
        if (loc->dtprel
-           && resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr, NULL))
+           && !resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr))
          return false;
        break;
       case DW_OP_plus_uconst:
@@ -23063,7 +24168,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
        break;
       case DW_OP_implicit_value:
        if (loc->dw_loc_oprnd2.val_class == dw_val_class_addr
-           && resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr, NULL))
+           && !resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr))
          return false;
        break;
       case DW_OP_GNU_implicit_pointer:
@@ -23320,7 +24425,7 @@ resolve_addr (dw_die_ref die)
        break;
       case dw_val_class_addr:
        if (a->dw_attr == DW_AT_const_value
-           && resolve_one_addr (&a->dw_attr_val.v.val_addr, NULL))
+           && !resolve_one_addr (&a->dw_attr_val.v.val_addr))
          {
             if (AT_index (a) != NOT_INDEXED)
               remove_addr_table_entry (a->dw_attr_val.val_entry);
@@ -23332,12 +24437,22 @@ resolve_addr (dw_die_ref die)
          {
            tree tdecl = SYMBOL_REF_DECL (a->dw_attr_val.v.val_addr);
            dw_die_ref tdie = lookup_decl_die (tdecl);
+           dw_die_ref cdie;
            if (tdie == NULL
                && DECL_EXTERNAL (tdecl)
-               && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE)
+               && DECL_ABSTRACT_ORIGIN (tdecl) == NULL_TREE
+               && (cdie = lookup_context_die (DECL_CONTEXT (tdecl))))
              {
-               force_decl_die (tdecl);
-               tdie = lookup_decl_die (tdecl);
+               /* Creating a full DIE for tdecl is overly expensive and
+                  at this point even wrong when in the LTO phase
+                  as it can end up generating new type DIEs we didn't
+                  output and thus optimize_external_refs will crash.  */
+               tdie = new_die (DW_TAG_subprogram, cdie, NULL_TREE);
+               add_AT_flag (tdie, DW_AT_external, 1);
+               add_AT_flag (tdie, DW_AT_declaration, 1);
+               add_linkage_attr (tdie, tdecl);
+               add_name_and_src_coords_attributes (tdie, tdecl);
+               equate_decl_number_to_die (tdecl, tdie);
              }
            if (tdie)
              {
@@ -23365,10 +24480,10 @@ resolve_addr (dw_die_ref die)
    This pass tries to share identical local lists in .debug_loc
    section.  */
 
-/* Iteratively hash operands of LOC opcode.  */
+/* Iteratively hash operands of LOC opcode into HSTATE.  */
 
-static hashval_t
-hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
+static void
+hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
 {
   dw_val_ref val1 = &loc->dw_loc_oprnd1;
   dw_val_ref val2 = &loc->dw_loc_oprnd2;
@@ -23427,7 +24542,7 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
     case DW_OP_piece:
     case DW_OP_deref_size:
     case DW_OP_xderef_size:
-      hash = iterative_hash_object (val1->v.val_int, hash);
+      hstate.add_object (val1->v.val_int);
       break;
     case DW_OP_skip:
     case DW_OP_bra:
@@ -23436,33 +24551,37 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
 
        gcc_assert (val1->val_class == dw_val_class_loc);
        offset = val1->v.val_loc->dw_loc_addr - (loc->dw_loc_addr + 3);
-       hash = iterative_hash_object (offset, hash);
+       hstate.add_object (offset);
       }
       break;
     case DW_OP_implicit_value:
-      hash = iterative_hash_object (val1->v.val_unsigned, hash);
+      hstate.add_object (val1->v.val_unsigned);
       switch (val2->val_class)
        {
        case dw_val_class_const:
-         hash = iterative_hash_object (val2->v.val_int, hash);
+         hstate.add_object (val2->v.val_int);
          break;
        case dw_val_class_vec:
          {
            unsigned int elt_size = val2->v.val_vec.elt_size;
            unsigned int len = val2->v.val_vec.length;
 
-           hash = iterative_hash_object (elt_size, hash);
-           hash = iterative_hash_object (len, hash);
-           hash = iterative_hash (val2->v.val_vec.array,
-                                  len * elt_size, hash);
+           hstate.add_int (elt_size);
+           hstate.add_int (len);
+           hstate.add (val2->v.val_vec.array, len * elt_size);
          }
          break;
        case dw_val_class_const_double:
-         hash = iterative_hash_object (val2->v.val_double.low, hash);
-         hash = iterative_hash_object (val2->v.val_double.high, hash);
+         hstate.add_object (val2->v.val_double.low);
+         hstate.add_object (val2->v.val_double.high);
          break;
-       case dw_val_class_addr:
-         hash = iterative_hash_rtx (val2->v.val_addr, hash);
+       case dw_val_class_wide_int:
+         hstate.add (val2->v.val_wide->get_val (),
+                     get_full_len (*val2->v.val_wide)
+                     * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
+         break;
+       case dw_val_class_addr: 
+         inchash::add_rtx (val2->v.val_addr, hstate);
          break;
        default:
          gcc_unreachable ();
@@ -23470,17 +24589,17 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
       break;
     case DW_OP_bregx:
     case DW_OP_bit_piece:
-      hash = iterative_hash_object (val1->v.val_int, hash);
-      hash = iterative_hash_object (val2->v.val_int, hash);
+      hstate.add_object (val1->v.val_int);
+      hstate.add_object (val2->v.val_int);
       break;
     case DW_OP_addr:
     hash_addr:
       if (loc->dtprel)
        {
          unsigned char dtprel = 0xd1;
-         hash = iterative_hash_object (dtprel, hash);
+         hstate.add_object (dtprel);
        }
-      hash = iterative_hash_rtx (val1->v.val_addr, hash);
+      inchash::add_rtx (val1->v.val_addr, hstate);
       break;
     case DW_OP_GNU_addr_index:
     case DW_OP_GNU_const_index:
@@ -23488,16 +24607,16 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
         if (loc->dtprel)
           {
             unsigned char dtprel = 0xd1;
-            hash = iterative_hash_object (dtprel, hash);
+           hstate.add_object (dtprel);
           }
-        hash = iterative_hash_rtx (val1->val_entry->addr.rtl, hash);
+        inchash::add_rtx (val1->val_entry->addr.rtl, hstate);
       }
       break;
     case DW_OP_GNU_implicit_pointer:
-      hash = iterative_hash_object (val2->v.val_int, hash);
+      hstate.add_int (val2->v.val_int);
       break;
     case DW_OP_GNU_entry_value:
-      hash = hash_loc_operands (val1->v.val_loc, hash);
+      hstate.add_object (val1->v.val_loc);
       break;
     case DW_OP_GNU_regval_type:
     case DW_OP_GNU_deref_type:
@@ -23506,16 +24625,16 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
          = get_AT_unsigned (val2->v.val_die_ref.die, DW_AT_byte_size);
        unsigned int encoding
          = get_AT_unsigned (val2->v.val_die_ref.die, DW_AT_encoding);
-       hash = iterative_hash_object (val1->v.val_int, hash);
-       hash = iterative_hash_object (byte_size, hash);
-       hash = iterative_hash_object (encoding, hash);
+       hstate.add_object (val1->v.val_int);
+       hstate.add_object (byte_size);
+       hstate.add_object (encoding);
       }
       break;
     case DW_OP_GNU_convert:
     case DW_OP_GNU_reinterpret:
       if (val1->val_class == dw_val_class_unsigned_const)
        {
-         hash = iterative_hash_object (val1->v.val_unsigned, hash);
+         hstate.add_object (val1->v.val_unsigned);
          break;
        }
       /* FALLTHRU */
@@ -23525,30 +24644,34 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
          = get_AT_unsigned (val1->v.val_die_ref.die, DW_AT_byte_size);
        unsigned int encoding
          = get_AT_unsigned (val1->v.val_die_ref.die, DW_AT_encoding);
-       hash = iterative_hash_object (byte_size, hash);
-       hash = iterative_hash_object (encoding, hash);
+       hstate.add_object (byte_size);
+       hstate.add_object (encoding);
        if (loc->dw_loc_opc != DW_OP_GNU_const_type)
          break;
-       hash = iterative_hash_object (val2->val_class, hash);
+       hstate.add_object (val2->val_class);
        switch (val2->val_class)
          {
          case dw_val_class_const:
-           hash = iterative_hash_object (val2->v.val_int, hash);
+           hstate.add_object (val2->v.val_int);
            break;
          case dw_val_class_vec:
            {
              unsigned int elt_size = val2->v.val_vec.elt_size;
              unsigned int len = val2->v.val_vec.length;
 
-             hash = iterative_hash_object (elt_size, hash);
-             hash = iterative_hash_object (len, hash);
-             hash = iterative_hash (val2->v.val_vec.array,
-                                    len * elt_size, hash);
+             hstate.add_object (elt_size);
+             hstate.add_object (len);
+             hstate.add (val2->v.val_vec.array, len * elt_size);
            }
            break;
          case dw_val_class_const_double:
-           hash = iterative_hash_object (val2->v.val_double.low, hash);
-           hash = iterative_hash_object (val2->v.val_double.high, hash);
+           hstate.add_object (val2->v.val_double.low);
+           hstate.add_object (val2->v.val_double.high);
+           break;
+         case dw_val_class_wide_int:
+           hstate.add (val2->v.val_wide->get_val (),
+                       get_full_len (*val2->v.val_wide)
+                       * HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
            break;
          default:
            gcc_unreachable ();
@@ -23560,13 +24683,12 @@ hash_loc_operands (dw_loc_descr_ref loc, hashval_t hash)
       /* Other codes have no operands.  */
       break;
     }
-  return hash;
 }
 
-/* Iteratively hash the whole DWARF location expression LOC.  */
+/* Iteratively hash the whole DWARF location expression LOC into HSTATE.  */
 
-static inline hashval_t
-hash_locs (dw_loc_descr_ref loc, hashval_t hash)
+static inline void
+hash_locs (dw_loc_descr_ref loc, inchash::hash &hstate)
 {
   dw_loc_descr_ref l;
   bool sizes_computed = false;
@@ -23576,15 +24698,14 @@ hash_locs (dw_loc_descr_ref loc, hashval_t hash)
   for (l = loc; l != NULL; l = l->dw_loc_next)
     {
       enum dwarf_location_atom opc = l->dw_loc_opc;
-      hash = iterative_hash_object (opc, hash);
+      hstate.add_object (opc);
       if ((opc == DW_OP_skip || opc == DW_OP_bra) && !sizes_computed)
        {
          size_of_locs (loc);
          sizes_computed = true;
        }
-      hash = hash_loc_operands (l, hash);
+      hash_loc_operands (l, hstate);
     }
-  return hash;
 }
 
 /* Compute hash of the whole location list LIST_HEAD.  */
@@ -23593,18 +24714,17 @@ static inline void
 hash_loc_list (dw_loc_list_ref list_head)
 {
   dw_loc_list_ref curr = list_head;
-  hashval_t hash = 0;
+  inchash::hash hstate;
 
   for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
     {
-      hash = iterative_hash (curr->begin, strlen (curr->begin) + 1, hash);
-      hash = iterative_hash (curr->end, strlen (curr->end) + 1, hash);
+      hstate.add (curr->begin, strlen (curr->begin) + 1);
+      hstate.add (curr->end, strlen (curr->end) + 1);
       if (curr->section)
-       hash = iterative_hash (curr->section, strlen (curr->section) + 1,
-                              hash);
-      hash = hash_locs (curr->expr, hash);
+       hstate.add (curr->section, strlen (curr->section) + 1);
+      hash_locs (curr->expr, hstate);
     }
-  list_head->hash = hash;
+  list_head->hash = hstate.end ();
 }
 
 /* Return true if X and Y opcodes have the same operands.  */
@@ -23698,6 +24818,8 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
        case dw_val_class_const_double:
          return valx2->v.val_double.low == valy2->v.val_double.low
                 && valx2->v.val_double.high == valy2->v.val_double.high;
+       case dw_val_class_wide_int:
+         return *valx2->v.val_wide == *valy2->v.val_wide;
        case dw_val_class_addr:
          return rtx_equal_p (valx2->v.val_addr, valy2->v.val_addr);
        default:
@@ -23741,6 +24863,8 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
        case dw_val_class_const_double:
          return valx2->v.val_double.low == valy2->v.val_double.low
                 && valx2->v.val_double.high == valy2->v.val_double.high;
+       case dw_val_class_wide_int:
+         return *valx2->v.val_wide == *valy2->v.val_wide;
        default:
          gcc_unreachable ();
        }
@@ -23782,16 +24906,17 @@ compare_locs (dw_loc_descr_ref x, dw_loc_descr_ref y)
 
 struct loc_list_hasher : typed_noop_remove <dw_loc_list_struct>
 {
-  typedef dw_loc_list_struct value_type;
-  typedef dw_loc_list_struct compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef dw_loc_list_struct *value_type;
+  typedef dw_loc_list_struct *compare_type;
+  static inline hashval_t hash (const dw_loc_list_struct *);
+  static inline bool equal (const dw_loc_list_struct *,
+                           const dw_loc_list_struct *);
 };
 
 /* Return precomputed hash of location list X.  */
 
 inline hashval_t
-loc_list_hasher::hash (const value_type *x)
+loc_list_hasher::hash (const dw_loc_list_struct *x)
 {
   return x->hash;
 }
@@ -23799,7 +24924,8 @@ loc_list_hasher::hash (const value_type *x)
 /* Return true if location lists A and B are the same.  */
 
 inline bool
-loc_list_hasher::equal (const value_type *a, const compare_type *b)
+loc_list_hasher::equal (const dw_loc_list_struct *a,
+                       const dw_loc_list_struct *b)
 {
   if (a == b)
     return 1;
@@ -23815,14 +24941,14 @@ loc_list_hasher::equal (const value_type *a, const compare_type *b)
   return a == NULL && b == NULL;
 }
 
-typedef hash_table <loc_list_hasher> loc_list_hash_type;
+typedef hash_table<loc_list_hasher> loc_list_hash_type;
 
 
 /* Recursively optimize location lists referenced from DIE
    children and share them whenever possible.  */
 
 static void
-optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type htab)
+optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type *htab)
 {
   dw_die_ref c;
   dw_attr_ref a;
@@ -23836,7 +24962,7 @@ optimize_location_lists_1 (dw_die_ref die, loc_list_hash_type htab)
        /* TODO: perform some optimizations here, before hashing
           it and storing into the hash table.  */
        hash_loc_list (list);
-       slot = htab.find_slot_with_hash (list, list->hash, INSERT);
+       slot = htab->find_slot_with_hash (list, list->hash, INSERT);
        if (*slot == NULL)
          *slot = list;
        else
@@ -23885,10 +25011,8 @@ index_location_lists (dw_die_ref die)
 static void
 optimize_location_lists (dw_die_ref die)
 {
-  loc_list_hash_type htab;
-  htab.create (500);
-  optimize_location_lists_1 (die, htab);
-  htab.dispose ();
+  loc_list_hash_type htab (500);
+  optimize_location_lists_1 (die, &htab);
 }
 \f
 /* Output stuff that dwarf requires at the end of every file,
@@ -23897,12 +25021,12 @@ optimize_location_lists (dw_die_ref die)
 static void
 dwarf2out_finish (const char *filename)
 {
-  limbo_die_node *node, *next_node;
   comdat_type_node *ctnode;
-  hash_table <comdat_type_hasher> comdat_type_table;
-  unsigned int i;
   dw_die_ref main_comp_unit_die;
 
+  /* Flush out any latecomers to the limbo party.  */
+  dwarf2out_early_finish ();
+
   /* PCH might result in DW_AT_producer string being restored from the
      header compilation, so always fill it with empty string initially
      and overwrite only here.  */
@@ -23915,77 +25039,23 @@ dwarf2out_finish (const char *filename)
   gen_remaining_tmpl_value_param_die_attribute ();
 
   /* Add the name for the main input file now.  We delayed this from
-     dwarf2out_init to avoid complications with PCH.  */
-  add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+     dwarf2out_init to avoid complications with PCH.
+     For LTO produced units use a fixed artificial name to avoid
+     leaking tempfile names into the dwarf.  */
+  if (!in_lto_p)
+    add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+  else
+    add_name_attribute (comp_unit_die (), "<artificial>");
   if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
     add_comp_dir_attribute (comp_unit_die ());
   else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
     {
       bool p = false;
-      htab_traverse (file_table, file_table_relative_p, &p);
+      file_table->traverse<bool *, file_table_relative_p> (&p);
       if (p)
        add_comp_dir_attribute (comp_unit_die ());
     }
 
-  if (deferred_locations_list)
-    for (i = 0; i < deferred_locations_list->length (); i++)
-      {
-       add_location_or_const_value_attribute (
-           (*deferred_locations_list)[i].die,
-           (*deferred_locations_list)[i].variable,
-           false,
-           DW_AT_location);
-      }
-
-  /* Traverse the limbo die list, and add parent/child links.  The only
-     dies without parents that should be here are concrete instances of
-     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
-     For concrete instances, we can get the parent die from the abstract
-     instance.  */
-  for (node = limbo_die_list; node; node = next_node)
-    {
-      dw_die_ref die = node->die;
-      next_node = node->next;
-
-      if (die->die_parent == NULL)
-       {
-         dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
-
-         if (origin && origin->die_parent)
-           add_child_die (origin->die_parent, die);
-         else if (is_cu_die (die))
-           ;
-         else if (seen_error ())
-           /* It's OK to be confused by errors in the input.  */
-           add_child_die (comp_unit_die (), die);
-         else
-           {
-             /* In certain situations, the lexical block containing a
-                nested function can be optimized away, which results
-                in the nested function die being orphaned.  Likewise
-                with the return type of that nested function.  Force
-                this to be a child of the containing function.
-
-                It may happen that even the containing function got fully
-                inlined and optimized out.  In that case we are lost and
-                assign the empty child.  This should not be big issue as
-                the function is likely unreachable too.  */
-             gcc_assert (node->created_for);
-
-             if (DECL_P (node->created_for))
-               origin = get_context_die (DECL_CONTEXT (node->created_for));
-             else if (TYPE_P (node->created_for))
-               origin = scope_die_for (node->created_for, comp_unit_die ());
-             else
-               origin = comp_unit_die ();
-
-             add_child_die (origin, die);
-           }
-       }
-    }
-
-  limbo_die_list = NULL;
-
 #if ENABLE_ASSERT_CHECKING
   {
     dw_die_ref die = comp_unit_die (), c;
@@ -23995,22 +25065,6 @@ dwarf2out_finish (const char *filename)
   resolve_addr (comp_unit_die ());
   move_marked_base_types ();
 
-  for (node = deferred_asm_name; node; node = node->next)
-    {
-      tree decl = node->created_for;
-      /* When generating LTO bytecode we can not generate new assembler
-         names at this point and all important decls got theirs via
-        free-lang-data.  */
-      if ((!flag_generate_lto || DECL_ASSEMBLER_NAME_SET_P (decl))
-         && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       {
-         add_linkage_attr (node->die, decl);
-         move_linkage_attr (node->die);
-       }
-    }
-
-  deferred_asm_name = NULL;
-
   /* Walk through the list of incomplete types again, trying once more to
      emit full debugging info for them.  */
   retry_incomplete_types ();
@@ -24049,6 +25103,7 @@ dwarf2out_finish (const char *filename)
   /* Traverse the DIE's and add add sibling attributes to those DIE's
      that have children.  */
   add_sibling_attributes (comp_unit_die ());
+  limbo_die_node *node;
   for (node = limbo_die_list; node; node = node->next)
     add_sibling_attributes (node->die);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -24132,18 +25187,24 @@ dwarf2out_finish (const char *filename)
                   dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
                   macinfo_section_label);
 
-  if (dwarf_split_debug_info && addr_index_table != NULL)
+  if (dwarf_split_debug_info)
     {
       /* optimize_location_lists calculates the size of the lists,
          so index them first, and assign indices to the entries.
          Although optimize_location_lists will remove entries from
          the table, it only does so for duplicates, and therefore
          only reduces ref_counts to 1.  */
-      unsigned int index = 0;
       index_location_lists (comp_unit_die ());
-      htab_traverse_noresize (addr_index_table,
-                              index_addr_table_entry, &index);
+
+      if (addr_index_table != NULL)
+        {
+          unsigned int index = 0;
+          addr_index_table
+           ->traverse_noresize<unsigned int *, index_addr_table_entry>
+           (&index);
+        }
     }
+
   if (have_location_lists)
     optimize_location_lists (comp_unit_die ());
 
@@ -24159,8 +25220,7 @@ dwarf2out_finish (const char *filename)
          skeleton die attrs are added when the skeleton type unit is
          created, so ensure it is created by this point.  */
       add_top_level_skeleton_die_attrs (main_comp_unit_die);
-      (void) get_skeleton_type_unit ();
-      htab_traverse_noresize (debug_str_hash, index_string, &index);
+      debug_str_hash->traverse_noresize<unsigned int *, index_string> (&index);
     }
 
   /* Output all of the compilation units.  We put the main one last so that
@@ -24168,7 +25228,7 @@ dwarf2out_finish (const char *filename)
   for (node = limbo_die_list; node; node = node->next)
     output_comp_unit (node->die, 0);
 
-  comdat_type_table.create (100);
+  hash_table<comdat_type_hasher> comdat_type_table (100);
   for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
     {
       comdat_type_node **slot = comdat_type_table.find_slot (ctnode, INSERT);
@@ -24189,7 +25249,6 @@ dwarf2out_finish (const char *filename)
       output_comdat_type_unit (ctnode);
       *slot = ctnode;
     }
-  comdat_type_table.dispose ();
 
   /* The AT_pubnames attribute needs to go in all skeleton dies, including
      both the main_cu and all skeleton TUs.  Making this call unconditional
@@ -24306,4 +25365,164 @@ dwarf2out_finish (const char *filename)
     output_indirect_strings ();
 }
 
+/* Perform any cleanups needed after the early debug generation pass
+   has run.  */
+
+static void
+dwarf2out_early_finish (void)
+{
+  limbo_die_node *node, *next_node;
+
+  /* Add DW_AT_linkage_name for all deferred DIEs.  */
+  for (node = deferred_asm_name; node; node = node->next)
+    {
+      tree decl = node->created_for;
+      if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
+         /* A missing DECL_ASSEMBLER_NAME can be a constant DIE that
+            ended up in in deferred_asm_name before we knew it was
+            constant and never written to disk.  */
+         && DECL_ASSEMBLER_NAME (decl))
+       {
+         add_linkage_attr (node->die, decl);
+         move_linkage_attr (node->die);
+       }
+    }
+  deferred_asm_name = NULL;
+
+  /* Traverse the limbo die list, and add parent/child links.  The only
+     dies without parents that should be here are concrete instances of
+     inline functions, and the comp_unit_die.  We can ignore the comp_unit_die.
+     For concrete instances, we can get the parent die from the abstract
+     instance.
+
+     The point here is to flush out the limbo list so that it is empty
+     and we don't need to stream it for LTO.  */
+  for (node = limbo_die_list; node; node = next_node)
+    {
+      dw_die_ref die = node->die;
+      next_node = node->next;
+
+      if (die->die_parent == NULL)
+       {
+         dw_die_ref origin = get_AT_ref (die, DW_AT_abstract_origin);
+
+         if (origin && origin->die_parent)
+           add_child_die (origin->die_parent, die);
+         else if (is_cu_die (die))
+           ;
+         else if (seen_error ())
+           /* It's OK to be confused by errors in the input.  */
+           add_child_die (comp_unit_die (), die);
+         else
+           {
+             /* In certain situations, the lexical block containing a
+                nested function can be optimized away, which results
+                in the nested function die being orphaned.  Likewise
+                with the return type of that nested function.  Force
+                this to be a child of the containing function.
+
+                It may happen that even the containing function got fully
+                inlined and optimized out.  In that case we are lost and
+                assign the empty child.  This should not be big issue as
+                the function is likely unreachable too.  */
+             gcc_assert (node->created_for);
+
+             if (DECL_P (node->created_for))
+               origin = get_context_die (DECL_CONTEXT (node->created_for));
+             else if (TYPE_P (node->created_for))
+               origin = scope_die_for (node->created_for, comp_unit_die ());
+             else
+               origin = comp_unit_die ();
+
+             add_child_die (origin, die);
+           }
+       }
+    }
+
+  limbo_die_list = NULL;
+}
+
+/* Reset all state within dwarf2out.c so that we can rerun the compiler
+   within the same process.  For use by toplev::finalize.  */
+
+void
+dwarf2out_c_finalize (void)
+{
+  last_var_location_insn = NULL;
+  cached_next_real_insn = NULL;
+  used_rtx_array = NULL;
+  incomplete_types = NULL;
+  decl_scope_table = NULL;
+  debug_info_section = NULL;
+  debug_skeleton_info_section = NULL;
+  debug_abbrev_section = NULL;
+  debug_skeleton_abbrev_section = NULL;
+  debug_aranges_section = NULL;
+  debug_addr_section = NULL;
+  debug_macinfo_section = NULL;
+  debug_line_section = NULL;
+  debug_skeleton_line_section = NULL;
+  debug_loc_section = NULL;
+  debug_pubnames_section = NULL;
+  debug_pubtypes_section = NULL;
+  debug_str_section = NULL;
+  debug_str_dwo_section = NULL;
+  debug_str_offsets_section = NULL;
+  debug_ranges_section = NULL;
+  debug_frame_section = NULL;
+  fde_vec = NULL;
+  debug_str_hash = NULL;
+  skeleton_debug_str_hash = NULL;
+  dw2_string_counter = 0;
+  have_multiple_function_sections = false;
+  text_section_used = false;
+  cold_text_section_used = false;
+  cold_text_section = NULL;
+  current_unit_personality = NULL;
+
+  next_die_offset = 0;
+  single_comp_unit_die = NULL;
+  comdat_type_list = NULL;
+  limbo_die_list = NULL;
+  file_table = NULL;
+  decl_die_table = NULL;
+  common_block_die_table = NULL;
+  decl_loc_table = NULL;
+  call_arg_locations = NULL;
+  call_arg_loc_last = NULL;
+  call_site_count = -1;
+  tail_call_site_count = -1;
+  cached_dw_loc_list_table = NULL;
+  abbrev_die_table = NULL;
+  abbrev_die_table_allocated = 0;
+  abbrev_die_table_in_use = 0;
+  line_info_label_num = 0;
+  cur_line_info_table = NULL;
+  text_section_line_info = NULL;
+  cold_text_section_line_info = NULL;
+  separate_line_info = NULL;
+  info_section_emitted = false;
+  pubname_table = NULL;
+  pubtype_table = NULL;
+  macinfo_table = NULL;
+  ranges_table = NULL;
+  ranges_table_allocated = 0;
+  ranges_table_in_use = 0;
+  ranges_by_label = 0;
+  ranges_by_label_allocated = 0;
+  ranges_by_label_in_use = 0;
+  have_location_lists = false;
+  loclabel_num = 0;
+  poc_label_num = 0;
+  last_emitted_file = NULL;
+  label_num = 0;
+  tmpl_value_parm_die_table = NULL;
+  generic_type_instances = NULL;
+  frame_pointer_fb_offset = 0;
+  frame_pointer_fb_offset_valid = false;
+  base_types.release ();
+  XDELETEVEC (producer_string);
+  producer_string = NULL;
+}
+
 #include "gt-dwarf2out.h"