aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog19
-rw-r--r--gdb/dwarf2read.c122
2 files changed, 130 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 5fe8c64..12d2a29 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,22 @@
+2010-08-20 Keith Seitz <keiths@redhat.com>
+
+ PR symtab/11465:
+ * dwarf2read.c (struct delayed_method_info): New struct.
+ (struct dwarf2_cu): Add vector method_list.
+ (scan_partial_symbols): Count methods for union, class, structure,
+ and interface types.
+ (add_to_method_list): New function.
+ (free_delayed_list): New function.
+ (compute_delayed_physnames): New function.
+ (process_full_comp_unit): Make a cleanup for the CU's delayed
+ physname list, compute the delayed physnames, and free the
+ the list.
+ (dwarf2_add_member_fn): For C++ and Java, delay the computation
+ of the physname until after the CU is read.
+
+ * dwarf2read.c (read_structure_type): Check if the current
+ DIE's type was already completed after dwarf2_full_name
+ was called.
2010-08-19 Stan Shebs <stan@codesourcery.com>
* NEWS: Mention some additional changes.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6ea1704..ec623a7 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -266,6 +266,29 @@ struct comp_unit_head
unsigned int first_die_offset;
};
+/* Type used for delaying computation of method physnames.
+ See comments for compute_delayed_physnames. */
+struct delayed_method_info
+{
+ /* The type to which the method is attached, i.e., its parent class. */
+ struct type *type;
+
+ /* The index of the method in the type's function fieldlists. */
+ int fnfield_index;
+
+ /* The index of the method in the fieldlist. */
+ int index;
+
+ /* The name of the DIE. */
+ const char *name;
+
+ /* The DIE associated with this method. */
+ struct die_info *die;
+};
+
+typedef struct delayed_method_info delayed_method_info;
+DEF_VEC_O (delayed_method_info);
+
/* Internal state when decoding a particular compilation unit. */
struct dwarf2_cu
{
@@ -344,6 +367,10 @@ struct dwarf2_cu
/* Header data from the line table, during full symbol processing. */
struct line_header *line_header;
+ /* A list of methods which need to have physnames computed
+ after all type information has been read. */
+ VEC (delayed_method_info) *method_list;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
@@ -1289,6 +1316,9 @@ byte_swap (offset_type value)
/* The suffix for an index file. */
#define INDEX_SUFFIX ".gdb-index"
+static const char *dwarf2_physname (char *name, struct die_info *die,
+ struct dwarf2_cu *cu);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
@@ -4342,6 +4372,56 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
}
}
+/* Add a DIE to the delayed physname list. */
+
+static void
+add_to_method_list (struct type *type, int fnfield_index, int index,
+ const char *name, struct die_info *die,
+ struct dwarf2_cu *cu)
+{
+ struct delayed_method_info mi;
+ mi.type = type;
+ mi.fnfield_index = fnfield_index;
+ mi.index = index;
+ mi.name = name;
+ mi.die = die;
+ VEC_safe_push (delayed_method_info, cu->method_list, &mi);
+}
+
+/* A cleanup for freeing the delayed method list. */
+
+static void
+free_delayed_list (void *ptr)
+{
+ struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr;
+ if (cu->method_list != NULL)
+ {
+ VEC_free (delayed_method_info, cu->method_list);
+ cu->method_list = NULL;
+ }
+}
+
+/* Compute the physnames of any methods on the CU's method list.
+
+ The computation of method physnames is delayed in order to avoid the
+ (bad) condition that one of the method's formal parameters is of an as yet
+ incomplete type. */
+
+static void
+compute_delayed_physnames (struct dwarf2_cu *cu)
+{
+ int i;
+ struct delayed_method_info *mi;
+ for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
+ {
+ char *physname;
+ struct fn_fieldlist *fn_flp
+ = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
+ physname = (char *) dwarf2_physname ((char *) mi->name, mi->die, cu);
+ fn_flp->fn_fields[mi->index].physname = physname ? physname : "";
+ }
+}
+
/* Generate full symbol information for PST and CU, whose DIEs have
already been loaded into memory. */
@@ -4352,13 +4432,14 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
struct objfile *objfile = per_cu->objfile;
CORE_ADDR lowpc, highpc;
struct symtab *symtab;
- struct cleanup *back_to;
+ struct cleanup *back_to, *delayed_list_cleanup;
CORE_ADDR baseaddr;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
buildsym_init ();
back_to = make_cleanup (really_free_pendings, NULL);
+ delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
cu->list_in_scope = &file_symbols;
@@ -4367,6 +4448,12 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
/* Do line number decoding in read_file_scope () */
process_die (cu->dies, cu);
+ /* Now that we have processed all the DIEs in the CU, all the types
+ should be complete, and it should now be safe to compute all of the
+ physnames. */
+ compute_delayed_physnames (cu);
+ do_cleanups (delayed_list_cleanup);
+
/* Some compilers don't define a DW_AT_high_pc attribute for the
compilation unit. If the DW_AT_high_pc is missing, synthesize
it, by scanning the DIE's below the compilation unit. */
@@ -6249,7 +6336,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
int i;
struct fn_field *fnp;
char *fieldname;
- char *physname;
struct nextfnfield *new_fnfield;
struct type *this_type;
@@ -6261,9 +6347,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
if (fieldname == NULL)
return;
- /* Get the mangled name. */
- physname = (char *) dwarf2_physname (fieldname, die, cu);
-
/* Look up member function name in fieldlist. */
for (i = 0; i < fip->nfnfields; i++)
{
@@ -6289,7 +6372,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
flp->name = fieldname;
flp->length = 0;
flp->head = NULL;
- fip->nfnfields++;
+ i = fip->nfnfields++;
}
/* Create a new member function field and chain it to the field list
@@ -6303,9 +6386,19 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
/* Fill in the member function field info. */
fnp = &new_fnfield->fnfield;
- /* The name is already allocated along with this objfile, so we don't
- need to duplicate it for the type. */
- fnp->physname = physname ? physname : "";
+
+ /* Delay processing of the physname until later. */
+ if (cu->language == language_cplus || cu->language == language_java)
+ {
+ add_to_method_list (type, i, flp->length - 1, fieldname,
+ die, cu);
+ }
+ else
+ {
+ char *physname = (char *) dwarf2_physname (fieldname, die, cu);
+ fnp->physname = physname ? physname : "";
+ }
+
fnp->type = alloc_type (objfile);
this_type = read_type_die (die, cu);
if (this_type && TYPE_CODE (this_type) == TYPE_CODE_FUNC)
@@ -6331,7 +6424,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
}
else
complaint (&symfile_complaints, _("member function type missing for '%s'"),
- physname);
+ dwarf2_full_name (fieldname, die, cu));
/* Get fcontext from DW_AT_containing_type if present. */
if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
@@ -6579,7 +6672,14 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
if (cu->language == language_cplus
|| cu->language == language_java)
{
- TYPE_TAG_NAME (type) = (char *) dwarf2_full_name (name, die, cu);
+ char *full_name = (char *) dwarf2_full_name (name, die, cu);
+
+ /* dwarf2_full_name might have already finished building the DIE's
+ type. If so, there is no need to continue. */
+ if (get_die_type (die, cu) != NULL)
+ return get_die_type (die, cu);
+
+ TYPE_TAG_NAME (type) = full_name;
if (die->tag == DW_TAG_structure_type
|| die->tag == DW_TAG_class_type)
TYPE_NAME (type) = TYPE_TAG_NAME (type);