GNU Binutils with patches for OS216
修订版 | e787e80915aef6d5257234acb844932da5d3b98e (tree) |
---|---|
时间 | 2017-02-22 06:32:51 |
作者 | Keith Seitz <keiths@redh...> |
Commiter | Keith Seitz |
new_fn_field refactor.
@@ -1796,6 +1796,12 @@ static int attr_to_dynamic_prop (const struct attribute *attr, | ||
1796 | 1796 | struct die_info *die, struct dwarf2_cu *cu, |
1797 | 1797 | struct dynamic_prop *prop); |
1798 | 1798 | |
1799 | +static struct fn_field new_fn_field | |
1800 | + (struct die_info *name_die, struct dwarf2_cu *name_cu, | |
1801 | + struct die_info *type_die, struct dwarf2_cu *type_cu, | |
1802 | + struct type *type, const char *fieldname, | |
1803 | + int fnl_idx, int field_idx); | |
1804 | + | |
1799 | 1805 | /* memory allocation interface */ |
1800 | 1806 | |
1801 | 1807 | 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) | ||
13051 | 13057 | && (type_name[len] == '\0' || type_name[len] == '<')); |
13052 | 13058 | } |
13053 | 13059 | |
13054 | -/* Add a member function to the proper fieldlist. */ | |
13060 | +/* Create a new fn_field which may represent an alias to an existing | |
13061 | + field (if a constructor or destructor). TYPE_DIE and TYPE_CU | |
13062 | + may be NULL, in which case they default to NAME_DIE and NAME_CU, | |
13063 | + i.e., not an aliased method. */ | |
13055 | 13064 | |
13056 | -static void | |
13057 | -dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, | |
13058 | - struct type *type, struct dwarf2_cu *cu) | |
13065 | +static struct fn_field | |
13066 | +new_fn_field (struct die_info *name_die, struct dwarf2_cu *name_cu, | |
13067 | + struct die_info *type_die, struct dwarf2_cu *type_cu, | |
13068 | + struct type *type, const char *fieldname, | |
13069 | + int fnl_idx, int field_idx) | |
13059 | 13070 | { |
13060 | - struct objfile *objfile = cu->objfile; | |
13071 | + struct fn_field fnfield; | |
13072 | + struct objfile *objfile; | |
13061 | 13073 | struct attribute *attr; |
13062 | - struct fnfieldlist *flp; | |
13063 | - int i; | |
13064 | - struct fn_field *fnp; | |
13065 | - const char *fieldname; | |
13066 | - struct nextfnfield *new_fnfield; | |
13067 | 13074 | struct type *this_type; |
13068 | 13075 | enum dwarf_access_attribute accessibility; |
13069 | 13076 | |
13070 | - if (cu->language == language_ada) | |
13071 | - error (_("unexpected member function in Ada type")); | |
13077 | + memset (&fnfield, 0, sizeof (fnfield)); | |
13072 | 13078 | |
13073 | - /* Get name of member function. */ | |
13074 | - fieldname = dwarf2_name (die, cu); | |
13075 | - if (fieldname == NULL) | |
13076 | - return; | |
13079 | + if (type_die == NULL) | |
13080 | + type_die = name_die; | |
13081 | + if (type_cu == NULL) | |
13082 | + type_cu = name_cu; | |
13077 | 13083 | |
13078 | - /* Look up member function name in fieldlist. */ | |
13079 | - for (i = 0; i < fip->nfnfields; i++) | |
13080 | - { | |
13081 | - if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) | |
13082 | - break; | |
13083 | - } | |
13084 | - | |
13085 | - /* Create new list element if necessary. */ | |
13086 | - if (i < fip->nfnfields) | |
13087 | - flp = &fip->fnfieldlists[i]; | |
13088 | - else | |
13089 | - { | |
13090 | - if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0) | |
13091 | - { | |
13092 | - fip->fnfieldlists = (struct fnfieldlist *) | |
13093 | - xrealloc (fip->fnfieldlists, | |
13094 | - (fip->nfnfields + DW_FIELD_ALLOC_CHUNK) | |
13095 | - * sizeof (struct fnfieldlist)); | |
13096 | - if (fip->nfnfields == 0) | |
13097 | - make_cleanup (free_current_contents, &fip->fnfieldlists); | |
13098 | - } | |
13099 | - flp = &fip->fnfieldlists[fip->nfnfields]; | |
13100 | - flp->name = fieldname; | |
13101 | - flp->length = 0; | |
13102 | - flp->head = NULL; | |
13103 | - i = fip->nfnfields++; | |
13104 | - } | |
13105 | - | |
13106 | - /* Create a new member function field and chain it to the field list | |
13107 | - entry. */ | |
13108 | - new_fnfield = XNEW (struct nextfnfield); | |
13109 | - make_cleanup (xfree, new_fnfield); | |
13110 | - memset (new_fnfield, 0, sizeof (struct nextfnfield)); | |
13111 | - new_fnfield->next = flp->head; | |
13112 | - flp->head = new_fnfield; | |
13113 | - flp->length++; | |
13114 | - | |
13115 | - /* Fill in the member function field info. */ | |
13116 | - fnp = &new_fnfield->fnfield; | |
13084 | + objfile = type_cu->objfile; | |
13117 | 13085 | |
13118 | 13086 | /* Delay processing of the physname until later. */ |
13119 | - if (cu->language == language_cplus) | |
13087 | + if (type_cu->language == language_cplus) | |
13120 | 13088 | { |
13121 | - add_to_method_list (type, i, flp->length - 1, fieldname, | |
13122 | - die, cu); | |
13089 | + add_to_method_list (type, field_idx, fnl_idx, fieldname, | |
13090 | + name_die, name_cu); | |
13123 | 13091 | } |
13124 | 13092 | else |
13125 | 13093 | { |
13126 | - const char *physname = dwarf2_physname (fieldname, die, cu); | |
13127 | - fnp->physname = physname ? physname : ""; | |
13094 | + const char *physname = dwarf2_physname (fieldname, name_die, name_cu); | |
13095 | + fnfield.physname = physname ? physname : ""; | |
13128 | 13096 | } |
13129 | 13097 | |
13130 | - fnp->type = alloc_type (objfile); | |
13131 | - this_type = read_type_die (die, cu); | |
13098 | + fnfield.type = alloc_type (objfile); | |
13099 | + this_type = read_type_die (type_die, type_cu); | |
13132 | 13100 | if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC) |
13133 | 13101 | { |
13134 | 13102 | int nparams = TYPE_NFIELDS (this_type); |
13135 | 13103 | |
13136 | 13104 | /* TYPE is the domain of this method, and THIS_TYPE is the type |
13137 | 13105 | of the method itself (TYPE_CODE_METHOD). */ |
13138 | - smash_to_method_type (fnp->type, type, | |
13106 | + smash_to_method_type (fnfield.type, type, | |
13139 | 13107 | TYPE_TARGET_TYPE (this_type), |
13140 | 13108 | TYPE_FIELDS (this_type), |
13141 | 13109 | TYPE_NFIELDS (this_type), |
@@ -13148,41 +13116,44 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, | ||
13148 | 13116 | pointer) as artificial. We obtain this information from |
13149 | 13117 | read_subroutine_type via TYPE_FIELD_ARTIFICIAL. */ |
13150 | 13118 | if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (this_type, 0) == 0) |
13151 | - fnp->voffset = VOFFSET_STATIC; | |
13119 | + fnfield.voffset = VOFFSET_STATIC; | |
13152 | 13120 | } |
13153 | 13121 | else |
13154 | 13122 | complaint (&symfile_complaints, _("member function type missing for '%s'"), |
13155 | - dwarf2_full_name (fieldname, die, cu)); | |
13123 | + dwarf2_full_name (fieldname, name_die, name_cu)); | |
13156 | 13124 | |
13157 | 13125 | /* Get fcontext from DW_AT_containing_type if present. */ |
13158 | - if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL) | |
13159 | - fnp->fcontext = die_containing_type (die, cu); | |
13126 | + if (dwarf2_attr (type_die, DW_AT_containing_type, type_cu) != NULL) | |
13127 | + fnfield.fcontext = die_containing_type (type_die, type_cu); | |
13160 | 13128 | |
13161 | 13129 | /* dwarf2 doesn't have stubbed physical names, so the setting of is_const and |
13162 | 13130 | is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */ |
13163 | 13131 | |
13164 | 13132 | /* Get accessibility. */ |
13165 | - attr = dwarf2_attr (die, DW_AT_accessibility, cu); | |
13133 | + attr = dwarf2_attr (type_die, DW_AT_accessibility, type_cu); | |
13166 | 13134 | if (attr) |
13167 | 13135 | accessibility = (enum dwarf_access_attribute) DW_UNSND (attr); |
13168 | 13136 | else |
13169 | - accessibility = dwarf2_default_access_attribute (die, cu); | |
13137 | + accessibility = dwarf2_default_access_attribute (type_die, type_cu); | |
13170 | 13138 | switch (accessibility) |
13171 | 13139 | { |
13140 | + case DW_ACCESS_public: | |
13141 | + fnfield.is_public = 1; | |
13142 | + break; | |
13172 | 13143 | case DW_ACCESS_private: |
13173 | - fnp->is_private = 1; | |
13144 | + fnfield.is_private = 1; | |
13174 | 13145 | break; |
13175 | 13146 | case DW_ACCESS_protected: |
13176 | - fnp->is_protected = 1; | |
13147 | + fnfield.is_protected = 1; | |
13177 | 13148 | break; |
13178 | 13149 | } |
13179 | 13150 | |
13180 | 13151 | /* Check for artificial methods. */ |
13181 | - attr = dwarf2_attr (die, DW_AT_artificial, cu); | |
13152 | + attr = dwarf2_attr (type_die, DW_AT_artificial, type_cu); | |
13182 | 13153 | if (attr && DW_UNSND (attr) != 0) |
13183 | - fnp->is_artificial = 1; | |
13154 | + fnfield.is_artificial = 1; | |
13184 | 13155 | |
13185 | - fnp->is_constructor = dwarf2_is_constructor (die, cu); | |
13156 | + fnfield.is_constructor = dwarf2_is_constructor (name_die, type_cu); | |
13186 | 13157 | |
13187 | 13158 | /* Get index in virtual function table if it is a virtual member |
13188 | 13159 | 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, | ||
13190 | 13161 | For everyone else, it is an expression to be evaluated relative |
13191 | 13162 | to the object address. */ |
13192 | 13163 | |
13193 | - attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu); | |
13164 | + attr = dwarf2_attr (type_die, DW_AT_vtable_elem_location, type_cu); | |
13194 | 13165 | if (attr) |
13195 | 13166 | { |
13196 | 13167 | 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, | ||
13198 | 13169 | if (DW_BLOCK (attr)->data[0] == DW_OP_constu) |
13199 | 13170 | { |
13200 | 13171 | /* Old-style GCC. */ |
13201 | - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2; | |
13172 | + fnfield.voffset = decode_locdesc (DW_BLOCK (attr), type_cu) + 2; | |
13202 | 13173 | } |
13203 | 13174 | else if (DW_BLOCK (attr)->data[0] == DW_OP_deref |
13204 | 13175 | || (DW_BLOCK (attr)->size > 1 |
13205 | 13176 | && DW_BLOCK (attr)->data[0] == DW_OP_deref_size |
13206 | - && DW_BLOCK (attr)->data[1] == cu->header.addr_size)) | |
13177 | + && DW_BLOCK (attr)->data[1] == type_cu->header.addr_size)) | |
13207 | 13178 | { |
13208 | - fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu); | |
13209 | - if ((fnp->voffset % cu->header.addr_size) != 0) | |
13179 | + fnfield.voffset = decode_locdesc (DW_BLOCK (attr), type_cu); | |
13180 | + if ((fnfield.voffset % type_cu->header.addr_size) != 0) | |
13210 | 13181 | dwarf2_complex_location_expr_complaint (); |
13211 | 13182 | else |
13212 | - fnp->voffset /= cu->header.addr_size; | |
13213 | - fnp->voffset += 2; | |
13183 | + fnfield.voffset /= type_cu->header.addr_size; | |
13184 | + fnfield.voffset += 2; | |
13214 | 13185 | } |
13215 | 13186 | else |
13216 | 13187 | dwarf2_complex_location_expr_complaint (); |
13217 | 13188 | |
13218 | - if (!fnp->fcontext) | |
13189 | + if (!fnfield.fcontext) | |
13219 | 13190 | { |
13220 | 13191 | /* If there is no `this' field and no DW_AT_containing_type, |
13221 | 13192 | 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, | ||
13226 | 13197 | complaint (&symfile_complaints, |
13227 | 13198 | _("cannot determine context for virtual member " |
13228 | 13199 | "function \"%s\" (offset %d)"), |
13229 | - fieldname, die->offset.sect_off); | |
13200 | + fieldname, type_die->offset.sect_off); | |
13230 | 13201 | } |
13231 | 13202 | else |
13232 | 13203 | { |
13233 | - fnp->fcontext | |
13204 | + fnfield.fcontext | |
13234 | 13205 | = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0)); |
13235 | 13206 | } |
13236 | 13207 | } |
@@ -13247,18 +13218,81 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, | ||
13247 | 13218 | } |
13248 | 13219 | else |
13249 | 13220 | { |
13250 | - attr = dwarf2_attr (die, DW_AT_virtuality, cu); | |
13221 | + attr = dwarf2_attr (type_die, DW_AT_virtuality, type_cu); | |
13251 | 13222 | if (attr && DW_UNSND (attr)) |
13252 | 13223 | { |
13253 | 13224 | /* GCC does this, as of 2008-08-25; PR debug/37237. */ |
13254 | 13225 | complaint (&symfile_complaints, |
13255 | 13226 | _("Member function \"%s\" (offset %d) is virtual " |
13256 | 13227 | "but the vtable offset is not specified"), |
13257 | - fieldname, die->offset.sect_off); | |
13228 | + fieldname, type_die->offset.sect_off); | |
13258 | 13229 | ALLOCATE_CPLUS_STRUCT_TYPE (type); |
13259 | 13230 | TYPE_CPLUS_DYNAMIC (type) = 1; |
13260 | 13231 | } |
13261 | 13232 | } |
13233 | + | |
13234 | + return fnfield; | |
13235 | +} | |
13236 | + | |
13237 | +/* Add a member function to the proper fieldlist. */ | |
13238 | + | |
13239 | +static void | |
13240 | +dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, | |
13241 | + struct type *type, struct dwarf2_cu *cu) | |
13242 | +{ | |
13243 | + struct fnfieldlist *flp; | |
13244 | + int i; | |
13245 | + const char *fieldname, *linkage_name; | |
13246 | + struct nextfnfield *new_fnfield; | |
13247 | + | |
13248 | + if (cu->language == language_ada) | |
13249 | + error (_("unexpected member function in Ada type")); | |
13250 | + | |
13251 | + /* Get name of member function. */ | |
13252 | + fieldname = dwarf2_name (die, cu); | |
13253 | + if (fieldname == NULL) | |
13254 | + return; | |
13255 | + | |
13256 | + /* Look up member function name in fieldlist. */ | |
13257 | + for (i = 0; i < fip->nfnfields; i++) | |
13258 | + { | |
13259 | + if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0) | |
13260 | + break; | |
13261 | + } | |
13262 | + | |
13263 | + /* Create new list element if necessary. */ | |
13264 | + if (i < fip->nfnfields) | |
13265 | + flp = &fip->fnfieldlists[i]; | |
13266 | + else | |
13267 | + { | |
13268 | + if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0) | |
13269 | + { | |
13270 | + fip->fnfieldlists = (struct fnfieldlist *) | |
13271 | + xrealloc (fip->fnfieldlists, | |
13272 | + (fip->nfnfields + DW_FIELD_ALLOC_CHUNK) | |
13273 | + * sizeof (struct fnfieldlist)); | |
13274 | + if (fip->nfnfields == 0) | |
13275 | + make_cleanup (free_current_contents, &fip->fnfieldlists); | |
13276 | + } | |
13277 | + flp = &fip->fnfieldlists[fip->nfnfields]; | |
13278 | + flp->name = fieldname; | |
13279 | + flp->length = 0; | |
13280 | + flp->head = NULL; | |
13281 | + i = fip->nfnfields++; | |
13282 | + } | |
13283 | + | |
13284 | + /* Create a new member function field and chain it to the field list | |
13285 | + entry. */ | |
13286 | + new_fnfield = XNEW (struct nextfnfield); | |
13287 | + make_cleanup (xfree, new_fnfield); | |
13288 | + memset (new_fnfield, 0, sizeof (struct nextfnfield)); | |
13289 | + new_fnfield->next = flp->head; | |
13290 | + flp->head = new_fnfield; | |
13291 | + flp->length++; | |
13292 | + | |
13293 | + /* Fill in the member function field info. */ | |
13294 | + new_fnfield->fnfield = new_fn_field (die, cu, NULL, NULL, type, fieldname, | |
13295 | + flp->length - 1, i); | |
13262 | 13296 | } |
13263 | 13297 | |
13264 | 13298 | /* Create the vector of member function fields, and attach it to the type. */ |