]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/dwarf2/read.c
gdb: add type::name / type::set_name
[thirdparty/binutils-gdb.git] / gdb / dwarf2 / read.c
index f1ddadef8d5c485801715cd5ab6eabd438ab9bc0..2c81a4eed65bf87e52d8dffadbc2737093c1d291 100644 (file)
@@ -1082,29 +1082,52 @@ struct partial_die_info : public allocate_on_obstack
    and friends.  */
 static int bits_per_byte = 8;
 
-/* When reading a variant or variant part, we track a bit more
-   information about the field, and store it in an object of this
-   type.  */
+struct variant_part_builder;
+
+/* When reading a variant, we track a bit more information about the
+   field, and store it in an object of this type.  */
 
 struct variant_field
 {
-  /* If we see a DW_TAG_variant, then this will be the discriminant
-     value.  */
-  ULONGEST discriminant_value;
+  int first_field = -1;
+  int last_field = -1;
+
+  /* A variant can contain other variant parts.  */
+  std::vector<variant_part_builder> variant_parts;
+
   /* If we see a DW_TAG_variant, then this will be set if this is the
      default branch.  */
-  bool default_branch;
-  /* While reading a DW_TAG_variant_part, this will be set if this
-     field is the discriminant.  */
-  bool is_discriminant;
+  bool default_branch = false;
+  /* If we see a DW_AT_discr_value, then this will be the discriminant
+     value.  */
+  ULONGEST discriminant_value = 0;
+  /* If we see a DW_AT_discr_list, then this is a pointer to the list
+     data.  */
+  struct dwarf_block *discr_list_data = nullptr;
+};
+
+/* This represents a DW_TAG_variant_part.  */
+
+struct variant_part_builder
+{
+  /* The offset of the discriminant field.  */
+  sect_offset discriminant_offset {};
+
+  /* Variants that are direct children of this variant part.  */
+  std::vector<variant_field> variants;
+
+  /* True if we're currently reading a variant.  */
+  bool processing_variant = false;
 };
 
 struct nextfield
 {
   int accessibility = 0;
   int virtuality = 0;
-  /* Extra information to describe a variant or variant part.  */
-  struct variant_field variant {};
+  /* Variant parts need to find the discriminant, which is a DIE
+     reference.  We track the section offset of each field to make
+     this link.  */
+  sect_offset offset;
   struct field field {};
 };
 
@@ -1139,6 +1162,13 @@ struct field_info
        list.  */
     std::vector<struct decl_field> nested_types_list;
 
+    /* If non-null, this is the variant part we are currently
+       reading.  */
+    variant_part_builder *current_variant_part = nullptr;
+    /* This holds all the top-level variant parts attached to the type
+       we're reading.  */
+    std::vector<variant_part_builder> variant_parts;
+
     /* Return the total number of fields (including baseclasses).  */
     int nfields () const
     {
@@ -1405,7 +1435,8 @@ static const char *namespace_name (struct die_info *die,
 
 static void process_enumeration_scope (struct die_info *, struct dwarf2_cu *);
 
-static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *,
+                                bool * = nullptr);
 
 static enum dwarf_array_dim_ordering read_array_order (struct die_info *,
                                                       struct dwarf2_cu *);
@@ -2567,7 +2598,7 @@ create_addrmap_from_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
                           struct mapped_index *index)
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   const gdb_byte *iter, *end;
   struct addrmap *mutable_map;
   CORE_ADDR baseaddr;
