Patchwork [RFA,2/2] Use std::vector for field lists in dwarf2read.c

login
register
mail settings
Submitter Tom Tromey
Date March 11, 2018, 5:19 a.m.
Message ID <20180311051959.17114-3-tom@tromey.com>
Download mbox | patch
Permalink /patch/26277/
State New
Headers show

Comments

Tom Tromey - March 11, 2018, 5:19 a.m.
This changes dwarf2read.c to use std::vector rather than a linked list
when managing the fields and base classes to be added to a type.  This
removes some bookkeeping types and also allows the removal of some
cleanups.

gdb/ChangeLog
2018-03-10  Tom Tromey  <tom@tromey.com>

	* dwarf2read.c (struct nextfield): Add initializers.
	(struct nextfnfield): Remove.
	(struct fnfieldlist): Add initializers.  Remove "length" and
	"head", use std::vector.
	(struct decl_field_list): Remove.
	(struct field_info): Add initializers.
	<fields, baseclasses>: Now std::vector.
	<nbaseclasses, nfnfields, typedef_field_list_count,
	nested_types_list_count>: Remove.
	(dwarf2_add_field, dwarf2_add_type_defn)
	(dwarf2_attach_fields_to_type, dwarf2_add_member_fn)
	(dwarf2_attach_fn_fields_to_type, handle_struct_member_die)
	(process_structure_scope): Update.
---
 gdb/ChangeLog    |  16 ++++
 gdb/dwarf2read.c | 287 ++++++++++++++++++-------------------------------------
 2 files changed, 111 insertions(+), 192 deletions(-)
Simon Marchi - March 11, 2018, 5:32 p.m.
On 2018-03-11 12:19 AM, Tom Tromey wrote:
> This changes dwarf2read.c to use std::vector rather than a linked list
> when managing the fields and base classes to be added to a type.  This
> removes some bookkeeping types and also allows the removal of some
> cleanups.

That was a good case of twisted and obfuscated code.  For example:

  for (k = flp->length; (k--, nfp); nfp = nfp->next)
    fn_flp->fn_fields[k] = nfp->fnfield;

Your patch makes the code more boring and readable, which is good :).

I didn't spot anything wrong, just some nits.  The patch LGTM with
those fixed.

