From e787e80915aef6d5257234acb844932da5d3b98e Mon Sep 17 00:00:00 2001 From: Keith Seitz Date: Tue, 21 Feb 2017 13:32:51 -0800 Subject: [PATCH] new_fn_field refactor. --- gdb/dwarf2read.c | 206 +++++++++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 86 deletions(-) diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 3edf6dbf77b..d6e074725af 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1796,6 +1796,12 @@ static int attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, struct dwarf2_cu *cu, struct dynamic_prop *prop); +static struct fn_field new_fn_field + (struct die_info *name_die, struct dwarf2_cu *name_cu, + struct die_info *type_die, struct dwarf2_cu *type_cu, + struct type *type, const char *fieldname, + int fnl_idx, int field_idx); + /* memory allocation interface */ static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *); @@ -13051,91 +13057,53 @@ dwarf2_is_constructor (struct die_info *die, struct dwarf2_cu *cu) && (type_name[len] == '\0' || type_name[len] == '<')); } -/* Add a member function to the proper fieldlist. */ +/* Create a new fn_field which may represent an alias to an existing + field (if a constructor or destructor). TYPE_DIE and TYPE_CU + may be NULL, in which case they default to NAME_DIE and NAME_CU, + i.e., not an aliased method. */ -static void -dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, - struct type *type, struct dwarf2_cu *cu) +static struct fn_field +new_fn_field (struct die_info *name_die, struct dwarf2_cu *name_cu, + struct die_info *type_die, struct dwarf2_cu *type_cu, + struct type *type, const char *fieldname, + int fnl_idx, int field_idx) { - struct objfile *objfile = cu->objfile; + struct fn_field fnfield; + struct objfile *objfile; struct attribute *attr; - struct fnfieldlist *flp; - int i; - struct fn_field *fnp; - const char *fieldname; - struct nextfnfield *new_fnfield; struct type *this_type; enum dwarf_access_attribute accessibility; - if (cu->language == language_ada) - error (_("unexpected member function in Ada type")); + memset (&fnfield, 0, sizeof (fnfield)); - /* Get name of member function. */ - fieldname = dwarf2_name (die, cu); - if (fieldname == NULL) - return; + if (type_die == NULL) + type_die = name_die; + if (type_cu == NULL) + type_cu = name_cu; - /* Look up member function name in fieldlist. */ - for (i = 0; i < fip->nfnfields; i++) - { - if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) - break; - } - - /* Create new list element if necessary. */ - if (i < fip->nfnfields) - flp = &fip->fnfieldlists[i]; - else - { - 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]; - flp->name = fieldname; - flp->length = 0; - flp->head = NULL; - i = fip->nfnfields++; - } - - /* 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; + objfile = type_cu->objfile; /* Delay processing of the physname until later. */ - if (cu->language == language_cplus) + if (type_cu->language == language_cplus) { - add_to_method_list (type, i, flp->length - 1, fieldname, - die, cu); + add_to_method_list (type, field_idx, fnl_idx, fieldname, + name_die, name_cu); } else { - const char *physname = dwarf2_physname (fieldname, die, cu); - fnp->physname = physname ? physname : ""; + const char *physname = dwarf2_physname (fieldname, name_die, name_cu); + fnfield.physname = physname ? physname : ""; } - fnp->type = alloc_type (objfile); - this_type = read_type_die (die, cu); + fnfield.type = alloc_type (objfile); + this_type = read_type_die (type_die, type_cu); if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) { int nparams = TYPE_NFIELDS (this_type); /* TYPE is the domain of this method, and THIS_TYPE is the type of the method itself (TYPE_CODE_METHOD). */ - smash_to_method_type (fnp->type, type, + smash_to_method_type (fnfield.type, type, TYPE_TARGET_TYPE (this_type), TYPE_FIELDS (this_type), TYPE_NFIELDS (this_type), @@ -13148,41 +13116,44 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, pointer) as artificial. We obtain this information from read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */ if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0) - fnp->voffset = VOFFSET_STATIC; + fnfield.voffset = VOFFSET_STATIC; } else complaint (&symfile_complaints, _("member function type missing for '%s'"), - dwarf2_full_name (fieldname, die, cu)); + dwarf2_full_name (fieldname, name_die, name_cu)); /* Get fcontext from DW_AT_containing_type if present. */ - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) - fnp->fcontext = die_containing_type (die, cu); + if (dwarf2_attr (type_die, DW_AT_containing_type, type_cu) != NULL) + fnfield.fcontext = die_containing_type (type_die, type_cu); /* dwarf2 doesn't have stubbed physical names, so the setting of is_const and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ /* Get accessibility. */ - attr = dwarf2_attr (die, DW_AT_accessibility, cu); + attr = dwarf2_attr (type_die, DW_AT_accessibility, type_cu); if (attr) accessibility = (enum dwarf_access_attribute) DW_UNSND (attr); else - accessibility = dwarf2_default_access_attribute (die, cu); + accessibility = dwarf2_default_access_attribute (type_die, type_cu); switch (accessibility) { + case DW_ACCESS_public: + fnfield.is_public = 1; + break; case DW_ACCESS_private: - fnp->is_private = 1; + fnfield.is_private = 1; break; case DW_ACCESS_protected: - fnp->is_protected = 1; + fnfield.is_protected = 1; break; } /* Check for artificial methods. */ - attr = dwarf2_attr (die, DW_AT_artificial, cu); + attr = dwarf2_attr (type_die, DW_AT_artificial, type_cu); if (attr && DW_UNSND (attr) != 0) - fnp->is_artificial = 1; + fnfield.is_artificial = 1; - fnp->is_constructor = dwarf2_is_constructor (die, cu); + fnfield.is_constructor = dwarf2_is_constructor (name_die, type_cu); /* Get index in virtual function table if it is a virtual member function. For older versions of GCC, this is an offset in the @@ -13190,7 +13161,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, For everyone else, it is an expression to be evaluated relative to the object address. */ - attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu); + attr = dwarf2_attr (type_die, DW_AT_vtable_elem_location, type_cu); if (attr) { if (attr_form_is_block (attr) && DW_BLOCK (attr)->size > 0) @@ -13198,24 +13169,24 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, if (DW_BLOCK (attr)->data[0] == DW_OP_constu) { /* Old-style GCC. */ - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; + fnfield.voffset = decode_locdesc (DW_BLOCK (attr), type_cu) + 2; } else if (DW_BLOCK (attr)->data[0] == DW_OP_deref || (DW_BLOCK (attr)->size > 1 && DW_BLOCK (attr)->data[0] == DW_OP_deref_size - && DW_BLOCK (attr)->data[1] == cu->header.addr_size)) + && DW_BLOCK (attr)->data[1] == type_cu->header.addr_size)) { - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu); - if ((fnp->voffset % cu->header.addr_size) != 0) + fnfield.voffset = decode_locdesc (DW_BLOCK (attr), type_cu); + if ((fnfield.voffset % type_cu->header.addr_size) != 0) dwarf2_complex_location_expr_complaint (); else - fnp->voffset /= cu->header.addr_size; - fnp->voffset += 2; + fnfield.voffset /= type_cu->header.addr_size; + fnfield.voffset += 2; } else dwarf2_complex_location_expr_complaint (); - if (!fnp->fcontext) + if (!fnfield.fcontext) { /* If there is no `this' field and no DW_AT_containing_type, we cannot actually find a base class context for the @@ -13226,11 +13197,11 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, complaint (&symfile_complaints, _("cannot determine context for virtual member " "function \"%s\" (offset %d)"), - fieldname, die->offset.sect_off); + fieldname, type_die->offset.sect_off); } else { - fnp->fcontext + fnfield.fcontext = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0)); } } @@ -13247,18 +13218,81 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, } else { - attr = dwarf2_attr (die, DW_AT_virtuality, cu); + attr = dwarf2_attr (type_die, DW_AT_virtuality, type_cu); if (attr && DW_UNSND (attr)) { /* GCC does this, as of 2008-08-25; PR debug/37237. */ complaint (&symfile_complaints, _("Member function \"%s\" (offset %d) is virtual " "but the vtable offset is not specified"), - fieldname, die->offset.sect_off); + fieldname, type_die->offset.sect_off); ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_CPLUS_DYNAMIC (type) = 1; } } + + return fnfield; +} + +/* Add a member function to the proper fieldlist. */ + +static void +dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, + struct type *type, struct dwarf2_cu *cu) +{ + struct fnfieldlist *flp; + int i; + const char *fieldname, *linkage_name; + struct nextfnfield *new_fnfield; + + if (cu->language == language_ada) + error (_("unexpected member function in Ada type")); + + /* Get name of member function. */ + fieldname = dwarf2_name (die, cu); + if (fieldname == NULL) + return; + + /* Look up member function name in fieldlist. */ + for (i = 0; i < fip->nfnfields; i++) + { + if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) + break; + } + + /* Create new list element if necessary. */ + if (i < fip->nfnfields) + flp = &fip->fnfieldlists[i]; + else + { + 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]; + flp->name = fieldname; + flp->length = 0; + flp->head = NULL; + i = fip->nfnfields++; + } + + /* 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. */ + new_fnfield->fnfield = new_fn_field (die, cu, NULL, NULL, type, fieldname, + flp->length - 1, i); } /* Create the vector of member function fields, and attach it to the type. */ -- 2.47.2