@@ -2624,7 +2655,7 @@ create_addrmap_from_aranges (struct dwarf2_per_objfile *dwarf2_per_objfile,
 {
   struct objfile *objfile = dwarf2_per_objfile->objfile;
   bfd *abfd = objfile->obfd;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
 
   auto_obstack temp_obstack;
@@ -2854,8 +2885,7 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
    Returns true if all went well, false otherwise.  */
 
 static bool
-read_gdb_index_from_buffer (struct objfile *objfile,
-                           const char *filename,
+read_gdb_index_from_buffer (const char *filename,
                            bool deprecated_ok,
                            gdb::array_view<const gdb_byte> buffer,
                            struct mapped_index *map,
@@ -2983,7 +3013,7 @@ dwarf2_read_gdb_index
     return 0;
 
   std::unique_ptr<struct mapped_index> map (new struct mapped_index);
-  if (!read_gdb_index_from_buffer (objfile, objfile_name (objfile),
+  if (!read_gdb_index_from_buffer (objfile_name (objfile),
                                   use_deprecated_index_sections,
                                   main_index_contents, map.get (), &cu_list,
                                   &cu_list_elements, &types_list,
@@ -3009,8 +3039,7 @@ dwarf2_read_gdb_index
       if (dwz_index_content.empty ())
        return 0;
 
-      if (!read_gdb_index_from_buffer (objfile,
-                                      bfd_get_filename (dwz->dwz_bfd.get ()),
+      if (!read_gdb_index_from_buffer (bfd_get_filename (dwz->dwz_bfd.get ()),
                                       1, dwz_index_content, &dwz_map,
                                       &dwz_list, &dwz_list_elements,
                                       &dwz_types_ignore,
@@ -3913,11 +3942,11 @@ dw2_expand_symtabs_matching_symbol
   struct name_and_matcher
   {
     symbol_name_matcher_ftype *matcher;
-    const std::string &name;
+    const char *name;
 
     bool operator== (const name_and_matcher &other) const
     {
-      return matcher == other.matcher && name == other.name;
+      return matcher == other.matcher && strcmp (name, other.name) == 0;
     }
   };
 
@@ -4605,7 +4634,7 @@ static void
 dw2_expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info &lookup_name,
+   const lookup_name_info *lookup_name,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
    enum search_domain kind)
@@ -4619,9 +4648,21 @@ dw2_expand_symtabs_matching
 
   dw_expand_symtabs_matching_file_matcher (dwarf2_per_objfile, file_matcher);
 
+  if (symbol_matcher == NULL && lookup_name == NULL)
+    {
+      for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
+       {
+         QUIT;
+
+         dw2_expand_symtabs_matching_one (per_cu, file_matcher,
+                                          expansion_notify);
+       }
+      return;
+    }
+
   mapped_index &index = *dwarf2_per_objfile->index_table;
 
-  dw2_expand_symtabs_matching_symbol (index, lookup_name,
+  dw2_expand_symtabs_matching_symbol (index, *lookup_name,
                                      symbol_matcher,
                                      kind, [&] (offset_type idx)
     {
@@ -4680,7 +4721,7 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile,
 
   if (warn_if_readin && data->v.quick->compunit_symtab)
     warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
-            paddress (get_objfile_arch (objfile), pc));
+            paddress (objfile->arch (), pc));
 
   result
     = recursively_find_pc_sect_compunit_symtab (dw2_instantiate_symtab (data,
@@ -4810,7 +4851,7 @@ read_debug_names_from_section (struct objfile *objfile,
 
   section->read (objfile);
 
-  map.dwarf5_byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
+  map.dwarf5_byte_order = gdbarch_byte_order (objfile->arch ());
 
   const gdb_byte *addr = section->buffer;
 
@@ -4981,6 +5022,26 @@ create_cus_from_debug_names_list (struct dwarf2_per_objfile *dwarf2_per_objfile,
                                  dwarf2_section_info &section,
                                  bool is_dwz)
 {
+  if (!map.augmentation_is_gdb)
+    {
+    for (uint32_t i = 0; i < map.cu_count; ++i)
+      {
+       sect_offset sect_off
+         = (sect_offset) (extract_unsigned_integer
+                          (map.cu_table_reordered + i * map.offset_size,
+                           map.offset_size,
+                           map.dwarf5_byte_order));
+       /* We don't know the length of the CU, because the CU list in a
+          .debug_names index can be incomplete, so we can't use the start of
+          the next CU as end of this CU.  We create the CUs here with length 0,
+          and in cutu_reader::cutu_reader we'll fill in the actual length.  */
+       dwarf2_per_cu_data *per_cu
+         = create_cu_from_index_list (dwarf2_per_objfile, &section, is_dwz,
+                                      sect_off, 0);
+       dwarf2_per_objfile->all_comp_units.push_back (per_cu);
+      }
+    }
+
   sect_offset sect_off_prev;
   for (uint32_t i = 0; i <= map.cu_count; ++i)
     {
@@ -5311,6 +5372,18 @@ dw2_debug_names_iterator::next ()
          ull = read_unsigned_leb128 (abfd, m_addr, &bytes_read);
          m_addr += bytes_read;
          break;
+       case DW_FORM_ref4:
+         ull = read_4_bytes (abfd, m_addr);
+         m_addr += 4;
+         break;
+       case DW_FORM_ref8:
+         ull = read_8_bytes (abfd, m_addr);
+         m_addr += 8;
+         break;
+       case DW_FORM_ref_sig8:
+         ull = read_8_bytes (abfd, m_addr);
+         m_addr += 8;
+         break;
        default:
          complaint (_("Unsupported .debug_names form %s [in module %s]"),
                     dwarf_form_name (attr.form),
@@ -5343,6 +5416,12 @@ dw2_debug_names_iterator::next ()
            }
          per_cu = &dwarf2_per_objfile->get_tu (ull)->per_cu;
          break;
+       case DW_IDX_die_offset:
+         /* In a per-CU index (as opposed to a per-module index), index
+            entries without CU attribute implicitly refer to the single CU.  */
+         if (per_cu == NULL)
+           per_cu = dwarf2_per_objfile->get_cu (0);
+         break;
        case DW_IDX_GNU_internal:
          if (!m_map.augmentation_is_gdb)
            break;
@@ -5614,7 +5693,7 @@ static void
 dw2_debug_names_expand_symtabs_matching
   (struct objfile *objfile,
    gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
-   const lookup_name_info &lookup_name,
+   const lookup_name_info *lookup_name,
    gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
    gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
    enum search_domain kind)
@@ -5628,9 +5707,21 @@ dw2_debug_names_expand_symtabs_matching
 
   dw_expand_symtabs_matching_file_matcher (dwarf2_per_objfile, file_matcher);
 
+  if (symbol_matcher == NULL && lookup_name == NULL)
+    {
+      for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
+       {
+         QUIT;
+
+         dw2_expand_symtabs_matching_one (per_cu, file_matcher,
+                                          expansion_notify);
+       }
+      return;
+    }
+
   mapped_debug_names &map = *dwarf2_per_objfile->debug_names_table;
 
-  dw2_expand_symtabs_matching_symbol (map, lookup_name,
+  dw2_expand_symtabs_matching_symbol (map, *lookup_name,
                                      symbol_matcher,
                                      kind, [&] (offset_type namei)
     {
@@ -5895,22 +5986,31 @@ struct dwarf2_include_psymtab : public partial_symtab
 
   void read_symtab (struct objfile *objfile) override
   {
-    expand_psymtab (objfile);
+    /* It's an include file, no symbols to read for it.
+       Everything is in the includer symtab.  */
+
+    /* The expansion of a dwarf2_include_psymtab is just a trigger for
+       expansion of the includer psymtab.  We use the dependencies[0] field to
+       model the includer.  But if we go the regular route of calling
+       expand_psymtab here, and having expand_psymtab call expand_dependencies
+       to expand the includer, we'll only use expand_psymtab on the includer
+       (making it a non-toplevel psymtab), while if we expand the includer via
+       another path, we'll use read_symtab (making it a toplevel psymtab).
+       So, don't pretend a dwarf2_include_psymtab is an actual toplevel
+       psymtab, and trigger read_symtab on the includer here directly.  */
+    includer ()->read_symtab (objfile);
   }
 
   void expand_psymtab (struct objfile *objfile) override
   {
-    if (m_readin)
-      return;
-    /* It's an include file, no symbols to read for it.
-       Everything is in the parent symtab.  */
-    expand_dependencies (objfile);
-    m_readin = true;
+    /* This is not called by read_symtab, and should not be called by any
+       expand_dependencies.  */
+    gdb_assert (false);
   }
 
   bool readin_p () const override
   {
-    return m_readin;
+    return includer ()->readin_p ();
   }
 
   struct compunit_symtab *get_compunit_symtab () const override
@@ -5919,8 +6019,13 @@ struct dwarf2_include_psymtab : public partial_symtab
   }
 
 private:
-
-  bool m_readin = false;
+  partial_symtab *includer () const
+  {
+    /* An include psymtab has exactly one dependency: the psymtab that
+       includes it.  */
+    gdb_assert (this->number_of_dependencies == 1);
+    return this->dependencies[0];
+  }
 };
 
 /* Allocate a new partial symtab for file named NAME and mark this new
@@ -6861,7 +6966,10 @@ cutu_reader::cutu_reader (struct dwarf2_per_cu_data *this_cu,
                                                    rcuh_kind::COMPILE);
 
          gdb_assert (this_cu->sect_off == cu->header.sect_off);
-         gdb_assert (this_cu->length == cu->header.get_length ());
+         if (this_cu->length == 0)
+           this_cu->length = cu->header.get_length ();
+         else
+           gdb_assert (this_cu->length == cu->header.get_length ());
          this_cu->dwarf_version = cu->header.version;
        }
     }
@@ -7217,7 +7325,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
 {
   struct dwarf2_cu *cu = reader->cu;
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct dwarf2_per_cu_data *per_cu = cu->per_cu;
   CORE_ADDR baseaddr;
   CORE_ADDR best_lowpc = 0, best_highpc = 0;
@@ -7743,7 +7851,12 @@ dwarf2_build_psymtabs_hard (struct dwarf2_per_objfile *dwarf2_per_objfile)
                           addrmap_create_mutable (&temp_obstack));
 
   for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
-    process_psymtab_comp_unit (per_cu, false, language_minimal);
+    {
+      if (per_cu->v.psymtab != NULL)
+       /* In case a forward DW_TAG_imported_unit has read the CU already.  */
+       continue;
+      process_psymtab_comp_unit (per_cu, false, language_minimal);
+    }
 
   /* This has to wait until we read the CUs, we need the list of DWOs.  */
   process_skeletonless_type_units (dwarf2_per_objfile);
@@ -7910,7 +8023,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
            case DW_TAG_variable:
            case DW_TAG_typedef:
            case DW_TAG_union_type:
-             if (!pdi->is_declaration)
+             if (!pdi->is_declaration
+                 || (pdi->tag == DW_TAG_variable && pdi->is_external))
                {
                  add_partial_symbol (pdi, cu);
                }
@@ -8131,7 +8245,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR addr = 0;
   const char *actual_name = NULL;
   CORE_ADDR baseaddr;
@@ -8146,6 +8260,15 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
   if (actual_name == NULL)
     actual_name = pdi->name;
 
+  partial_symbol psymbol;
+  memset (&psymbol, 0, sizeof (psymbol));
+  psymbol.ginfo.set_language (cu->language, &objfile->objfile_obstack);
+  psymbol.ginfo.section = -1;
+
+  /* The code below indicates that the psymbol should be installed by
+     setting this.  */
+  gdb::optional<psymbol_placement> where;
+
   switch (pdi->tag)
     {
     case DW_TAG_inlined_subroutine:
@@ -8162,34 +8285,25 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
              But in Ada and Fortran, we want to be able to access nested
              procedures globally.  So all Ada and Fortran subprograms are
              stored in the global scope.  */
-         add_psymbol_to_list (actual_name,
-                              built_actual_name != NULL,
-                              VAR_DOMAIN, LOC_BLOCK,
-                              SECT_OFF_TEXT (objfile),
-                              psymbol_placement::GLOBAL,
-                              addr,
-                              cu->language, objfile);
+         where = psymbol_placement::GLOBAL;
        }
       else
-       {
-         add_psymbol_to_list (actual_name,
-                              built_actual_name != NULL,
-                              VAR_DOMAIN, LOC_BLOCK,
-                              SECT_OFF_TEXT (objfile),
-                              psymbol_placement::STATIC,
-                              addr, cu->language, objfile);
-       }
+       where = psymbol_placement::STATIC;
+
+      psymbol.domain = VAR_DOMAIN;
+      psymbol.aclass = LOC_BLOCK;
+      psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+      psymbol.ginfo.value.address = addr;
 
       if (pdi->main_subprogram && actual_name != NULL)
        set_objfile_main_name (objfile, actual_name, cu->language);
       break;
     case DW_TAG_constant:
-      add_psymbol_to_list (actual_name,
-                          built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC,
-                          -1, (pdi->is_external
-                               ? psymbol_placement::GLOBAL
-                               : psymbol_placement::STATIC),
-                          0, cu->language, objfile);
+      psymbol.domain = VAR_DOMAIN;
+      psymbol.aclass = LOC_STATIC;
+      where = (pdi->is_external
+              ? psymbol_placement::GLOBAL
+              : psymbol_placement::STATIC);
       break;
     case DW_TAG_variable:
       if (pdi->d.locdesc)
@@ -8220,12 +8334,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
             table building.  */
 
          if (pdi->d.locdesc || pdi->has_type)
-           add_psymbol_to_list (actual_name,
-                                built_actual_name != NULL,
-                                VAR_DOMAIN, LOC_STATIC,
-                                SECT_OFF_TEXT (objfile),
-                                psymbol_placement::GLOBAL,
-                                addr, cu->language, objfile);
+           {
+             psymbol.domain = VAR_DOMAIN;
+             psymbol.aclass = LOC_STATIC;
+             psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+             psymbol.ginfo.value.address = addr;
+             where = psymbol_placement::GLOBAL;
+           }
        }
       else
        {
@@ -8236,42 +8351,37 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
          if (!has_loc && !pdi->has_const_value)
            return;
 
-         add_psymbol_to_list (actual_name,
-                              built_actual_name != NULL,
-                              VAR_DOMAIN, LOC_STATIC,
-                              SECT_OFF_TEXT (objfile),
-                              psymbol_placement::STATIC,
-                              has_loc ? addr : 0,
-                              cu->language, objfile);
+         psymbol.domain = VAR_DOMAIN;
+         psymbol.aclass = LOC_STATIC;
+         psymbol.ginfo.section = SECT_OFF_TEXT (objfile);
+         if (has_loc)
+           psymbol.ginfo.value.address = addr;
+         where = psymbol_placement::STATIC;
        }
       break;
     case DW_TAG_typedef:
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
-      add_psymbol_to_list (actual_name,
-                          built_actual_name != NULL,
-                          VAR_DOMAIN, LOC_TYPEDEF, -1,
-                          psymbol_placement::STATIC,
-                          0, cu->language, objfile);
+      psymbol.domain = VAR_DOMAIN;
+      psymbol.aclass = LOC_TYPEDEF;
+      where = psymbol_placement::STATIC;
       break;
     case DW_TAG_imported_declaration:
     case DW_TAG_namespace:
-      add_psymbol_to_list (actual_name,
-                          built_actual_name != NULL,
-                          VAR_DOMAIN, LOC_TYPEDEF, -1,
-                          psymbol_placement::GLOBAL,
-                          0, cu->language, objfile);
+      psymbol.domain = VAR_DOMAIN;
+      psymbol.aclass = LOC_TYPEDEF;
+      where = psymbol_placement::GLOBAL;
       break;
     case DW_TAG_module:
       /* With Fortran 77 there might be a "BLOCK DATA" module
          available without any name.  If so, we skip the module as it
          doesn't bring any value.  */
       if (actual_name != nullptr)
-       add_psymbol_to_list (actual_name,
-                            built_actual_name != NULL,
-                            MODULE_DOMAIN, LOC_TYPEDEF, -1,
-                            psymbol_placement::GLOBAL,
-                            0, cu->language, objfile);
+       {
+         psymbol.domain = MODULE_DOMAIN;
+         psymbol.aclass = LOC_TYPEDEF;
+         where = psymbol_placement::GLOBAL;
+       }
       break;
     case DW_TAG_class_type:
     case DW_TAG_interface_type:
@@ -8288,27 +8398,37 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
       /* NOTE: carlton/2003-10-07: See comment in new_symbol about
         static vs. global.  */
-      add_psymbol_to_list (actual_name,
-                          built_actual_name != NULL,
-                          STRUCT_DOMAIN, LOC_TYPEDEF, -1,
-                          cu->language == language_cplus
-                          ? psymbol_placement::GLOBAL
-                          : psymbol_placement::STATIC,
-                          0, cu->language, objfile);
-
+      psymbol.domain = STRUCT_DOMAIN;
+      psymbol.aclass = LOC_TYPEDEF;
+      where = (cu->language == language_cplus
+              ? psymbol_placement::GLOBAL
+              : psymbol_placement::STATIC);
       break;
     case DW_TAG_enumerator:
-      add_psymbol_to_list (actual_name,
-                          built_actual_name != NULL,
-                          VAR_DOMAIN, LOC_CONST, -1,
-                          cu->language == language_cplus
-                          ? psymbol_placement::GLOBAL
-                          : psymbol_placement::STATIC,
-                          0, cu->language, objfile);
+      psymbol.domain = VAR_DOMAIN;
+      psymbol.aclass = LOC_CONST;
+      where = (cu->language == language_cplus
+              ? psymbol_placement::GLOBAL
+              : psymbol_placement::STATIC);
       break;
     default:
       break;
     }
+
+  if (where.has_value ())
+    {
+      if (built_actual_name != nullptr)
+       actual_name = objfile->intern (actual_name);
+      if (pdi->linkage_name == nullptr || cu->language == language_ada)
+       psymbol.ginfo.set_linkage_name (actual_name);
+      else
+       {
+         psymbol.ginfo.set_demangled_name (actual_name,
+                                           &objfile->objfile_obstack);
+         psymbol.ginfo.set_linkage_name (pdi->linkage_name);
+       }
+      add_psymbol_to_list (psymbol, *where, objfile);
+    }
 }
 
 /* Read a partial die corresponding to a namespace; also, add a symbol
@@ -8374,7 +8494,7 @@ add_partial_subprogram (struct partial_die_info *pdi,
          if (set_addrmap)
            {
              struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-             struct gdbarch *gdbarch = get_objfile_arch (objfile);
+             struct gdbarch *gdbarch = objfile->arch ();
              CORE_ADDR baseaddr;
              CORE_ADDR this_highpc;
              CORE_ADDR this_lowpc;
@@ -8836,8 +8956,7 @@ process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile)
 void
 dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
 {
-  if (readin)
-    return;
+  gdb_assert (!readin);
 
   expand_dependencies (objfile);
 
@@ -9053,7 +9172,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
                                     saved_package_name);
       struct symbol *sym;
 
-      sym = allocate_symbol (objfile);
+      sym = new (&objfile->objfile_obstack) symbol;
       sym->set_language (language_go, &objfile->objfile_obstack);
       sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
       /* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
@@ -9075,37 +9194,72 @@ rust_fully_qualify (struct obstack *obstack, const char *p1, const char *p2)
   return obconcat (obstack, p1, "::", p2, (char *) NULL);
 }
 
-/* A helper that allocates a struct discriminant_info to attach to a
-   union type.  */
+/* A helper that allocates a variant part to attach to a Rust enum
+   type.  OBSTACK is where the results should be allocated.  TYPE is
+   the type we're processing.  DISCRIMINANT_INDEX is the index of the
+   discriminant.  It must be the index of one of the fields of TYPE.
+   DEFAULT_INDEX is the index of the default field; or -1 if there is
+   no default.  RANGES is indexed by "effective" field number (the
+   field index, but omitting the discriminant and default fields) and
+   must hold the discriminant values used by the variants.  Note that
+   RANGES must have a lifetime at least as long as OBSTACK -- either
+   already allocated on it, or static.  */
 
-static struct discriminant_info *
-alloc_discriminant_info (struct type *type, int discriminant_index,
-                        int default_index)
-{
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
-  gdb_assert (discriminant_index == -1
-             || (discriminant_index >= 0
-                 && discriminant_index < TYPE_NFIELDS (type)));
+static void
+alloc_rust_variant (struct obstack *obstack, struct type *type,
+                   int discriminant_index, int default_index,
+                   gdb::array_view<discriminant_range> ranges)
+{
+  /* When DISCRIMINANT_INDEX == -1, we have a univariant enum.  Those
+     must be handled by the caller.  */
+  gdb_assert (discriminant_index >= 0
+             && discriminant_index < TYPE_NFIELDS (type));
   gdb_assert (default_index == -1
              || (default_index >= 0 && default_index < TYPE_NFIELDS (type)));
 
-  TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+  /* We have one variant for each non-discriminant field.  */
+  int n_variants = TYPE_NFIELDS (type) - 1;
+
+  variant *variants = new (obstack) variant[n_variants];
+  int var_idx = 0;
+  int range_idx = 0;
+  for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+    {
+      if (i == discriminant_index)
+       continue;
 
-  struct discriminant_info *disc
-    = ((struct discriminant_info *)
-       TYPE_ZALLOC (type,
-                   offsetof (struct discriminant_info, discriminants)
-                   + TYPE_NFIELDS (type) * sizeof (disc->discriminants[0])));
-  disc->default_index = default_index;
-  disc->discriminant_index = discriminant_index;
+      variants[var_idx].first_field = i;
+      variants[var_idx].last_field = i + 1;
 
-  struct dynamic_prop prop;
-  prop.kind = PROP_UNDEFINED;
-  prop.data.baton = disc;
+      /* The default field does not need a range, but other fields do.
+        We skipped the discriminant above.  */
+      if (i != default_index)
+       {
+         variants[var_idx].discriminants = ranges.slice (range_idx, 1);
+         ++range_idx;
+       }
+
+      ++var_idx;
+    }
 
-  add_dyn_prop (DYN_PROP_DISCRIMINATED, prop, type);
+  gdb_assert (range_idx == ranges.size ());
+  gdb_assert (var_idx == n_variants);
 
-  return disc;
+  variant_part *part = new (obstack) variant_part;
+  part->discriminant_index = discriminant_index;
+  part->is_unsigned = TYPE_UNSIGNED (TYPE_FIELD_TYPE (type,
+                                                     discriminant_index));
+  part->variants = gdb::array_view<variant> (variants, n_variants);
+
+  void *storage = obstack_alloc (obstack, sizeof (gdb::array_view<variant_part>));
+  gdb::array_view<variant_part> *prop_value
+    = new (storage) gdb::array_view<variant_part> (part, 1);
+
+  struct dynamic_prop prop;
+  prop.kind = PROP_VARIANT_PARTS;
+  prop.data.variant_parts = prop_value;
+
+  type->add_dyn_prop (DYN_PROP_VARIANT_PARTS, prop);
 }
 
 /* Some versions of rustc emitted enums in an unusual way.
@@ -9131,7 +9285,7 @@ alloc_discriminant_info (struct type *type, int discriminant_index,
 static void
 quirk_rust_enum (struct type *type, struct objfile *objfile)
 {
-  gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+  gdb_assert (type->code () == TYPE_CODE_UNION);
 
   /* We don't need to deal with empty enums.  */
   if (TYPE_NFIELDS (type) == 0)
@@ -9169,55 +9323,44 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
          field_type = TYPE_FIELD_TYPE (field_type, index);
        }
 
-      /* Make a union to hold the variants.  */
-      struct type *union_type = alloc_type (objfile);
-      TYPE_CODE (union_type) = TYPE_CODE_UNION;
-      TYPE_NFIELDS (union_type) = 3;
-      TYPE_FIELDS (union_type)
+      /* Smash this type to be a structure type.  We have to do this
+        because the type has already been recorded.  */
+      type->set_code (TYPE_CODE_STRUCT);
+      TYPE_NFIELDS (type) = 3;
+      /* Save the field we care about.  */
+      struct field saved_field = TYPE_FIELD (type, 0);
+      TYPE_FIELDS (type)
        = (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
-      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
-      set_type_align (union_type, TYPE_RAW_ALIGN (type));
 
-      /* Put the discriminant must at index 0.  */
-      TYPE_FIELD_TYPE (union_type, 0) = field_type;
-      TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
-      TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
-      SET_FIELD_BITPOS (TYPE_FIELD (union_type, 0), bit_offset);
+      /* Put the discriminant at index 0.  */
+      TYPE_FIELD_TYPE (type, 0) = field_type;
+      TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
+      TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
+      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), bit_offset);
 
       /* The order of fields doesn't really matter, so put the real
         field at index 1 and the data-less field at index 2.  */
-      struct discriminant_info *disc
-       = alloc_discriminant_info (union_type, 0, 1);
-      TYPE_FIELD (union_type, 1) = TYPE_FIELD (type, 0);
-      TYPE_FIELD_NAME (union_type, 1)
-       = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1)));
-      TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1))
-       = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
-                             TYPE_FIELD_NAME (union_type, 1));
+      TYPE_FIELD (type, 1) = saved_field;
+      TYPE_FIELD_NAME (type, 1)
+       = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 1)));
+      TYPE_FIELD_TYPE (type, 1)->set_name
+       (rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+                            TYPE_FIELD_NAME (type, 1)));
 
       const char *dataless_name
        = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
                              name);
       struct type *dataless_type = init_type (objfile, TYPE_CODE_VOID, 0,
                                              dataless_name);
-      TYPE_FIELD_TYPE (union_type, 2) = dataless_type;
+      TYPE_FIELD_TYPE (type, 2) = dataless_type;
       /* NAME points into the original discriminant name, which
         already has the correct lifetime.  */
-      TYPE_FIELD_NAME (union_type, 2) = name;
-      SET_FIELD_BITPOS (TYPE_FIELD (union_type, 2), 0);
-      disc->discriminants[2] = 0;
+      TYPE_FIELD_NAME (type, 2) = name;
+      SET_FIELD_BITPOS (TYPE_FIELD (type, 2), 0);
 
-      /* Smash this type to be a structure type.  We have to do this
-        because the type has already been recorded.  */
-      TYPE_CODE (type) = TYPE_CODE_STRUCT;
-      TYPE_NFIELDS (type) = 1;
-      TYPE_FIELDS (type)
-       = (struct field *) TYPE_ZALLOC (type, sizeof (struct field));
-
-      /* Install the variant part.  */
-      TYPE_FIELD_TYPE (type, 0) = union_type;
-      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
-      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+      /* Indicate that this is a variant type.  */
+      static discriminant_range ranges[1] = { { 0, 0 } };
+      alloc_rust_variant (&objfile->objfile_obstack, type, 0, 1, ranges);
     }
   /* A union with a single anonymous field is probably an old-style
      univariant enum.  */
@@ -9225,33 +9368,15 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
     {
       /* Smash this type to be a structure type.  We have to do this
         because the type has already been recorded.  */
-      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      type->set_code (TYPE_CODE_STRUCT);
 
-      /* Make a union to hold the variants.  */
-      struct type *union_type = alloc_type (objfile);
-      TYPE_CODE (union_type) = TYPE_CODE_UNION;
-      TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
-      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
-      set_type_align (union_type, TYPE_RAW_ALIGN (type));
-      TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
-
-      struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
+      struct type *field_type = TYPE_FIELD_TYPE (type, 0);
       const char *variant_name
        = rust_last_path_segment (TYPE_NAME (field_type));
-      TYPE_FIELD_NAME (union_type, 0) = variant_name;
-      TYPE_NAME (field_type)
-       = rust_fully_qualify (&objfile->objfile_obstack,
-                             TYPE_NAME (type), variant_name);
-
-      /* Install the union in the outer struct type.  */
-      TYPE_NFIELDS (type) = 1;
-      TYPE_FIELDS (type)
-       = (struct field *) TYPE_ZALLOC (union_type, sizeof (struct field));
-      TYPE_FIELD_TYPE (type, 0) = union_type;
-      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
-      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
-
-      alloc_discriminant_info (union_type, -1, 0);
+      TYPE_FIELD_NAME (type, 0) = variant_name;
+      field_type->set_name
+       (rust_fully_qualify (&objfile->objfile_obstack,
+                            TYPE_NAME (type), variant_name));
     }
   else
     {
@@ -9260,7 +9385,7 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
        {
          disr_type = TYPE_FIELD_TYPE (type, i);
 
-         if (TYPE_CODE (disr_type) != TYPE_CODE_STRUCT)
+         if (disr_type->code () != TYPE_CODE_STRUCT)
            {
              /* All fields of a true enum will be structs.  */
              return;
@@ -9290,35 +9415,22 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
 
       /* Smash this type to be a structure type.  We have to do this
         because the type has already been recorded.  */
-      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      type->set_code (TYPE_CODE_STRUCT);
 
-      /* Make a union to hold the variants.  */
+      /* Make space for the discriminant field.  */
       struct field *disr_field = &TYPE_FIELD (disr_type, 0);
-      struct type *union_type = alloc_type (objfile);
-      TYPE_CODE (union_type) = TYPE_CODE_UNION;
-      TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
-      TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
-      set_type_align (union_type, TYPE_RAW_ALIGN (type));
-      TYPE_FIELDS (union_type)
-       = (struct field *) TYPE_ZALLOC (union_type,
-                                       (TYPE_NFIELDS (union_type)
-                                        * sizeof (struct field)));
-
-      memcpy (TYPE_FIELDS (union_type) + 1, TYPE_FIELDS (type),
+      field *new_fields
+       = (struct field *) TYPE_ZALLOC (type, (TYPE_NFIELDS (type)
+                                              * sizeof (struct field)));
+      memcpy (new_fields + 1, TYPE_FIELDS (type),
              TYPE_NFIELDS (type) * sizeof (struct field));
+      TYPE_FIELDS (type) = new_fields;
+      TYPE_NFIELDS (type) = TYPE_NFIELDS (type) + 1;
 
       /* Install the discriminant at index 0 in the union.  */
-      TYPE_FIELD (union_type, 0) = *disr_field;
-      TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
-      TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
-
-      /* Install the union in the outer struct type.  */
-      TYPE_FIELD_TYPE (type, 0) = union_type;
-      TYPE_FIELD_NAME (type, 0) = "<<variants>>";
-      TYPE_NFIELDS (type) = 1;
-
-      /* Set the size and offset of the union type.  */
-      SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+      TYPE_FIELD (type, 0) = *disr_field;
+      TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
+      TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
 
       /* We need a way to find the correct discriminant given a
         variant name.  For convenience we build a map here.  */
@@ -9334,9 +9446,13 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
            }
        }
 
-      int n_fields = TYPE_NFIELDS (union_type);
-      struct discriminant_info *disc
-       = alloc_discriminant_info (union_type, 0, -1);
+      int n_fields = TYPE_NFIELDS (type);
+      /* We don't need a range entry for the discriminant, but we do
+        need one for every other field, as there is no default
+        variant.  */
+      discriminant_range *ranges = XOBNEWVEC (&objfile->objfile_obstack,
+                                             discriminant_range,
+                                             n_fields - 1);
       /* Skip the discriminant here.  */
       for (int i = 1; i < n_fields; ++i)
        {
@@ -9344,25 +9460,32 @@ quirk_rust_enum (struct type *type, struct objfile *objfile)
             That name can be used to look up the correct
             discriminant.  */
          const char *variant_name
-           = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type,
-                                                                 i)));
+           = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, i)));
 
          auto iter = discriminant_map.find (variant_name);
          if (iter != discriminant_map.end ())