> @@ -15475,43 +15454,35 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
>  {
>    struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
>    struct gdbarch *gdbarch = get_objfile_arch (objfile);
> -  struct nextfield *new_field;
>    struct attribute *attr;
>    struct field *fp;
>    const char *fieldname = "";
>  
> -  /* Allocate a new field list entry and link it in.  */
> -  new_field = XNEW (struct nextfield);
> -  make_cleanup (xfree, new_field);
> -  memset (new_field, 0, sizeof (struct nextfield));
> -
>    if (die->tag == DW_TAG_inheritance)
> -    {
> -      new_field->next = fip->baseclasses;
> -      fip->baseclasses = new_field;
> -    }
> +    fip->baseclasses.emplace_back ();
>    else
> -    {
> -      new_field->next = fip->fields;
> -      fip->fields = new_field;
> -    }
> +    fip->fields.emplace_back ();
> +  struct nextfield &new_field
> +    = ((die->tag == DW_TAG_inheritance)
> +       ? fip->baseclasses : fip->fields).back ();

I think this construct is not very readable.  I would prefer keeping new_field as
a pointer, and setting it in each branch of the previous if.

> @@ -15926,49 +15865,33 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
>      return;
>  
>    /* Look up member function name in fieldlist.  */
> -  for (i = 0; i < fip->nfnfields; i++)
> +  for (i = 0; i < fip->fnfieldlists.size (); i++)
>      {
>        if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
> -	break;
> +	{
> +	  flp = &fip->fnfieldlists[i];
> +	  break;
> +	}
>      }
>  
>    /* Create new list element if necessary.  */

This comment is stale.

> -  if (i < fip->nfnfields)
> -    flp = &fip->fnfieldlists[i];
> -  else
> +  if (flp == nullptr)
>      {
> -      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
> -	{
> -	  fip->fnfieldlists = (struct fnfieldlist *)
> -	    xrealloc (fip->fnfieldlists,
> -		      (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
> -		      * sizeof (struct fnfieldlist));
> -	  if (fip->nfnfields == 0)
> -	    make_cleanup (free_current_contents, &fip->fnfieldlists);
> -	}
> -      flp = &fip->fnfieldlists[fip->nfnfields];
> +      fip->fnfieldlists.emplace_back ();
> +      flp = &fip->fnfieldlists.back ();
>        flp->name = fieldname;
> -      flp->length = 0;
> -      flp->head = NULL;
> -      i = fip->nfnfields++;
> +      i = fip->fnfieldlists.size () - 1;
>      }
>  
>    /* Create a new member function field and chain it to the field list
>       entry.  */

This one too.

> -  new_fnfield = XNEW (struct nextfnfield);
> -  make_cleanup (xfree, new_fnfield);
> -  memset (new_fnfield, 0, sizeof (struct nextfnfield));
> -  new_fnfield->next = flp->head;
> -  flp->head = new_fnfield;
> -  flp->length++;
> -
> -  /* Fill in the member function field info.  */
> -  fnp = &new_fnfield->fnfield;
> +  flp->fnfields.emplace_back ();
> +  fnp = &flp->fnfields.back ();
>  
>    /* Delay processing of the physname until later.  */
>    if (cu->language == language_cplus)
>      {
> -      add_to_method_list (type, i, flp->length - 1, fieldname,
> +      add_to_method_list (type, i, flp->fnfields.size () - 1, fieldname,
>  			  die, cu);
>      }

Nit: If you remove the unnecessary braces here, you can avoid the line wrapping.

>    else
> @@ -16117,7 +16040,6 @@ static void
>  dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
>  				 struct dwarf2_cu *cu)
>  {
> -  struct fnfieldlist *flp;
>    int i;
>  
>    if (cu->language == language_ada)
> @@ -16125,23 +16047,25 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
>  
>    ALLOCATE_CPLUS_STRUCT_TYPE (type);
>    TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
> -    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
> +    TYPE_ALLOC (type,
> +		sizeof (struct fn_fieldlist) * fip->fnfieldlists.size ());
>  
> -  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
> +  for (i = 0; i < fip->fnfieldlists.size (); i++)

Variables i and k can be declared in the for loops.

>      {
> -      struct nextfnfield *nfp = flp->head;
> +      struct fnfieldlist &nf = fip->fnfieldlists[i];
>        struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
>        int k;
>  
> -      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
> -      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
> +      TYPE_FN_FIELDLIST_NAME (type, i) = nf.name;
> +      TYPE_FN_FIELDLIST_LENGTH (type, i) = nf.fnfields.size ();
>        fn_flp->fn_fields = (struct fn_field *)
> -	TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
> -      for (k = flp->length; (k--, nfp); nfp = nfp->next)
> -	fn_flp->fn_fields[k] = nfp->fnfield;
> +	TYPE_ALLOC (type, sizeof (struct fn_field) * nf.fnfields.size ());
> +
> +      for (k = 0; k < nf.fnfields.size (); ++k)
> +	fn_flp->fn_fields[k] = nf.fnfields[k];
>      }
>  
> -  TYPE_NFN_FIELDS (type) = fip->nfnfields;
> +  TYPE_NFN_FIELDS (type) = fip->fnfieldlists.size ();
>  }
>  
>  /* Returns non-zero if NAME is the name of a vtable member in CU's
> @@ -16419,11 +16343,11 @@ handle_struct_member_die (struct die_info *child_die, struct type *type,
>  
>        /* The first field was just added, so we can stash the
>  	 discriminant there.  */
> -      gdb_assert (fi->fields != NULL);
> +      gdb_assert (!fi->fields.empty ());
>        if (discr == NULL)
> -	fi->fields->variant.default_branch = true;
> +	fi->fields.back ().variant.default_branch = true;
>        else
> -	fi->fields->variant.discriminant_value = DW_UNSND (discr);
> +	fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
>      }
>  }
>  
> @@ -16478,9 +16402,6 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
>      {
>        struct field_info fi;
>        std::vector<struct symbol *> template_args;
> -      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
> -
> -      memset (&fi, 0, sizeof (struct field_info));
>  
>        child_die = die->child;
>  
> @@ -16489,7 +16410,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
>  	  handle_struct_member_die (child_die, type, &fi, &template_args, cu);
>  
>  	  if (is_variant_part && discr_offset == child_die->sect_off)
> -	    fi.fields->variant.is_discriminant = true;
> +	    fi.fields.back ().variant.is_discriminant = true;
>  
>  	  child_die = sibling_die (child_die);
>  	}
> @@ -16512,7 +16433,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
>        /* Attach fields and member functions to the type.  */
>        if (fi.nfields)
>  	dwarf2_attach_fields_to_type (&fi, type, cu);
> -      if (fi.nfnfields)
> +      if (!fi.fnfieldlists.empty ())
>  	{
>  	  dwarf2_attach_fn_fields_to_type (&fi, type, cu);
>  
> @@ -16582,9 +16503,9 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
>  
>        /* Copy fi.typedef_field_list linked list elements content into the
>  	 allocated array TYPE_TYPEDEF_FIELD_ARRAY (type).  */
> -      if (fi.typedef_field_list)
> +      if (!fi.typedef_field_list.empty ())
>  	{
> -	  int i = fi.typedef_field_list_count;
> +	  int i = fi.typedef_field_list.size ();

Can you rename this variable to something else (size, count, etc) and declare
the int i in the for loop?  The two usages of i are not related anymore, so it
would be clearer with two separate variables.

>  
>  	  ALLOCATE_CPLUS_STRUCT_TYPE (type);
>  	  TYPE_TYPEDEF_FIELD_ARRAY (type)
> @@ -16592,23 +16513,15 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
>  	       TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i));
>  	  TYPE_TYPEDEF_FIELD_COUNT (type) = i;
>  
> -	  /* Reverse the list order to keep the debug info elements order.  */
> -	  while (--i >= 0)
> -	    {
> -	      struct decl_field *dest, *src;
> -
> -	      dest = &TYPE_TYPEDEF_FIELD (type, i);
> -	      src = &fi.typedef_field_list->field;
> -	      fi.typedef_field_list = fi.typedef_field_list->next;
> -	      *dest = *src;
> -	    }
> +	  for (i = 0; i < fi.typedef_field_list.size (); ++i)
> +	    TYPE_TYPEDEF_FIELD (type, i) = fi.typedef_field_list[i];
>  	}
>  
>        /* Copy fi.nested_types_list linked list elements content into the
>  	 allocated array TYPE_NESTED_TYPES_ARRAY (type).  */
> -      if (fi.nested_types_list != NULL && cu->language != language_ada)
> +      if (!fi.nested_types_list.empty () && cu->language != language_ada)
>  	{
> -	  int i = fi.nested_types_list_count;
> +	  int i = fi.nested_types_list.size ();

Same here.

Thanks!

Simon
Tom Tromey - March 12, 2018, 3:06 a.m.
>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

Simon> I didn't spot anything wrong, just some nits.  The patch LGTM with
Simon> those fixed.

Thanks.  I'm appending the new patch.
I'm checking it in.

Simon> This comment is stale.
[...]
Simon> This one too.

I updated them a bit, but maybe not super well.  I was inclined to just
remove them but I didn't know how that would go over.

I can fix them up more somehow if you want.

Simon> Nit: If you remove the unnecessary braces here, you can avoid the
Simon> line wrapping.

It was 1 character too long for that but I removed the braces anyhow.

Tom

Patch

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index bbeb76ca70..4323d09d14 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -1725,31 +1725,17 @@  struct variant_field
 
 struct nextfield
 {
-  struct nextfield *next;
-  int accessibility;
-  int virtuality;
+  int accessibility = 0;
+  int virtuality = 0;
   /* Extra information to describe a variant or variant part.  */
-  struct variant_field variant;
-  struct field field;
-};
-
-struct nextfnfield
-{
-  struct nextfnfield *next;
-  struct fn_field fnfield;
+  struct variant_field variant {};
+  struct field field {};
 };
 
 struct fnfieldlist
 {
-  const char *name;
-  int length;
-  struct nextfnfield *head;
-};
-
-struct decl_field_list
-{
-  struct decl_field field;
-  struct decl_field_list *next;
+  const char *name = nullptr;
+  std::vector<struct fn_field> fnfields;
 };
 
 /* The routines that read and process dies for a C struct or C++ class
@@ -1758,34 +1744,27 @@  struct decl_field_list
 struct field_info
   {
     /* List of data member and baseclasses fields.  */
-    struct nextfield *fields, *baseclasses;
+    std::vector<struct nextfield> fields;
+    std::vector<struct nextfield> baseclasses;
 
     /* Number of fields (including baseclasses).  */
-    int nfields;
-
-    /* Number of baseclasses.  */
-    int nbaseclasses;
+    int nfields = 0;
 
     /* Set if the accesibility of one of the fields is not public.  */
-    int non_public_fields;
+    int non_public_fields = 0;
 
     /* Member function fieldlist array, contains name of possibly overloaded
        member function, number of overloaded member functions and a pointer
        to the head of the member function field chain.  */
-    struct fnfieldlist *fnfieldlists;
-
-    /* Number of entries in the fnfieldlists array.  */
-    int nfnfields;
+    std::vector<struct fnfieldlist> fnfieldlists;
 
     /* typedefs defined inside this class.  TYPEDEF_FIELD_LIST contains head of
        a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements.  */
-    struct decl_field_list *typedef_field_list;
-    unsigned typedef_field_list_count;
+    std::vector<struct decl_field> typedef_field_list;
 
     /* Nested types defined by this class and the number of elements in this
        list.  */
-    struct decl_field_list *nested_types_list;
-    unsigned nested_types_list_count;
+    std::vector<struct decl_field> nested_types_list;
   };
 
 /* One item on the queue of compilation units to read in full symbols
@@ -15475,43 +15454,35 @@  dwarf2_add_field (struct field_info *fip, struct die_info *die,
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
-  struct nextfield *new_field;
   struct attribute *attr;
   struct field *fp;
   const char *fieldname = "";
 
-  /* Allocate a new field list entry and link it in.  */
-  new_field = XNEW (struct nextfield);
-  make_cleanup (xfree, new_field);
-  memset (new_field, 0, sizeof (struct nextfield));
-
   if (die->tag == DW_TAG_inheritance)
-    {
-      new_field->next = fip->baseclasses;
-      fip->baseclasses = new_field;
-    }
+    fip->baseclasses.emplace_back ();
   else
-    {
-      new_field->next = fip->fields;
-      fip->fields = new_field;
-    }
+    fip->fields.emplace_back ();
+  struct nextfield &new_field
+    = ((die->tag == DW_TAG_inheritance)
+       ? fip->baseclasses : fip->fields).back ();
+
   fip->nfields++;
 
   attr = dwarf2_attr (die, DW_AT_accessibility, cu);
   if (attr)
-    new_field->accessibility = DW_UNSND (attr);
+    new_field.accessibility = DW_UNSND (attr);
   else
-    new_field->accessibility = dwarf2_default_access_attribute (die, cu);
-  if (new_field->accessibility != DW_ACCESS_public)
+    new_field.accessibility = dwarf2_default_access_attribute (die, cu);
+  if (new_field.accessibility != DW_ACCESS_public)
     fip->non_public_fields = 1;
 
   attr = dwarf2_attr (die, DW_AT_virtuality, cu);
   if (attr)
-    new_field->virtuality = DW_UNSND (attr);
+    new_field.virtuality = DW_UNSND (attr);
   else
-    new_field->virtuality = DW_VIRTUALITY_none;
+    new_field.virtuality = DW_VIRTUALITY_none;
 