-           disc->discriminants[i] = iter->second;
+           {
+             ranges[i].low = iter->second;
+             ranges[i].high = iter->second;
+           }
 
          /* Remove the discriminant field, if it exists.  */
-         struct type *sub_type = TYPE_FIELD_TYPE (union_type, i);
+         struct type *sub_type = TYPE_FIELD_TYPE (type, i);
          if (TYPE_NFIELDS (sub_type) > 0)
            {
              --TYPE_NFIELDS (sub_type);
              ++TYPE_FIELDS (sub_type);
            }
-         TYPE_FIELD_NAME (union_type, i) = variant_name;
-         TYPE_NAME (sub_type)
-           rust_fully_qualify (&objfile->objfile_obstack,
-                                 TYPE_NAME (type), variant_name);
+         TYPE_FIELD_NAME (type, i) = variant_name;
+         sub_type->set_name
+           (rust_fully_qualify (&objfile->objfile_obstack,
+                                TYPE_NAME (type), variant_name));
        }
+
+      /* Indicate that this is a variant type.  */
+      alloc_rust_variant (&objfile->objfile_obstack, type, 0, 1,
+                         gdb::array_view<discriminant_range> (ranges,
+                                                              n_fields - 1));
     }
 }
 
@@ -9511,7 +9634,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
   struct dwarf2_cu *cu = per_cu->cu;
   struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR lowpc, highpc;
   struct compunit_symtab *cust;
   CORE_ADDR baseaddr;
@@ -9956,6 +10079,12 @@ dw2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
   if (linkage_name == NULL)
     linkage_name = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu);
 
+  /* rustc emits invalid values for DW_AT_linkage_name.  Ignore these.
+     See https://github.com/rust-lang/rust/issues/32925.  */
+  if (cu->language == language_rust && linkage_name != NULL
+      && strchr (linkage_name, '{') != NULL)
+    linkage_name = NULL;
+
   return linkage_name;
 }
 
@@ -10170,7 +10299,7 @@ dwarf2_compute_name (const char *name,
                     the two cases.  */
                  if (TYPE_NFIELDS (type) > 0
                      && TYPE_FIELD_ARTIFICIAL (type, 0)
-                     && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
+                     && TYPE_FIELD_TYPE (type, 0)->code () == TYPE_CODE_PTR
                      && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
                                                                        0))))
                    buf.puts (" const");
@@ -10230,13 +10359,8 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
   if (!die_needs_namespace (die, cu))
     return dwarf2_compute_name (name, die, cu, 1);
 
-  mangled = dw2_linkage_name (die, cu);
-
-  /* rustc emits invalid values for DW_AT_linkage_name.  Ignore these.
-     See https://github.com/rust-lang/rust/issues/32925.  */
-  if (cu->language == language_rust && mangled != NULL
-      && strchr (mangled, '{') != NULL)
-    mangled = NULL;
+  if (cu->language != language_rust)
+    mangled = dw2_linkage_name (die, cu);
 
   /* DW_AT_linkage_name is missing in some cases - depend on what GDB
      has computed.  */
@@ -10359,7 +10483,7 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
          sect_offset sect_off = attr->get_ref_die_offset ();
 
          type = get_die_type_at_offset (sect_off, cu->per_cu);
-         if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+         if (type != NULL && type->code () == TYPE_CODE_NAMESPACE)
            {
              /* This declaration is a global namespace alias.  Add
                 a symbol for it whose type is the aliased namespace.  */
@@ -10716,7 +10840,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
@@ -10838,6 +10962,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
                            COMPUNIT_DIRNAME (cust),
                            compunit_language (cust),
                            0, cust));
+         list_in_scope = get_builder ()->get_file_symbols ();
        }
       return;
     }
@@ -10889,6 +11014,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
                        COMPUNIT_DIRNAME (cust),
                        compunit_language (cust),
                        0, cust));
+      list_in_scope = get_builder ()->get_file_symbols ();
 
       auto &file_names = line_header->file_names ();
       for (i = 0; i < file_names.size (); ++i)
@@ -12795,7 +12921,7 @@ static void
 read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct context_stack *newobj;
   CORE_ADDR lowpc;
   CORE_ADDR highpc;
@@ -12857,7 +12983,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
       if (child_die->tag == DW_TAG_template_type_param
          || child_die->tag == DW_TAG_template_value_param)
        {
-         templ_func = allocate_template_symbol (objfile);
+         templ_func = new (&objfile->objfile_obstack) template_symbol;
          templ_func->subclass = SYMBOL_TEMPLATE;
          break;
        }
@@ -12996,7 +13122,7 @@ static void
 read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR lowpc, highpc;
   struct die_info *child_die;
   CORE_ADDR baseaddr;
@@ -13017,7 +13143,16 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       for (child_die = die->child;
           child_die != NULL && child_die->tag;
           child_die = child_die->sibling)
-       process_die (child_die, cu);
+       {
+         /* We might already be processing this DIE.  This can happen
+            in an unusual circumstance -- where a subroutine A
+            appears lexically in another subroutine B, but A actually
+            inlines B.  The recursion is broken here, rather than in
+            inherit_abstract_dies, because it seems better to simply
+            drop concrete children here.  */
+         if (!child_die->in_process)
+           process_die (child_die, cu);
+       }
       return;
     case PC_BOUNDS_INVALID:
       return;
@@ -13067,7 +13202,7 @@ static void
 read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   CORE_ADDR pc, baseaddr;
   struct attribute *attr;
   struct call_site *call_site, call_site_local;
@@ -13173,7 +13308,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
            func_type = get_die_type (func_die, cu);
          if (func_type != NULL)
            {
-             gdb_assert (TYPE_CODE (func_type) == TYPE_CODE_FUNC);
+             gdb_assert (func_type->code () == TYPE_CODE_FUNC);
 
              /* Enlist this call site to the function.  */
              call_site->tail_call_next = TYPE_TAIL_CALL_LIST (func_type);
@@ -13411,8 +13546,7 @@ read_variable (struct die_info *die, struct dwarf2_cu *cu)
        {
          struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
 
-         storage = new (&objfile->objfile_obstack) rust_vtable_symbol ();
-         initialize_objfile_symbol (storage);
+         storage = new (&objfile->objfile_obstack) rust_vtable_symbol;
          storage->concrete_type = containing_type;
          storage->subclass = SYMBOL_RUST_VTABLE;
        }
@@ -13712,7 +13846,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
                    dwarf2_psymtab *ranges_pst)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   const CORE_ADDR baseaddr = objfile->text_section_offset ();
   int low_set = 0;
   CORE_ADDR low = 0;
@@ -13956,7 +14090,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
                             CORE_ADDR baseaddr, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct attribute *attr;
   struct attribute *attr_high;
 
@@ -14137,6 +14271,53 @@ handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
   return 0;
 }
 
+/* Look for DW_AT_data_member_location and store the results in FIELD.  */
+
+static void
+handle_data_member_location (struct die_info *die, struct dwarf2_cu *cu,
+                            struct field *field)
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
+  if (attr != NULL)
+    {
+      if (attr->form_is_constant ())
+       {
+         LONGEST offset = attr->constant_value (0);
+         SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+       }
+      else if (attr->form_is_section_offset ())
+       dwarf2_complex_location_expr_complaint ();
+      else if (attr->form_is_block ())
+       {
+         bool handled;
+         CORE_ADDR offset = decode_locdesc (DW_BLOCK (attr), cu, &handled);
+         if (handled)
+           SET_FIELD_BITPOS (*field, offset * bits_per_byte);
+         else
+           {
+             struct objfile *objfile
+               = cu->per_cu->dwarf2_per_objfile->objfile;
+             struct dwarf2_locexpr_baton *dlbaton
+               = XOBNEW (&objfile->objfile_obstack,
+                         struct dwarf2_locexpr_baton);
+             dlbaton->data = DW_BLOCK (attr)->data;
+             dlbaton->size = DW_BLOCK (attr)->size;
+             /* When using this baton, we want to compute the address
+                of the field, not the value.  This is why
+                is_reference is set to false here.  */
+             dlbaton->is_reference = false;
+             dlbaton->per_cu = cu->per_cu;
+
+             SET_FIELD_DWARF_BLOCK (*field, dlbaton);
+           }
+       }
+      else
+       dwarf2_complex_location_expr_complaint ();
+    }
+}
+
 /* Add an aggregate field to the field list.  */
 
 static void
@@ -14144,7 +14325,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
                  struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct nextfield *new_field;
   struct attribute *attr;
   struct field *fp;
@@ -14161,6 +14342,8 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
       new_field = &fip->fields.back ();
     }
 
+  new_field->offset = die->sect_off;
+
   attr = dwarf2_attr (die, DW_AT_accessibility, cu);
   if (attr != nullptr)
     new_field->accessibility = DW_UNSND (attr);
@@ -14179,8 +14362,6 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
     {
-      LONGEST offset;
-
       /* Data member other than a C++ static data member.  */
 
       /* Get type of field.  */
@@ -14200,8 +14381,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
        }
 
       /* Get bit offset of field.  */
-      if (handle_data_member_location (die, cu, &offset))
-       SET_FIELD_BITPOS (*fp, offset * bits_per_byte);
+      handle_data_member_location (die, cu, fp);
       attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
       if (attr != nullptr)
        {
@@ -14310,44 +14490,12 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
     }
   else if (die->tag == DW_TAG_inheritance)
     {
-      LONGEST offset;
-
       /* C++ base class field.  */
-      if (handle_data_member_location (die, cu, &offset))
-       SET_FIELD_BITPOS (*fp, offset * bits_per_byte);
+      handle_data_member_location (die, cu, fp);
       FIELD_BITSIZE (*fp) = 0;
       FIELD_TYPE (*fp) = die_type (die, cu);
       FIELD_NAME (*fp) = TYPE_NAME (fp->type);
     }