-  fp = &new_field->field;
+  fp = &new_field.field;
 
   if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
     {
@@ -15602,7 +15573,7 @@  dwarf2_add_field (struct field_info *fip, struct die_info *die,
       if (dwarf2_attr (die, DW_AT_artificial, cu))
 	{
 	  FIELD_ARTIFICIAL (*fp) = 1;
-	  new_field->accessibility = DW_ACCESS_private;
+	  new_field.accessibility = DW_ACCESS_private;
 	  fip->non_public_fields = 1;
 	}
     }
@@ -15654,7 +15625,6 @@  dwarf2_add_field (struct field_info *fip, struct die_info *die,
       FIELD_BITSIZE (*fp) = 0;
       FIELD_TYPE (*fp) = die_type (die, cu);
       FIELD_NAME (*fp) = type_name_no_tag (fp->type);
-      fip->nbaseclasses++;
     }
   else if (die->tag == DW_TAG_variant_part)
     {
@@ -15697,20 +15667,14 @@  static void
 dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
 		      struct dwarf2_cu *cu)
 {
-  struct decl_field_list *new_field;
-  struct decl_field *fp;
-
-  /* Allocate a new field list entry and link it in.  */
-  new_field = XCNEW (struct decl_field_list);
-  make_cleanup (xfree, new_field);
+  struct decl_field fp;
+  memset (&fp, 0, sizeof (fp));
 
   gdb_assert (type_can_define_types (die));
 
-  fp = &new_field->field;
-
   /* Get name of field.  NULL is okay here, meaning an anonymous type.  */
-  fp->name = dwarf2_name (die, cu);
-  fp->type = read_type_die (die, cu);
+  fp.name = dwarf2_name (die, cu);
+  fp.type = read_type_die (die, cu);
 
   /* Save accessibility.  */
   enum dwarf_access_attribute accessibility;
@@ -15725,10 +15689,10 @@  dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
       /* The assumed value if neither private nor protected.  */
       break;
     case DW_ACCESS_private:
-      fp->is_private = 1;
+      fp.is_private = 1;
       break;
     case DW_ACCESS_protected:
-      fp->is_protected = 1;
+      fp.is_protected = 1;
       break;
     default:
       complaint (&symfile_complaints,
@@ -15736,17 +15700,9 @@  dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
     }
 
   if (die->tag == DW_TAG_typedef)
-    {
-      new_field->next = fip->typedef_field_list;
-      fip->typedef_field_list = new_field;
-      fip->typedef_field_list_count++;
-    }
+    fip->typedef_field_list.push_back (fp);
   else
-    {
-      new_field->next = fip->nested_types_list;
-      fip->nested_types_list = new_field;
-      fip->nested_types_list_count++;
-    }
+    fip->nested_types_list.push_back (fp);
 }
 
 /* Create the vector of fields, and attach it to the type.  */
@@ -15761,8 +15717,7 @@  dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
      and create blank accessibility bitfields if necessary.  */
   TYPE_NFIELDS (type) = nfields;
   TYPE_FIELDS (type) = (struct field *)
-    TYPE_ALLOC (type, sizeof (struct field) * nfields);
-  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+    TYPE_ZALLOC (type, sizeof (struct field) * nfields);
 
   if (fip->non_public_fields && cu->language != language_ada)
     {
@@ -15783,68 +15738,53 @@  dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
 
   /* If the type has baseclasses, allocate and clear a bit vector for
      TYPE_FIELD_VIRTUAL_BITS.  */
-  if (fip->nbaseclasses && cu->language != language_ada)
+  if (!fip->baseclasses.empty () && cu->language != language_ada)
     {
-      int num_bytes = B_BYTES (fip->nbaseclasses);
+      int num_bytes = B_BYTES (fip->baseclasses.size ());
       unsigned char *pointer;
 
       ALLOCATE_CPLUS_STRUCT_TYPE (type);
       pointer = (unsigned char *) TYPE_ALLOC (type, num_bytes);
       TYPE_FIELD_VIRTUAL_BITS (type) = pointer;
-      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
-      TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->baseclasses.size ());
+      TYPE_N_BASECLASSES (type) = fip->baseclasses.size ();
     }
 
   if (TYPE_FLAG_DISCRIMINATED_UNION (type))
     {
       struct discriminant_info *di = alloc_discriminant_info (type, -1, -1);
 
-      int index = nfields - 1;
-      struct nextfield *field = fip->fields;
-
-      while (index >= 0)
+      for (int index = 0; index < nfields; ++index)
 	{
-	  if (field->variant.is_discriminant)
+	  struct nextfield &field = fip->fields[index];
+
+	  if (field.variant.is_discriminant)
 	    di->discriminant_index = index;
-	  else if (field->variant.default_branch)
+	  else if (field.variant.default_branch)
 	    di->default_index = index;
 	  else
-	    di->discriminants[index] = field->variant.discriminant_value;
-
-	  --index;
-	  field = field->next;
+	    di->discriminants[index] = field.variant.discriminant_value;
 	}
     }
 
-  /* Copy the saved-up fields into the field vector.  Start from the head of
-     the list, adding to the tail of the field array, so that they end up in
-     the same order in the array in which they were added to the list.  */
-  while (nfields-- > 0)
+  /* Copy the saved-up fields into the field vector.  */
+  for (int i = 0; i < nfields; ++i)
     {
-      struct nextfield *fieldp;
+      struct nextfield &field
+	= ((i < fip->baseclasses.size ()) ? fip->baseclasses[i]
+	   : fip->fields[i - fip->baseclasses.size ()]);
 
-      if (fip->fields)
-	{
-	  fieldp = fip->fields;
-	  fip->fields = fieldp->next;
-	}
-      else
-	{
-	  fieldp = fip->baseclasses;
-	  fip->baseclasses = fieldp->next;
-	}
-
-      TYPE_FIELD (type, nfields) = fieldp->field;
-      switch (fieldp->accessibility)
+      TYPE_FIELD (type, i) = field.field;
+      switch (field.accessibility)
 	{
 	case DW_ACCESS_private:
 	  if (cu->language != language_ada)
-	    SET_TYPE_FIELD_PRIVATE (type, nfields);
+	    SET_TYPE_FIELD_PRIVATE (type, i);
 	  break;
 
 	case DW_ACCESS_protected:
 	  if (cu->language != language_ada)
-	    SET_TYPE_FIELD_PROTECTED (type, nfields);
+	    SET_TYPE_FIELD_PROTECTED (type, i);
 	  break;
 
 	case DW_ACCESS_public:
@@ -15854,19 +15794,19 @@  dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
 	  /* Unknown accessibility.  Complain and treat it as public.  */
 	  {
 	    complaint (&symfile_complaints, _("unsupported accessibility %d"),
-		       fieldp->accessibility);
+		       field.accessibility);
 	  }
 	  break;
 	}
-      if (nfields < fip->nbaseclasses)
+      if (i < fip->baseclasses.size ())
 	{
-	  switch (fieldp->virtuality)
+	  switch (field.virtuality)
 	    {
 	    case DW_VIRTUALITY_virtual:
 	    case DW_VIRTUALITY_pure_virtual:
 	      if (cu->language == language_ada)
 		error (_("unexpected virtuality in component of Ada type"));
-	      SET_TYPE_FIELD_VIRTUAL (type, nfields);
+	      SET_TYPE_FIELD_VIRTUAL (type, i);
 	      break;
 	    }
 	}
@@ -15909,11 +15849,10 @@  dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
 {
   struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
   struct attribute *attr;
-  struct fnfieldlist *flp;
   int i;
+  struct fnfieldlist *flp = nullptr;
   struct fn_field *fnp;
   const char *fieldname;
-  struct nextfnfield *new_fnfield;
   struct type *this_type;
   enum dwarf_access_attribute accessibility;
 
@@ -15926,49 +15865,33 @@  dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
     return;
 
   /* Look up member function name in fieldlist.  */
-  for (i = 0; i < fip->nfnfields; i++)
+  for (i = 0; i < fip->fnfieldlists.size (); i++)
     {
       if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
-	break;
+	{
+	  flp = &fip->fnfieldlists[i];
+	  break;
+	}
     }
 
   /* Create new list element if necessary.  */
-  if (i < fip->nfnfields)
-    flp = &fip->fnfieldlists[i];
-  else
+  if (flp == nullptr)
     {
-      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
-	{
-	  fip->fnfieldlists = (struct fnfieldlist *)
-	    xrealloc (fip->fnfieldlists,
-		      (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
-		      * sizeof (struct fnfieldlist));
-	  if (fip->nfnfields == 0)
-	    make_cleanup (free_current_contents, &fip->fnfieldlists);
-	}
-      flp = &fip->fnfieldlists[fip->nfnfields];
+      fip->fnfieldlists.emplace_back ();
+      flp = &fip->fnfieldlists.back ();
       flp->name = fieldname;
-      flp->length = 0;
-      flp->head = NULL;
-      i = fip->nfnfields++;
+      i = fip->fnfieldlists.size () - 1;
     }
 
   /* Create a new member function field and chain it to the field list
      entry.  */
-  new_fnfield = XNEW (struct nextfnfield);
-  make_cleanup (xfree, new_fnfield);
-  memset (new_fnfield, 0, sizeof (struct nextfnfield));
-  new_fnfield->next = flp->head;
-  flp->head = new_fnfield;
-  flp->length++;
-
-  /* Fill in the member function field info.  */
-  fnp = &new_fnfield->fnfield;
+  flp->fnfields.emplace_back ();
+  fnp = &flp->fnfields.back ();
 
   /* Delay processing of the physname until later.  */
   if (cu->language == language_cplus)
     {
-      add_to_method_list (type, i, flp->length - 1, fieldname,
+      add_to_method_list (type, i, flp->fnfields.size () - 1, fieldname,
 			  die, cu);
     }
   else
@@ -16117,7 +16040,6 @@  static void
 dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
 				 struct dwarf2_cu *cu)
 {
-  struct fnfieldlist *flp;
   int i;
 
   if (cu->language == language_ada)
@@ -16125,23 +16047,25 @@  dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
 
   ALLOCATE_CPLUS_STRUCT_TYPE (type);
   TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
-    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+    TYPE_ALLOC (type,
+		sizeof (struct fn_fieldlist) * fip->fnfieldlists.size ());
 
-  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+  for (i = 0; i < fip->fnfieldlists.size (); i++)
     {
-      struct nextfnfield *nfp = flp->head;
+      struct fnfieldlist &nf = fip->fnfieldlists[i];
       struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
       int k;
 
-      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
-      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+      TYPE_FN_FIELDLIST_NAME (type, i) = nf.name;
+      TYPE_FN_FIELDLIST_LENGTH (type, i) = nf.fnfields.size ();
       fn_flp->fn_fields = (struct fn_field *)
-	TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
-      for (k = flp->length; (k--, nfp); nfp = nfp->next)
-	fn_flp->fn_fields[k] = nfp->fnfield;
+	TYPE_ALLOC (type, sizeof (struct fn_field) * nf.fnfields.size ());
+
+      for (k = 0; k < nf.fnfields.size (); ++k)
+	fn_flp->fn_fields[k] = nf.fnfields[k];
     }
 
-  TYPE_NFN_FIELDS (type) = fip->nfnfields;
+  TYPE_NFN_FIELDS (type) = fip->fnfieldlists.size ();
 }
 
 /* Returns non-zero if NAME is the name of a vtable member in CU's
@@ -16419,11 +16343,11 @@  handle_struct_member_die (struct die_info *child_die, struct type *type,
 
       /* The first field was just added, so we can stash the
 	 discriminant there.  */
-      gdb_assert (fi->fields != NULL);
+      gdb_assert (!fi->fields.empty ());
       if (discr == NULL)
-	fi->fields->variant.default_branch = true;
+	fi->fields.back ().variant.default_branch = true;
       else
-	fi->fields->variant.discriminant_value = DW_UNSND (discr);
+	fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
     }
 }
 
@@ -16478,9 +16402,6 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
     {
       struct field_info fi;
       std::vector<struct symbol *> template_args;
-      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-
-      memset (&fi, 0, sizeof (struct field_info));
 
       child_die = die->child;
 
@@ -16489,7 +16410,7 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 	  handle_struct_member_die (child_die, type, &fi, &template_args, cu);
 
 	  if (is_variant_part && discr_offset == child_die->sect_off)
-	    fi.fields->variant.is_discriminant = true;
+	    fi.fields.back ().variant.is_discriminant = true;
 
 	  child_die = sibling_die (child_die);
 	}
@@ -16512,7 +16433,7 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
       /* Attach fields and member functions to the type.  */
       if (fi.nfields)
 	dwarf2_attach_fields_to_type (&fi, type, cu);
-      if (fi.nfnfields)
+      if (!fi.fnfieldlists.empty ())
 	{
 	  dwarf2_attach_fn_fields_to_type (&fi, type, cu);
 
@@ -16582,9 +16503,9 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 
       /* Copy fi.typedef_field_list linked list elements content into the
 	 allocated array TYPE_TYPEDEF_FIELD_ARRAY (type).  */
-      if (fi.typedef_field_list)
+      if (!fi.typedef_field_list.empty ())
 	{
-	  int i = fi.typedef_field_list_count;
+	  int i = fi.typedef_field_list.size ();
 
 	  ALLOCATE_CPLUS_STRUCT_TYPE (type);
 	  TYPE_TYPEDEF_FIELD_ARRAY (type)
@@ -16592,23 +16513,15 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 	       TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i));
 	  TYPE_TYPEDEF_FIELD_COUNT (type) = i;
 
-	  /* Reverse the list order to keep the debug info elements order.  */
-	  while (--i >= 0)
-	    {
-	      struct decl_field *dest, *src;
-
-	      dest = &TYPE_TYPEDEF_FIELD (type, i);
-	      src = &fi.typedef_field_list->field;
-	      fi.typedef_field_list = fi.typedef_field_list->next;
-	      *dest = *src;
-	    }
+	  for (i = 0; i < fi.typedef_field_list.size (); ++i)
+	    TYPE_TYPEDEF_FIELD (type, i) = fi.typedef_field_list[i];
 	}
 
       /* Copy fi.nested_types_list linked list elements content into the
 	 allocated array TYPE_NESTED_TYPES_ARRAY (type).  */