-  else if (die->tag == DW_TAG_variant_part)
-    {
-      /* process_structure_scope will treat this DIE as a union.  */
-      process_structure_scope (die, cu);
-
-      /* The variant part is relative to the start of the enclosing
-        structure.  */
-      SET_FIELD_BITPOS (*fp, 0);
-      fp->type = get_die_type (die, cu);
-      fp->artificial = 1;
-      fp->name = "<<variant>>";
-
-      /* Normally a DW_TAG_variant_part won't have a size, but our
-        representation requires one, so set it to the maximum of the
-        child sizes, being sure to account for the offset at which
-        each child is seen.  */
-      if (TYPE_LENGTH (fp->type) == 0)
-       {
-         unsigned max = 0;
-         for (int i = 0; i < TYPE_NFIELDS (fp->type); ++i)
-           {
-             unsigned len = ((TYPE_FIELD_BITPOS (fp->type, i) + 7) / 8
-                             + TYPE_LENGTH (TYPE_FIELD_TYPE (fp->type, i)));
-             if (len > max)
-               max = len;
-           }
-         TYPE_LENGTH (fp->type) = max;
-       }
-    }
   else
     gdb_assert_not_reached ("missing case in dwarf2_add_field");
 }
@@ -14414,6 +14562,202 @@ dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
     fip->nested_types_list.push_back (fp);
 }
 
+/* A convenience typedef that's used when finding the discriminant
+   field for a variant part.  */
+typedef std::unordered_map<sect_offset, int, gdb::hash_enum<sect_offset>>
+  offset_map_type;
+
+/* Compute the discriminant range for a given variant.  OBSTACK is
+   where the results will be stored.  VARIANT is the variant to
+   process.  IS_UNSIGNED indicates whether the discriminant is signed
+   or unsigned.  */
+
+static const gdb::array_view<discriminant_range>
+convert_variant_range (struct obstack *obstack, const variant_field &variant,
+                      bool is_unsigned)
+{
+  std::vector<discriminant_range> ranges;
+
+  if (variant.default_branch)
+    return {};
+
+  if (variant.discr_list_data == nullptr)
+    {
+      discriminant_range r
+       = {variant.discriminant_value, variant.discriminant_value};
+      ranges.push_back (r);
+    }
+  else
+    {
+      gdb::array_view<const gdb_byte> data (variant.discr_list_data->data,
+                                           variant.discr_list_data->size);
+      while (!data.empty ())
+       {
+         if (data[0] != DW_DSC_range && data[0] != DW_DSC_label)
+           {
+             complaint (_("invalid discriminant marker: %d"), data[0]);
+             break;
+           }
+         bool is_range = data[0] == DW_DSC_range;
+         data = data.slice (1);
+
+         ULONGEST low, high;
+         unsigned int bytes_read;
+
+         if (data.empty ())
+           {
+             complaint (_("DW_AT_discr_list missing low value"));
+             break;
+           }
+         if (is_unsigned)
+           low = read_unsigned_leb128 (nullptr, data.data (), &bytes_read);
+         else
+           low = (ULONGEST) read_signed_leb128 (nullptr, data.data (),
+                                                &bytes_read);
+         data = data.slice (bytes_read);
+
+         if (is_range)
+           {
+             if (data.empty ())
+               {
+                 complaint (_("DW_AT_discr_list missing high value"));
+                 break;
+               }
+             if (is_unsigned)
+               high = read_unsigned_leb128 (nullptr, data.data (),
+                                            &bytes_read);
+             else
+               high = (LONGEST) read_signed_leb128 (nullptr, data.data (),
+                                                    &bytes_read);
+             data = data.slice (bytes_read);
+           }
+         else
+           high = low;
+
+         ranges.push_back ({ low, high });
+       }
+    }
+
+  discriminant_range *result = XOBNEWVEC (obstack, discriminant_range,
+                                         ranges.size ());
+  std::copy (ranges.begin (), ranges.end (), result);
+  return gdb::array_view<discriminant_range> (result, ranges.size ());
+}
+
+static const gdb::array_view<variant_part> create_variant_parts
+  (struct obstack *obstack,
+   const offset_map_type &offset_map,
+   struct field_info *fi,
+   const std::vector<variant_part_builder> &variant_parts);
+
+/* Fill in a "struct variant" for a given variant field.  RESULT is
+   the variant to fill in.  OBSTACK is where any needed allocations
+   will be done.  OFFSET_MAP holds the mapping from section offsets to
+   fields for the type.  FI describes the fields of the type we're
+   processing.  FIELD is the variant field we're converting.  */
+
+static void
+create_one_variant (variant &result, struct obstack *obstack,
+                   const offset_map_type &offset_map,
+                   struct field_info *fi, const variant_field &field)
+{
+  result.discriminants = convert_variant_range (obstack, field, false);
+  result.first_field = field.first_field + fi->baseclasses.size ();
+  result.last_field = field.last_field + fi->baseclasses.size ();
+  result.parts = create_variant_parts (obstack, offset_map, fi,
+                                      field.variant_parts);
+}
+
+/* Fill in a "struct variant_part" for a given variant part.  RESULT
+   is the variant part to fill in.  OBSTACK is where any needed
+   allocations will be done.  OFFSET_MAP holds the mapping from
+   section offsets to fields for the type.  FI describes the fields of
+   the type we're processing.  BUILDER is the variant part to be
+   converted.  */
+
+static void
+create_one_variant_part (variant_part &result,
+                        struct obstack *obstack,
+                        const offset_map_type &offset_map,
+                        struct field_info *fi,
+                        const variant_part_builder &builder)
+{
+  auto iter = offset_map.find (builder.discriminant_offset);
+  if (iter == offset_map.end ())
+    {
+      result.discriminant_index = -1;
+      /* Doesn't matter.  */
+      result.is_unsigned = false;
+    }
+  else
+    {
+      result.discriminant_index = iter->second;
+      result.is_unsigned
+       = TYPE_UNSIGNED (FIELD_TYPE
+                        (fi->fields[result.discriminant_index].field));
+    }
+
+  size_t n = builder.variants.size ();
+  variant *output = new (obstack) variant[n];
+  for (size_t i = 0; i < n; ++i)
+    create_one_variant (output[i], obstack, offset_map, fi,
+                       builder.variants[i]);
+
+  result.variants = gdb::array_view<variant> (output, n);
+}
+
+/* Create a vector of variant parts that can be attached to a type.
+   OBSTACK is where any needed allocations will be done.  OFFSET_MAP
+   holds the mapping from section offsets to fields for the type.  FI
+   describes the fields of the type we're processing.  VARIANT_PARTS
+   is the vector to convert.  */
+
+static const gdb::array_view<variant_part>
+create_variant_parts (struct obstack *obstack,
+                     const offset_map_type &offset_map,
+                     struct field_info *fi,
+                     const std::vector<variant_part_builder> &variant_parts)
+{
+  if (variant_parts.empty ())
+    return {};
+
+  size_t n = variant_parts.size ();
+  variant_part *result = new (obstack) variant_part[n];
+  for (size_t i = 0; i < n; ++i)
+    create_one_variant_part (result[i], obstack, offset_map, fi,
+                            variant_parts[i]);
+
+  return gdb::array_view<variant_part> (result, n);
+}
+
+/* Compute the variant part vector for FIP, attaching it to TYPE when
+   done.  */
+
+static void
+add_variant_property (struct field_info *fip, struct type *type,
+                     struct dwarf2_cu *cu)
+{
+  /* Map section offsets of fields to their field index.  Note the
+     field index here does not take the number of baseclasses into
+     account.  */
+  offset_map_type offset_map;
+  for (int i = 0; i < fip->fields.size (); ++i)
+    offset_map[fip->fields[i].offset] = i;
+
+  struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
+  gdb::array_view<variant_part> parts
+    = create_variant_parts (&objfile->objfile_obstack, offset_map, fip,
+                           fip->variant_parts);
+
+  struct dynamic_prop prop;
+  prop.kind = PROP_VARIANT_PARTS;
+  prop.data.variant_parts
+    = ((gdb::array_view<variant_part> *)
+       obstack_copy (&objfile->objfile_obstack, &parts, sizeof (parts)));
+
+  type->add_dyn_prop (DYN_PROP_VARIANT_PARTS, prop);
+}
+
 /* Create the vector of fields, and attach it to the type.  */
 
 static void
@@ -14459,22 +14803,8 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
       TYPE_N_BASECLASSES (type) = fip->baseclasses.size ();
     }
 
-  if (TYPE_FLAG_DISCRIMINATED_UNION (type))
-    {
-      struct discriminant_info *di = alloc_discriminant_info (type, -1, -1);
-
-      for (int index = 0; index < nfields; ++index)
-       {
-         struct nextfield &field = fip->fields[index];
-
-         if (field.variant.is_discriminant)
-           di->discriminant_index = index;
-         else if (field.variant.default_branch)
-           di->default_index = index;
-         else
-           di->discriminants[index] = field.variant.discriminant_value;
-       }
-    }
+  if (!fip->variant_parts.empty ())
+    add_variant_property (fip, type, cu);
 
   /* Copy the saved-up fields into the field vector.  */
   for (int i = 0; i < nfields; ++i)
@@ -14628,7 +14958,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
 
   fnp->type = alloc_type (objfile);
   this_type = read_type_die (die, cu);
-  if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC)
+  if (this_type && this_type->code () == TYPE_CODE_FUNC)
     {
       int nparams = TYPE_NFIELDS (this_type);
 
@@ -14826,7 +15156,7 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   struct type *pfn_type, *self_type, *new_type;
 
   /* Check for a structure with no name and two children.  */
-  if (TYPE_CODE (type) != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 2)
+  if (type->code () != TYPE_CODE_STRUCT || TYPE_NFIELDS (type) != 2)
     return;
 
   /* Check for __pfn and __delta members.  */
@@ -14839,15 +15169,15 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
   /* Find the type of the method.  */
   pfn_type = TYPE_FIELD_TYPE (type, 0);
   if (pfn_type == NULL
-      || TYPE_CODE (pfn_type) != TYPE_CODE_PTR
-      || TYPE_CODE (TYPE_TARGET_TYPE (pfn_type)) != TYPE_CODE_FUNC)
+      || pfn_type->code () != TYPE_CODE_PTR
+      || TYPE_TARGET_TYPE (pfn_type)->code () != TYPE_CODE_FUNC)
     return;
 
   /* Look for the "this" argument.  */
   pfn_type = TYPE_TARGET_TYPE (pfn_type);
   if (TYPE_NFIELDS (pfn_type) == 0
       /* || TYPE_FIELD_TYPE (pfn_type, 0) == NULL */
-      || TYPE_CODE (TYPE_FIELD_TYPE (pfn_type, 0)) != TYPE_CODE_PTR)
+      || TYPE_FIELD_TYPE (pfn_type, 0)->code () != TYPE_CODE_PTR)
     return;
 
   self_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0));
@@ -15026,32 +15356,27 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
          if (get_die_type (die, cu) != NULL)
            return get_die_type (die, cu);
 
-         TYPE_NAME (type) = full_name;
+         type->set_name (full_name);
        }
       else
        {
          /* The name is already allocated along with this objfile, so
             we don't need to duplicate it for the type.  */
-         TYPE_NAME (type) = name;
+         type->set_name (name);
        }
     }
 
   if (die->tag == DW_TAG_structure_type)
     {
-      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      type->set_code (TYPE_CODE_STRUCT);
     }
   else if (die->tag == DW_TAG_union_type)
     {
-      TYPE_CODE (type) = TYPE_CODE_UNION;
-    }
-  else if (die->tag == DW_TAG_variant_part)
-    {
-      TYPE_CODE (type) = TYPE_CODE_UNION;
-      TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+      type->set_code (TYPE_CODE_UNION);
     }
   else
     {
-      TYPE_CODE (type) = TYPE_CODE_STRUCT;
+      type->set_code (TYPE_CODE_STRUCT);
     }
 
   if (cu->language == language_cplus && die->tag == DW_TAG_class_type)
@@ -15076,14 +15401,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
         TYPE_LENGTH (type) = DW_UNSND (attr);
       else
        {
-         /* For the moment, dynamic type sizes are not supported
-            by GDB's struct type.  The actual size is determined
-            on-demand when resolving the type of a given object,
-            so set the type's length to zero for now.  Otherwise,
-            we record an expression as the length, and that expression
-            could lead to a very large value, which could eventually
-            lead to us trying to allocate that much memory when creating
-            a value of that type.  */
+         struct dynamic_prop prop;
+         if (attr_to_dynamic_prop (attr, die, cu, &prop,
+                                   cu->per_cu->addr_type ()))
+           type->add_dyn_prop (DYN_PROP_BYTE_SIZE, prop);
           TYPE_LENGTH (type) = 0;
        }
     }
@@ -15122,6 +15443,130 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
   return type;
 }
 