-      if (fi.nested_types_list != NULL && cu->language != language_ada)
+      if (!fi.nested_types_list.empty () && cu->language != language_ada)
 	{
-	  int i = fi.nested_types_list_count;
+	  int i = fi.nested_types_list.size ();
 
 	  ALLOCATE_CPLUS_STRUCT_TYPE (type);
 	  TYPE_NESTED_TYPES_ARRAY (type)
@@ -16616,19 +16529,9 @@  process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
 	       TYPE_ALLOC (type, sizeof (struct decl_field) * i));
 	  TYPE_NESTED_TYPES_COUNT (type) = i;
 
-	  /* Reverse the list order to keep the debug info elements order.  */
-	  while (--i >= 0)
-	    {
-	      struct decl_field *dest, *src;
-
-	      dest = &TYPE_NESTED_TYPES_FIELD (type, i);
-	      src = &fi.nested_types_list->field;
-	      fi.nested_types_list = fi.nested_types_list->next;
-	      *dest = *src;
-	    }
+	  for (i = 0; i < fi.nested_types_list.size (); ++i)
+	    TYPE_NESTED_TYPES_FIELD (type, i) = fi.nested_types_list[i];
 	}
-
-      do_cleanups (back_to);
     }
 
   quirk_gcc_member_function_pointer (type, objfile);