+static void handle_struct_member_die
+  (struct die_info *child_die,
+   struct type *type,
+   struct field_info *fi,
+   std::vector<struct symbol *> *template_args,
+   struct dwarf2_cu *cu);
+
+/* A helper for handle_struct_member_die that handles
+   DW_TAG_variant_part.  */
+
+static void
+handle_variant_part (struct die_info *die, struct type *type,
+                    struct field_info *fi,
+                    std::vector<struct symbol *> *template_args,
+                    struct dwarf2_cu *cu)
+{
+  variant_part_builder *new_part;
+  if (fi->current_variant_part == nullptr)
+    {
+      fi->variant_parts.emplace_back ();
+      new_part = &fi->variant_parts.back ();
+    }
+  else if (!fi->current_variant_part->processing_variant)
+    {
+      complaint (_("nested DW_TAG_variant_part seen "
+                  "- DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return;
+    }
+  else
+    {
+      variant_field &current = fi->current_variant_part->variants.back ();
+      current.variant_parts.emplace_back ();
+      new_part = &current.variant_parts.back ();
+    }
+
+  /* When we recurse, we want callees to add to this new variant
+     part.  */
+  scoped_restore save_current_variant_part
+    = make_scoped_restore (&fi->current_variant_part, new_part);
+
+  struct attribute *discr = dwarf2_attr (die, DW_AT_discr, cu);
+  if (discr == NULL)
+    {
+      /* It's a univariant form, an extension we support.  */
+    }
+  else if (discr->form_is_ref ())
+    {
+      struct dwarf2_cu *target_cu = cu;
+      struct die_info *target_die = follow_die_ref (die, discr, &target_cu);
+
+      new_part->discriminant_offset = target_die->sect_off;
+    }
+  else
+    {
+      complaint (_("DW_AT_discr does not have DIE reference form"
+                  " - DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+    }
+
+  for (die_info *child_die = die->child;
+       child_die != NULL;
+       child_die = child_die->sibling)
+    handle_struct_member_die (child_die, type, fi, template_args, cu);
+}
+
+/* A helper for handle_struct_member_die that handles
+   DW_TAG_variant.  */
+
+static void
+handle_variant (struct die_info *die, struct type *type,
+               struct field_info *fi,
+               std::vector<struct symbol *> *template_args,
+               struct dwarf2_cu *cu)
+{
+  if (fi->current_variant_part == nullptr)
+    {
+      complaint (_("saw DW_TAG_variant outside DW_TAG_variant_part "
+                  "- DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return;
+    }
+  if (fi->current_variant_part->processing_variant)
+    {
+      complaint (_("nested DW_TAG_variant seen "
+                  "- DIE at %s [in module %s]"),
+                sect_offset_str (die->sect_off),
+                objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+      return;
+    }
+
+  scoped_restore save_processing_variant
+    = make_scoped_restore (&fi->current_variant_part->processing_variant,
+                          true);
+
+  fi->current_variant_part->variants.emplace_back ();
+  variant_field &variant = fi->current_variant_part->variants.back ();
+  variant.first_field = fi->fields.size ();
+
+  /* In a variant we want to get the discriminant and also add a
+     field for our sole member child.  */
+  struct attribute *discr = dwarf2_attr (die, DW_AT_discr_value, cu);
+  if (discr == nullptr)
+    {
+      discr = dwarf2_attr (die, DW_AT_discr_list, cu);
+      if (discr == nullptr || DW_BLOCK (discr)->size == 0)
+       variant.default_branch = true;
+      else
+       variant.discr_list_data = DW_BLOCK (discr);
+    }
+  else
+    variant.discriminant_value = DW_UNSND (discr);
+
+  for (die_info *variant_child = die->child;
+       variant_child != NULL;
+       variant_child = variant_child->sibling)
+    handle_struct_member_die (variant_child, type, fi, template_args, cu);
+
+  variant.last_field = fi->fields.size ();
+}
+
 /* A helper for process_structure_scope that handles a single member
    DIE.  */
 
@@ -15132,8 +15577,7 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
                          struct dwarf2_cu *cu)
 {
   if (child_die->tag == DW_TAG_member
-      || child_die->tag == DW_TAG_variable
-      || child_die->tag == DW_TAG_variant_part)
+      || child_die->tag == DW_TAG_variable)
     {
       /* NOTE: carlton/2002-11-05: A C++ static data member
         should be a DW_TAG_member that is a declaration, but
@@ -15170,41 +15614,10 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
       if (arg != NULL)
        template_args->push_back (arg);
     }
+  else if (child_die->tag == DW_TAG_variant_part)
+    handle_variant_part (child_die, type, fi, template_args, cu);
   else if (child_die->tag == DW_TAG_variant)
-    {
-      /* In a variant we want to get the discriminant and also add a
-        field for our sole member child.  */
-      struct attribute *discr = dwarf2_attr (child_die, DW_AT_discr_value, cu);
-
-      for (die_info *variant_child = child_die->child;
-          variant_child != NULL;
-          variant_child = variant_child->sibling)
-       {
-         if (variant_child->tag == DW_TAG_member)
-           {
-             handle_struct_member_die (variant_child, type, fi,
-                                       template_args, cu);
-             /* Only handle the one.  */
-             break;
-           }
-       }
-
-      /* We don't handle this but we might as well report it if we see
-        it.  */
-      if (dwarf2_attr (child_die, DW_AT_discr_list, cu) != nullptr)
-         complaint (_("DW_AT_discr_list is not supported yet"
-                      " - DIE at %s [in module %s]"),
-                    sect_offset_str (child_die->sect_off),
-                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
-
-      /* The first field was just added, so we can stash the
-        discriminant there.  */
-      gdb_assert (!fi->fields.empty ());
-      if (discr == NULL)
-       fi->fields.back ().variant.default_branch = true;
-      else
-       fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
-    }
+    handle_variant (child_die, type, fi, template_args, cu);
 }
 
 /* Finish creating a structure or union type, including filling in
@@ -15221,39 +15634,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (type == NULL)
     type = read_structure_type (die, cu);
 
-  /* When reading a DW_TAG_variant_part, we need to notice when we
-     read the discriminant member, so we can record it later in the
-     discriminant_info.  */
-  bool is_variant_part = TYPE_FLAG_DISCRIMINATED_UNION (type);
-  sect_offset discr_offset {};
   bool has_template_parameters = false;
-
-  if (is_variant_part)
-    {
-      struct attribute *discr = dwarf2_attr (die, DW_AT_discr, cu);
-      if (discr == NULL)
-       {
-         /* Maybe it's a univariant form, an extension we support.
-            In this case arrange not to check the offset.  */
-         is_variant_part = false;
-       }
-      else if (discr->form_is_ref ())
-       {
-         struct dwarf2_cu *target_cu = cu;
-         struct die_info *target_die = follow_die_ref (die, discr, &target_cu);
-
-         discr_offset = target_die->sect_off;
-       }
-      else
-       {
-         complaint (_("DW_AT_discr does not have DIE reference form"
-                      " - DIE at %s [in module %s]"),
-                    sect_offset_str (die->sect_off),
-                    objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
-         is_variant_part = false;
-       }
-    }
-
   if (die->child != NULL && ! die_is_declaration (die, cu))
     {
       struct field_info fi;
@@ -15264,10 +15645,6 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
       while (child_die && child_die->tag)
        {
          handle_struct_member_die (child_die, type, &fi, &template_args, cu);
-
-         if (is_variant_part && discr_offset == child_die->sect_off)
-           fi.fields.back ().variant.is_discriminant = true;
-
          child_die = child_die->sibling;
        }
 
@@ -15423,7 +15800,8 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
      these DIEs are identified by the fact that they have no byte_size
      attribute, and a declaration attribute.  */
   if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
-      || !die_is_declaration (die, cu))
+      || !die_is_declaration (die, cu)
+      || dwarf2_attr (die, DW_AT_signature, cu) != NULL)
     {
       struct symbol *sym = new_symbol (die, type, cu);
 
@@ -15461,8 +15839,9 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Assuming DIE is an enumeration type, and TYPE is its associated type,
-   update TYPE using some information only available in DIE's children.  */
+/* Assuming DIE is an enumeration type, and TYPE is its associated
+   type, update TYPE using some information only available in DIE's
+   children.  In particular, the fields are computed.  */
 
 static void
 update_enumeration_type_from_children (struct die_info *die,
@@ -15474,6 +15853,7 @@ update_enumeration_type_from_children (struct die_info *die,
   int flag_enum = 1;
 
   auto_obstack obstack;
+  std::vector<struct field> fields;
 
   for (child_die = die->child;
        child_die != NULL && child_die->tag;
@@ -15509,10 +15889,19 @@ update_enumeration_type_from_children (struct die_info *die,
            flag_enum = 0;
        }
 
-      /* If we already know that the enum type is neither unsigned, nor
-        a flag type, no need to look at the rest of the enumerates.  */
-      if (!unsigned_enum && !flag_enum)
-       break;
+      fields.emplace_back ();
+      struct field &field = fields.back ();
+      FIELD_NAME (field) = dwarf2_physname (name, child_die, cu);
+      SET_FIELD_ENUMVAL (field, value);
+    }
+
+  if (!fields.empty ())
+    {
+      TYPE_NFIELDS (type) = fields.size ();
+      TYPE_FIELDS (type) = (struct field *)
+       TYPE_ALLOC (type, sizeof (struct field) * fields.size ());
+      memcpy (TYPE_FIELDS (type), fields.data (),
+             sizeof (struct field) * fields.size ());
     }
 
   if (unsigned_enum)
@@ -15547,10 +15936,10 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
 
   type = alloc_type (objfile);
 
-  TYPE_CODE (type) = TYPE_CODE_ENUM;
+  type->set_code (TYPE_CODE_ENUM);
   name = dwarf2_full_name (NULL, die, cu);
   if (name != NULL)
-    TYPE_NAME (type) = name;
+    type->set_name (name);
 
   attr = dwarf2_attr (die, DW_AT_type, cu);
   if (attr != NULL)
@@ -15580,11 +15969,6 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   if (die_is_declaration (die, cu))
     TYPE_STUB (type) = 1;
 
-  /* Finish the creation of this type by using the enum's children.
-     We must call this even when the underlying type has been provided
-     so that we can determine if we're looking at a "flag" enum.  */
-  update_enumeration_type_from_children (die, type, cu);
-
   /* If this type has an underlying type that is not a stub, then we
      may use its attributes.  We always use the "unsigned" attribute
      in this situation, because ordinarily we guess whether the type
@@ -15606,7 +15990,15 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
 
   TYPE_DECLARED_CLASS (type) = dwarf2_flag_true_p (die, DW_AT_enum_class, cu);
 
-  return set_die_type (die, type, cu);
+  set_die_type (die, type, cu);
+
+  /* Finish the creation of this type by using the enum's children.
+     Note that, as usual, this must come after set_die_type to avoid
+     infinite recursion when trying to compute the names of the
+     enumerators.  */
+  update_enumeration_type_from_children (die, type, cu);
+
+  return type;
 }
 
 /* Given a pointer to a die which begins an enumeration, process all
@@ -15627,8 +16019,6 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (die->child != NULL)
     {
       struct die_info *child_die;
-      struct symbol *sym;
-      std::vector<struct field> fields;
       const char *name;
 
       child_die = die->child;
@@ -15642,30 +16032,11 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
            {
              name = dwarf2_name (child_die, cu);
              if (name)
-               {
-                 sym = new_symbol (child_die, this_type, cu);
-
-                 fields.emplace_back ();
-                 struct field &field = fields.back ();
-
-                 FIELD_NAME (field) = sym->linkage_name ();
-                 FIELD_TYPE (field) = NULL;
-                 SET_FIELD_ENUMVAL (field, SYMBOL_VALUE (sym));
-                 FIELD_BITSIZE (field) = 0;
-               }
+               new_symbol (child_die, this_type, cu);
            }
 
          child_die = child_die->sibling;
        }
-
-      if (!fields.empty ())
-       {
-         TYPE_NFIELDS (this_type) = fields.size ();
-         TYPE_FIELDS (this_type) = (struct field *)
-           TYPE_ALLOC (this_type, sizeof (struct field) * fields.size ());
-         memcpy (TYPE_FIELDS (this_type), fields.data (),
-                 sizeof (struct field) * fields.size ());
-       }
     }
 
   /* If we are reading an enum from a .debug_types unit, and the enum
@@ -15815,7 +16186,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
 
   name = dwarf2_name (die, cu);
   if (name)
-    TYPE_NAME (type) = name;
+    type->set_name (name);
 
   maybe_set_alignment (cu, die, type);
 
@@ -15910,7 +16281,7 @@ mark_common_block_symbol_computed (struct symbol *sym,
   struct dwarf2_locexpr_baton *baton;
   gdb_byte *ptr;
   unsigned int cu_off;
-  enum bfd_endian byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
+  enum bfd_endian byte_order = gdbarch_byte_order (objfile->arch ());
   LONGEST offset = 0;
 
   gdb_assert (common_loc && member_loc);
@@ -16218,7 +16589,7 @@ static struct type *
 read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct gdbarch *gdbarch
-    = get_objfile_arch (cu->per_cu->dwarf2_per_objfile->objfile);
+    = cu->per_cu->dwarf2_per_objfile->objfile->arch ();
   struct comp_unit_head *cu_header = &cu->header;
   struct type *type;
   struct attribute *attr_byte_size;
@@ -16307,9 +16678,9 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
   if (type)
     return type;
 
-  if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
+  if (check_typedef (to_type)->code () == TYPE_CODE_METHOD)
     type = lookup_methodptr_type (to_type);
-  else if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_FUNC)
+  else if (check_typedef (to_type)->code () == TYPE_CODE_FUNC)
     {
       struct type *new_type
        = alloc_type (cu->per_cu->dwarf2_per_objfile->objfile);
@@ -16374,7 +16745,7 @@ add_array_cv_type (struct die_info *die, struct dwarf2_cu *cu,
   base_type = copy_type (base_type);
   inner_array = base_type;
 
-  while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+  while (TYPE_TARGET_TYPE (inner_array)->code () == TYPE_CODE_ARRAY)
     {
       TYPE_TARGET_TYPE (inner_array) =
        copy_type (TYPE_TARGET_TYPE (inner_array));
@@ -16403,7 +16774,7 @@ read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
 
   /* In case the const qualifier is applied to an array type, the element type
      is so qualified, not the array type (section 6.7.3 of C99).  */
-  if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+  if (base_type->code () == TYPE_CODE_ARRAY)
     return add_array_cv_type (die, cu, base_type, 1, 0);
 
   cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
@@ -16425,7 +16796,7 @@ read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
   /* In case the volatile qualifier is applied to an array type, the
      element type is so qualified, not the array type (section 6.7.3
      of C99).  */
-  if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+  if (base_type->code () == TYPE_CODE_ARRAY)
     return add_array_cv_type (die, cu, base_type, 0, 1);
 
   cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
@@ -16477,7 +16848,7 @@ static struct type *
 read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
   struct dynamic_prop prop;
@@ -16795,7 +17166,7 @@ static struct type *
 dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name,
                        const char *name_hint, enum bfd_endian byte_order)
 {
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   const struct floatformat **format;
   struct type *type;
 
@@ -16843,7 +17214,7 @@ dwarf2_init_complex_target_type (struct dwarf2_cu *cu,
                                 int bits, const char *name_hint,
                                 enum bfd_endian byte_order)
 {
-  gdbarch *gdbarch = get_objfile_arch (objfile);
+  gdbarch *gdbarch = objfile->arch ();
   struct type *tt = nullptr;
 
   /* Try to find a suitable floating point builtin type of size BITS.
@@ -16916,7 +17287,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   if (!name)
     complaint (_("DW_AT_name missing from DW_TAG_base_type"));
 
-  arch = get_objfile_arch (objfile);
+  arch = objfile->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (arch);
 
   attr = dwarf2_attr (die, DW_AT_endianity, cu);
@@ -16951,7 +17322,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
       case DW_ATE_complex_float:
        type = dwarf2_init_complex_target_type (cu, objfile, bits / 2, name,
                                                byte_order);
-       if (TYPE_CODE (type) == TYPE_CODE_ERROR)
+       if (type->code () == TYPE_CODE_ERROR)
          {
            if (name == nullptr)
              {
@@ -17206,7 +17577,7 @@ read_subrange_index_type (struct die_info *die, struct dwarf2_cu *cu)
      GCC produces an empty range DIE.
      FIXME: muller/2010-05-28: Possible references to object for low bound,
      high bound or count are not yet handled by this code.  */
-  if (TYPE_CODE (index_type) == TYPE_CODE_VOID)
+  if (index_type->code () == TYPE_CODE_VOID)
     index_type = cu->per_cu->addr_sized_int_type (false);
 
   return index_type;
@@ -17386,7 +17757,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   name = dwarf2_name (die, cu);
   if (name)
-    TYPE_NAME (range_type) = name;
+    range_type->set_name (name);
 
   attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr != nullptr)
@@ -17409,7 +17780,7 @@ read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu)
 
   type = init_type (cu->per_cu->dwarf2_per_objfile->objfile, TYPE_CODE_VOID,0,
                    NULL);
-  TYPE_NAME (type) = dwarf2_name (die, cu);
+  type->set_name (dwarf2_name (die, cu));
 
   /* In Ada, an unspecified type is typically used when the description
      of the type is deferred to a different unit.  When encountering
@@ -17982,7 +18353,12 @@ partial_die_info::read (const struct die_reader_specs *reader,
          /* Note that both forms of linkage name might appear.  We
             assume they will be the same, and we only store the last
             one we see.  */
-         linkage_name = DW_STRING (&attr);
+         linkage_name = attr.value_as_string ();
+         /* rustc emits invalid values for DW_AT_linkage_name.  Ignore these.
+            See https://github.com/rust-lang/rust/issues/32925.  */
+         if (cu->language == language_rust && linkage_name != NULL
+             && strchr (linkage_name, '{') != NULL)
+           linkage_name = NULL;
          break;
        case DW_AT_low_pc:
          has_low_pc_attr = 1;
@@ -18138,7 +18514,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
       if (lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
        {
          struct objfile *objfile = dwarf2_per_objfile->objfile;
-         struct gdbarch *gdbarch = get_objfile_arch (objfile);
+         struct gdbarch *gdbarch = objfile->arch ();
 
          complaint (_("DW_AT_low_pc %s is zero "
                       "for DIE at %s [in module %s]"),
@@ -18150,7 +18526,7 @@ partial_die_info::read (const struct die_reader_specs *reader,
       else if (lowpc >= highpc)
        {
          struct objfile *objfile = dwarf2_per_objfile->objfile;
-         struct gdbarch *gdbarch = get_objfile_arch (objfile);
+         struct gdbarch *gdbarch = objfile->arch ();
 
          complaint (_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
                       "for DIE at %s [in module %s]"),
@@ -18554,7 +18930,6 @@ read_attribute_value (const struct die_reader_specs *reader,
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
   bfd *abfd = reader->abfd;
   struct comp_unit_head *cu_header = &cu->header;
   unsigned int bytes_read;
@@ -18578,9 +18953,12 @@ read_attribute_value (const struct die_reader_specs *reader,
       info_ptr += bytes_read;
       break;
     case DW_FORM_addr:
-      DW_ADDR (attr) = cu->header.read_address (abfd, info_ptr, &bytes_read);
-      DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
-      info_ptr += bytes_read;
+      {
+       struct gdbarch *gdbarch = objfile->arch ();
+       DW_ADDR (attr) = cu->header.read_address (abfd, info_ptr, &bytes_read);
+       DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
+       info_ptr += bytes_read;
+      }
       break;
     case DW_FORM_block2:
       blk = dwarf_alloc_block (cu);
@@ -19160,17 +19538,8 @@ dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *c
 
   if (attr != NULL)
     {
-      if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
-         || attr->form == DW_FORM_string
-         || attr->form == DW_FORM_strx
-         || attr->form == DW_FORM_strx1
-         || attr->form == DW_FORM_strx2
-         || attr->form == DW_FORM_strx3
-         || attr->form == DW_FORM_strx4
-         || attr->form == DW_FORM_GNU_str_index
-         || attr->form == DW_FORM_GNU_strp_alt)
-       str = DW_STRING (attr);
-      else
+      str = attr->value_as_string ();
+      if (str == nullptr)
         complaint (_("string type expected for attribute %s for "
                     "DIE at %s in module %s"),
                   dwarf_attr_name (name), sect_offset_str (die->sect_off),
@@ -19792,7 +20161,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
   CORE_ADDR baseaddr;
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
   bfd *abfd = objfile->obfd;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   /* True if we're recording line info (as opposed to building partial
      symtabs and just interested in finding include files mentioned by
      the line number program).  */
@@ -20216,7 +20585,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
   struct dwarf2_per_objfile *dwarf2_per_objfile
     = cu->per_cu->dwarf2_per_objfile;
   struct objfile *objfile = dwarf2_per_objfile->objfile;
-  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+  struct gdbarch *gdbarch = objfile->arch ();
   struct symbol *sym = NULL;
   const char *name;
   struct attribute *attr = NULL;
@@ -20231,27 +20600,31 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
   name = dwarf2_name (die, cu);
   if (name)
     {
-      const char *linkagename;
       int suppress_add = 0;
 
       if (space)
        sym = space;
       else
-       sym = allocate_symbol (objfile);
+       sym = new (&objfile->objfile_obstack) symbol;
       OBJSTAT (objfile, n_syms++);
 
       /* Cache this symbol's name and the name's demangled form (if any).  */
       sym->set_language (cu->language, &objfile->objfile_obstack);
-      linkagename = dwarf2_physname (name, die, cu);
-      sym->compute_and_set_names (linkagename, false, objfile->per_bfd);
-
       /* Fortran does not have mangling standard and the mangling does differ
         between gfortran, iFort etc.  */
-      if (cu->language == language_fortran
-          && symbol_get_demangled_name (sym) == NULL)
-       symbol_set_demangled_name (sym,
-                                  dwarf2_full_name (name, die, cu),
-                                  NULL);
+      const char *physname
+       = (cu->language == language_fortran
+          ? dwarf2_full_name (name, die, cu)
+          : dwarf2_physname (name, die, cu));
+      const char *linkagename = dw2_linkage_name (die, cu);
+
+      if (linkagename == nullptr || cu->language == language_ada)
+       sym->set_linkage_name (physname);
+      else
+       {
+         sym->set_demangled_name (physname, &objfile->objfile_obstack);
+         sym->set_linkage_name (linkagename);
+       }
 
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
@@ -20343,7 +20716,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
          /* Compilation with minimal debug info may result in
             variables with missing type entries.  Change the
             misleading `void' type to something sensible.  */
-         if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
+         if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_VOID)
            SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
 
          attr = dwarf2_attr (die, DW_AT_const_value, cu);
@@ -20532,7 +20905,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
                       with this objfile, so we don't need to
                       duplicate it for the type.  */
                    if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
-                     TYPE_NAME (SYMBOL_TYPE (sym)) = sym->search_name ();
+                     SYMBOL_TYPE (sym)->set_name (sym->search_name ());
                  }
              }
          }
@@ -21412,13 +21785,11 @@ dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
 {
   if (name && cu->language == language_cplus)
     {
-      std::string canon_name = cp_canonicalize_string (name);
+      gdb::unique_xmalloc_ptr<char> canon_name
+       = cp_canonicalize_string (name);
 
-      if (!canon_name.empty ())
-       {
-         if (canon_name != name)
-           name = objfile->intern (canon_name);
-       }
+      if (canon_name != nullptr)
+       name = objfile->intern (canon_name.get ());
     }
 
   return name;
@@ -21863,7 +22234,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
     {
       CORE_ADDR pc = (*get_frame_pc) (baton);
       CORE_ADDR baseaddr = objfile->text_section_offset ();
-      struct gdbarch *gdbarch = get_objfile_arch (objfile);
+      struct gdbarch *gdbarch = objfile->arch ();
 
       for (const auto &cand_off
             : dwarf2_per_objfile->abstract_to_concrete[die->sect_off])
@@ -22379,27 +22750,13 @@ read_signatured_type (struct signatured_type *sig_type)
 
 /* Decode simple location descriptions.
    Given a pointer to a dwarf block that defines a location, compute
-   the location and return the value.
-
-   NOTE drow/2003-11-18: This function is called in two situations
-   now: for the address of static or global variables (partial symbols
-   only) and for offsets into structures which are expected to be
-   (more or less) constant.  The partial symbol case should go away,
-   and only the constant case should remain.  That will let this
-   function complain more accurately.  A few special modes are allowed
-   without complaint for global variables (for instance, global
-   register values and thread-local values).
-
-   A location description containing no operations indicates that the
-   object is optimized out.  The return value is 0 for that case.
-   FIXME drow/2003-11-16: No callers check for this case any more; soon all
-   callers will only want a very basic result and this can become a
-   complaint.
-
-   Note that stack[0] is unused except as a default error return.  */
+   the location and return the value.  If COMPUTED is non-null, it is
+   set to true to indicate that decoding was successful, and false
+   otherwise.  If COMPUTED is null, then this function may emit a
+   complaint.  */
 
 static CORE_ADDR
-decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
+decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu, bool *computed)
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
   size_t i;
@@ -22410,6 +22767,9 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
   unsigned int bytes_read, unsnd;
   gdb_byte op;
 
+  if (computed != nullptr)
+    *computed = false;
+
   i = 0;
   stacki = 0;
   stack[stacki] = 0;
@@ -22489,7 +22849,12 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
        case DW_OP_reg31:
          stack[++stacki] = op - DW_OP_reg0;
          if (i < size)
-           dwarf2_complex_location_expr_complaint ();
+           {
+             if (computed == nullptr)
+               dwarf2_complex_location_expr_complaint ();
+             else
+               return 0;
+           }
          break;
 
        case DW_OP_regx:
@@ -22497,7 +22862,12 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
          i += bytes_read;
          stack[++stacki] = unsnd;
          if (i < size)
-           dwarf2_complex_location_expr_complaint ();
+           {
+             if (computed == nullptr)
+               dwarf2_complex_location_expr_complaint ();
+             else
+               return 0;
+           }
          break;
 
        case DW_OP_addr:
@@ -22579,7 +22949,12 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
             global symbols, although the variable's address will be bogus
             in the psymtab.  */
          if (i < size)
-           dwarf2_complex_location_expr_complaint ();
+           {
+             if (computed == nullptr)
+               dwarf2_complex_location_expr_complaint ();
+             else
+               return 0;
+           }
          break;
 
         case DW_OP_GNU_push_tls_address:
@@ -22593,11 +22968,18 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
             non-zero to not look as a variable garbage collected by linker
             which have DW_OP_addr 0.  */
          if (i < size)
-           dwarf2_complex_location_expr_complaint ();
+           {
+             if (computed == nullptr)
+               dwarf2_complex_location_expr_complaint ();
+             else
+               return 0;
+           }
          stack[stacki]++;
           break;
 
        case DW_OP_GNU_uninit:
+         if (computed != nullptr)
+           return 0;
          break;
 
        case DW_OP_addrx:
@@ -22609,16 +22991,17 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
          break;
 
        default:
-         {
-           const char *name = get_DW_OP_name (op);
+         if (computed == nullptr)
+           {
+             const char *name = get_DW_OP_name (op);
 
-           if (name)
-             complaint (_("unsupported stack op: '%s'"),
-                        name);
-           else
-             complaint (_("unsupported stack op: '%02x'"),
-                        op);
-         }
+             if (name)
+               complaint (_("unsupported stack op: '%s'"),
+                          name);
+             else
+               complaint (_("unsupported stack op: '%02x'"),
+                          op);
+           }
 
          return (stack[stacki]);
        }
@@ -22627,16 +23010,21 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
          outside of the allocated space.  Also enforce minimum>0.  */
       if (stacki >= ARRAY_SIZE (stack) - 1)
        {
-         complaint (_("location description stack overflow"));
+         if (computed == nullptr)
+           complaint (_("location description stack overflow"));
          return 0;
        }
 
       if (stacki <= 0)
        {
-         complaint (_("location description stack underflow"));
+         if (computed == nullptr)
+           complaint (_("location description stack underflow"));
          return 0;
        }
     }
+
+  if (computed != nullptr)
+    *computed = true;
   return (stack[stacki]);
 }
 
@@ -23250,11 +23638,11 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
      But this is not a problem, because the gnat-specific information
      is actually not needed for these types.  */
   if (need_gnat_info (cu)
-      && TYPE_CODE (type) != TYPE_CODE_FUNC
-      && TYPE_CODE (type) != TYPE_CODE_FLT
-      && TYPE_CODE (type) != TYPE_CODE_METHODPTR
-      && TYPE_CODE (type) != TYPE_CODE_MEMBERPTR
-      && TYPE_CODE (type) != TYPE_CODE_METHOD
+      && type->code () != TYPE_CODE_FUNC
+      && type->code () != TYPE_CODE_FLT
+      && type->code () != TYPE_CODE_METHODPTR
+      && type->code () != TYPE_CODE_MEMBERPTR
+      && type->code () != TYPE_CODE_METHOD
       && !HAVE_GNAT_AUX_INFO (type))
     INIT_GNAT_SPECIFIC (type);
 
@@ -23264,7 +23652,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct type *prop_type = cu->per_cu->addr_sized_int_type (false);
       if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
-        add_dyn_prop (DYN_PROP_ALLOCATED, prop, type);
+        type->add_dyn_prop (DYN_PROP_ALLOCATED, prop);
     }
   else if (attr != NULL)
     {
@@ -23279,7 +23667,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
     {
       struct type *prop_type = cu->per_cu->addr_sized_int_type (false);
       if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
-        add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type);
+        type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
     }
   else if (attr != NULL)
     {
@@ -23292,7 +23680,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   attr = dwarf2_attr (die, DW_AT_data_location, cu);
   if (attr_to_dynamic_prop (attr, die, cu, &prop,
                            cu->per_cu->addr_type ()))
-    add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type);
+    type->add_dyn_prop (DYN_PROP_DATA_LOCATION, prop);
 
   if (dwarf2_per_objfile->die_type_hash == NULL)
     dwarf2_per_objfile->die_type_hash
@@ -23446,19 +23834,6 @@ partial_die_eq (const void *item_lhs, const void *item_rhs)
 struct cmd_list_element *set_dwarf_cmdlist;
 struct cmd_list_element *show_dwarf_cmdlist;
 
-static void
-set_dwarf_cmd (const char *args, int from_tty)
-{
-  help_list (set_dwarf_cmdlist, "maintenance set dwarf ", all_commands,
-            gdb_stdout);
-}
-
-static void
-show_dwarf_cmd (const char *args, int from_tty)
-{
-  cmd_show_list (show_dwarf_cmdlist, from_tty, "");
-}
-
 static void
 show_check_physname (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
@@ -23472,17 +23847,17 @@ void _initialize_dwarf2_read ();
 void
 _initialize_dwarf2_read ()
 {
-  add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
+  add_basic_prefix_cmd ("dwarf", class_maintenance, _("\
 Set DWARF specific variables.\n\
 Configure DWARF variables such as the cache size."),
-                  &set_dwarf_cmdlist, "maintenance set dwarf ",
-                  0/*allow-unknown*/, &maintenance_set_cmdlist);
+                       &set_dwarf_cmdlist, "maintenance set dwarf ",
+                       0/*allow-unknown*/, &maintenance_set_cmdlist);
 
-  add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
+  add_show_prefix_cmd ("dwarf", class_maintenance, _("\
 Show DWARF specific variables.\n\
 Show DWARF variables such as the cache size."),
-                  &show_dwarf_cmdlist, "maintenance show dwarf ",
-                  0/*allow-unknown*/, &maintenance_show_cmdlist);
+                      &show_dwarf_cmdlist, "maintenance show dwarf ",
+                      0/*allow-unknown*/, &maintenance_show_cmdlist);
 
   add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
                            &dwarf_max_cache_age, _("\