diff options
author | David Carlton <carlton@bactrian.org> | 2003-05-16 23:32:27 +0000 |
---|---|---|
committer | David Carlton <carlton@bactrian.org> | 2003-05-16 23:32:27 +0000 |
commit | ec153107db6dd8b739f5d270196a5a39b1b14d4f (patch) | |
tree | 50fe33836f3d7acd5a137533abe43e272223e2d3 | |
parent | 7ac041296192ab212ed91e5e755ff8b893c1213d (diff) | |
download | gdb-ec153107db6dd8b739f5d270196a5a39b1b14d4f.zip gdb-ec153107db6dd8b739f5d270196a5a39b1b14d4f.tar.gz gdb-ec153107db6dd8b739f5d270196a5a39b1b14d4f.tar.bz2 |
2003-05-16 David Carlton <carlton@bactrian.org>
* dwarf2read.c (read_comp_unit): Separate code out into
read_die_and_children and read_die_and_siblings.
(read_die_and_children): New.
(read_die_and_siblings): New.
(read_full_die): Add HAS_CHILDREN argument.
struct die_info: Delete HAS_CHILDREN, NEXT members; add CHILD,
SIBLING, PARENT members.
(psymtab_to_symtab_1): Use new members of struct die_info.
(process_die, read_file_scope, read_func_scope)
(read_lexical_block_scope, read_structure_scope, read_enumeration)
(read_array_type, read_common_block, read_namespace)
(read_subroutine_type, read_die_and_children, free_die_list)
(dump_die, dump_die_list): Ditto.
(read_namespace): Separate code out into namespace_name.
(namespace_name): New.
(typename_concat): New.
(determine_prefix): New.
(read_type_die): Set prefix appropriately.
(class_name): New.
2003-05-16 David Carlton <carlton@bactrian.org>
* gdb.c++/rtti.exp: Convert the gdb/488 kfail into a fail, and
delete the <.*BaseN> branches.
-rw-r--r-- | gdb/ChangeLog | 22 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 357 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.c++/rtti.exp | 15 |
4 files changed, 277 insertions, 122 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b160201..cdaf889 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2003-05-16 David Carlton <carlton@bactrian.org> + + * dwarf2read.c (read_comp_unit): Separate code out into + read_die_and_children and read_die_and_siblings. + (read_die_and_children): New. + (read_die_and_siblings): New. + (read_full_die): Add HAS_CHILDREN argument. + struct die_info: Delete HAS_CHILDREN, NEXT members; add CHILD, + SIBLING, PARENT members. + (psymtab_to_symtab_1): Use new members of struct die_info. + (process_die, read_file_scope, read_func_scope) + (read_lexical_block_scope, read_structure_scope, read_enumeration) + (read_array_type, read_common_block, read_namespace) + (read_subroutine_type, read_die_and_children, free_die_list) + (dump_die, dump_die_list): Ditto. + (read_namespace): Separate code out into namespace_name. + (namespace_name): New. + (typename_concat): New. + (determine_prefix): New. + (read_type_die): Set prefix appropriately. + (class_name): New. + 2003-05-09 David Carlton <carlton@bactrian.org> * linespec.c (examine_compound_token): Handled classes nested diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 65b4e26..247ea47 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -316,13 +316,14 @@ struct attr_abbrev struct die_info { enum dwarf_tag tag; /* Tag indicating type of die */ - unsigned short has_children; /* Does the die have children */ unsigned int abbrev; /* Abbrev number */ unsigned int offset; /* Offset in .debug_info section */ unsigned int num_attrs; /* Number of attributes */ struct attribute *attrs; /* An array of attributes */ struct die_info *next_ref; /* Next die in ref hash table */ - struct die_info *next; /* Next die in linked list */ + struct die_info *child; /* Its first child, if any. */ + struct die_info *sibling; /* Its next sibling, if any. */ + struct die_info *parent; /* Its parent, if any. */ struct type *type; /* Cached type information */ }; @@ -731,7 +732,7 @@ static char *read_partial_die (struct partial_die_info *, const struct comp_unit_head *); static char *read_full_die (struct die_info **, bfd *, char *, - const struct comp_unit_head *); + const struct comp_unit_head *, int *); static char *read_attribute (struct attribute *, struct attr_abbrev *, bfd *, char *, const struct comp_unit_head *); @@ -813,6 +814,12 @@ static struct type *tag_type_to_type (struct die_info *, struct objfile *, static void read_type_die (struct die_info *, struct objfile *, const struct comp_unit_head *); +static char *determine_prefix (struct die_info *die); + +static char *typename_concat (const char *prefix, const char *suffix); + +static char *class_name (struct die_info *die); + static void read_typedef (struct die_info *, struct objfile *, const struct comp_unit_head *); @@ -854,6 +861,9 @@ static void read_common_block (struct die_info *, struct objfile *, static void read_namespace (struct die_info *die, struct objfile *objfile, const struct comp_unit_head *cu_header); +static const char *namespace_name (struct die_info *die, + int *is_anonymous); + static void read_enumeration (struct die_info *, struct objfile *, const struct comp_unit_head *); @@ -888,6 +898,16 @@ static void read_subroutine_type (struct die_info *, struct objfile *, static struct die_info *read_comp_unit (char *, bfd *, const struct comp_unit_head *); +static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd, + const struct comp_unit_head *, + char **new_info_ptr, + struct die_info *parent); + +static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd, + const struct comp_unit_head *, + char **new_info_ptr, + struct die_info *parent); + static void free_die_list (struct die_info *); static struct cleanup *make_cleanup_free_die_list (struct die_info *); @@ -1941,9 +1961,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) the compilation unit. If the DW_AT_high_pc is missing, synthesize it, by scanning the DIE's below the compilation unit. */ highpc = 0; - if (dies->has_children) + if (dies->child != NULL) { - child_die = dies->next; + child_die = dies->child; while (child_die && child_die->tag) { if (child_die->tag == DW_TAG_subprogram) @@ -2053,7 +2073,7 @@ process_die (struct die_info *die, struct objfile *objfile, Fortran case, so we'll have to replace this gdb_assert if Fortran compilers start generating that info. */ processing_has_namespace_info = 1; - gdb_assert (!die->has_children); + gdb_assert (die->child == NULL); break; default: new_symbol (die, NULL, objfile, cu_header); @@ -2083,9 +2103,9 @@ read_file_scope (struct die_info *die, struct objfile *objfile, if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header)) { - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { if (child_die->tag == DW_TAG_subprogram) @@ -2162,9 +2182,9 @@ read_file_scope (struct die_info *die, struct objfile *objfile, initialize_cu_func_list (); /* Process all dies in compilation unit. */ - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { process_die (child_die, objfile, cu_header); @@ -2302,9 +2322,9 @@ read_func_scope (struct die_info *die, struct objfile *objfile, list_in_scope = &local_symbols; - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { process_die (child_die, objfile, cu_header); @@ -2352,9 +2372,9 @@ read_lexical_block_scope (struct die_info *die, struct objfile *objfile, highpc += baseaddr; push_context (0, lowpc); - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { process_die (child_die, objfile, cu_header); @@ -3043,7 +3063,7 @@ read_structure_scope (struct die_info *die, struct objfile *objfile, type within the structure itself. */ die->type = type; - if (die->has_children && ! die_is_declaration (die)) + if (die->child != NULL && ! die_is_declaration (die)) { struct field_info fi; struct die_info *child_die; @@ -3051,7 +3071,7 @@ read_structure_scope (struct die_info *die, struct objfile *objfile, memset (&fi, 0, sizeof (struct field_info)); - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { @@ -3233,9 +3253,9 @@ read_enumeration (struct die_info *die, struct objfile *objfile, num_fields = 0; fields = NULL; - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { if (child_die->tag != DW_TAG_enumerator) @@ -3314,7 +3334,7 @@ read_array_type (struct die_info *die, struct objfile *objfile, /* Irix 6.2 native cc creates array types without children for arrays with unspecified length. */ - if (die->has_children == 0) + if (die->child == NULL) { index_type = dwarf2_fundamental_type (objfile, FT_INTEGER); range_type = create_range_type (NULL, index_type, 0, -1); @@ -3323,7 +3343,7 @@ read_array_type (struct die_info *die, struct objfile *objfile, } back_to = make_cleanup (null_cleanup, NULL); - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { if (child_die->tag == DW_TAG_subrange_type) @@ -3469,9 +3489,9 @@ read_common_block (struct die_info *die, struct objfile *objfile, "common block member"); } } - if (die->has_children) + if (die->child != NULL) { - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { sym = new_symbol (child_die, NULL, objfile, cu_header); @@ -3494,26 +3514,11 @@ read_namespace (struct die_info *die, struct objfile *objfile, const struct comp_unit_head *cu_header) { const char *previous_prefix = processing_current_prefix; - const char *name = NULL; + const char *name; int is_anonymous; struct die_info *current_die; - /* Loop through the extensions until we find a name. */ - - for (current_die = die; - current_die != NULL; - current_die = dwarf2_extension (die)) - { - name = dwarf2_name (current_die); - if (name != NULL) - break; - } - - /* Is it an anonymous namespace? */ - - is_anonymous = (name == NULL); - if (is_anonymous) - name = "(anonymous namespace)"; + name = namespace_name (die, &is_anonymous); /* Now build the name of the current namespace. */ @@ -3542,9 +3547,9 @@ read_namespace (struct die_info *die, struct objfile *objfile, strlen (previous_prefix), strlen (processing_current_prefix)); - if (die->has_children) + if (die->child != NULL) { - struct die_info *child_die = die->next; + struct die_info *child_die = die->child; while (child_die && child_die->tag) { @@ -3556,6 +3561,32 @@ read_namespace (struct die_info *die, struct objfile *objfile, processing_current_prefix = previous_prefix; } +static const char * +namespace_name (struct die_info *die, int *is_anonymous) +{ + struct die_info *current_die; + const char *name = NULL; + + /* Loop through the extensions until we find a name. */ + + for (current_die = die; + current_die != NULL; + current_die = dwarf2_extension (die)) + { + name = dwarf2_name (current_die); + if (name != NULL) + break; + } + + /* Is it an anonymous namespace? */ + + *is_anonymous = (name == NULL); + if (*is_anonymous) + name = "(anonymous namespace)"; + + return name; +} + /* Extract all information from a DW_TAG_pointer_type DIE and add to the user defined type vector. */ @@ -3779,7 +3810,7 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile, || cu_language == language_cplus) TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; - if (die->has_children) + if (die->child != NULL) { struct die_info *child_die; int nparams = 0; @@ -3788,7 +3819,7 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile, /* Count the number of parameters. FIXME: GDB currently ignores vararg functions, but knows about vararg member functions. */ - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { if (child_die->tag == DW_TAG_formal_parameter) @@ -3803,7 +3834,7 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile, TYPE_FIELDS (ftype) = (struct field *) TYPE_ALLOC (ftype, nparams * sizeof (struct field)); - child_die = die->next; + child_die = die->child; while (child_die && child_die->tag) { if (child_die->tag == DW_TAG_formal_parameter) @@ -3935,46 +3966,82 @@ static struct die_info * read_comp_unit (char *info_ptr, bfd *abfd, const struct comp_unit_head *cu_header) { - struct die_info *first_die, *last_die, *die; - char *cur_ptr; - int nesting_level; - /* Reset die reference table; we are building new ones now. */ dwarf2_empty_hash_tables (); + return read_die_and_children (info_ptr, abfd, cu_header, &info_ptr, NULL); +} + +/* Read a single die and all its descendents. */ + +static struct die_info * +read_die_and_children (char *info_ptr, bfd *abfd, + const struct comp_unit_head *cu_header, + char **new_info_ptr, + struct die_info *parent) +{ + struct die_info *die; + char *cur_ptr; + int has_children; + + cur_ptr = read_full_die (&die, abfd, info_ptr, cu_header, &has_children); + store_in_ref_table (die->offset, die); + + if (has_children) + { + die->child = read_die_and_siblings (cur_ptr, abfd, cu_header, + new_info_ptr, die); + } + else + { + die->child = NULL; + *new_info_ptr = cur_ptr; + } + + die->sibling = NULL; + die->parent = parent; + return die; +} + +/* Helper function for read_comp_unit; it reads in a die, all of its + descendents, and all of its siblings. */ + +static struct die_info * +read_die_and_siblings (char *info_ptr, bfd *abfd, + const struct comp_unit_head *cu_header, + char **new_info_ptr, + struct die_info *parent) +{ + struct die_info *first_die, *last_sibling, *die; + char *cur_ptr; + cur_ptr = info_ptr; - nesting_level = 0; - first_die = last_die = NULL; - do + first_die = last_sibling = NULL; + + while (1) { - cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header); - if (die->has_children) + die = read_die_and_children (cur_ptr, abfd, cu_header, &cur_ptr, parent); + + if (!first_die) { - nesting_level++; + first_die = die; } - if (die->tag == 0) + else { - nesting_level--; + last_sibling->sibling = die; } - die->next = NULL; - - /* Enter die in reference hash table */ - store_in_ref_table (die->offset, die); - - if (!first_die) + if (die->tag == 0) { - first_die = last_die = die; + *new_info_ptr = cur_ptr; + return first_die; } else { - last_die->next = die; - last_die = die; + last_sibling = die; } } - while (nesting_level > 0); - return first_die; } /* Free a linked list of dies. */ @@ -3987,7 +4054,9 @@ free_die_list (struct die_info *dies) die = dies; while (die) { - next = die->next; + if (die->child != NULL) + free_die_list (die->child); + next = die->sibling; xfree (die->attrs); xfree (die); die = next; @@ -4301,12 +4370,13 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd, return info_ptr; } -/* Read the die from the .debug_info section buffer. And set diep to - point to a newly allocated die with its information. */ +/* Read the die from the .debug_info section buffer. Set DIEP to + point to a newly allocated die with its information, and set + HAS_CHILDREN to tell whether the die has children or not. */ static char * read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, int *has_children) { unsigned int abbrev_number, bytes_read, i, offset; struct abbrev_info *abbrev; @@ -4322,6 +4392,7 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, die->abbrev = abbrev_number; die->type = NULL; *diep = die; + *has_children = 0; return info_ptr; } @@ -4334,7 +4405,6 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, die = dwarf_alloc_die (); die->offset = offset; die->tag = abbrev->tag; - die->has_children = abbrev->has_children; die->abbrev = abbrev_number; die->type = NULL; @@ -4349,6 +4419,7 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr, } *diep = die; + *has_children = abbrev->has_children; return info_ptr; } @@ -5869,6 +5940,11 @@ static void read_type_die (struct die_info *die, struct objfile *objfile, const struct comp_unit_head *cu_header) { + char *prefix = determine_prefix (die); + const char *old_prefix = processing_current_prefix; + struct cleanup *back_to = make_cleanup (xfree, prefix); + processing_current_prefix = prefix; + switch (die->tag) { case DW_TAG_class_type: @@ -5915,8 +5991,100 @@ read_type_die (struct die_info *die, struct objfile *objfile, dwarf_tag_name (die->tag)); break; } + + processing_current_prefix = old_prefix; + do_cleanups (back_to); +} + +/* Determine the name of the namespace/class that DIE is defined + within, or NULL if we can't tell. The caller should xfree the + result. */ + +static char * +determine_prefix (struct die_info *die) +{ + struct die_info *parent; + + if (cu_language != language_cplus) + return NULL; + + parent = die->parent; + + if (parent == NULL) + { + return (processing_has_namespace_info ? xstrdup ("") : NULL); + } + else + { + char *parent_prefix = determine_prefix (parent); + + switch (parent->tag) { + case DW_TAG_namespace: + { + int dummy; + + return typename_concat (parent_prefix, + namespace_name (parent, &dummy)); + } + case DW_TAG_class_type: + case DW_TAG_structure_type: + { + + if (parent_prefix != NULL) + return typename_concat (parent_prefix, dwarf2_name (parent)); + else + return class_name (parent); + } + default: + return parent_prefix; + } + } +} + +/* Return a newly-allocated string formed by concatenating PREFIX, + "::", and SUFFIX, except that if PREFIX is NULL or the empty + string, just return a copy of SUFFIX. */ + +static char * +typename_concat (const char *prefix, const char *suffix) +{ + if (prefix == NULL || prefix[0] == '\0') + return xstrdup (suffix); + else + { + char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1); + + strcpy (retval, prefix); + strcat (retval, "::"); + strcat (retval, suffix); + + return retval; + } } +/* Return a newly-allocated string giving the name of the class given + by DIE. */ + +static char * +class_name (struct die_info *die) +{ + struct die_info *child; + const char *name; + + for (child = die->child; child != NULL; child = sibling_die (child)) + { + if (child->tag == DW_TAG_subprogram) + return class_name_from_physname (dwarf2_linkage_name (child)); + } + + name = dwarf2_name (die); + if (name != NULL) + return xstrdup (name); + else + return xstrdup (""); +} + + static struct type * dwarf_base_type (int encoding, int size, struct objfile *objfile) { @@ -6031,43 +6199,7 @@ copy_die (struct die_info *old_die) static struct die_info * sibling_die (struct die_info *die) { - int nesting_level = 0; - - if (!die->has_children) - { - if (die->next && (die->next->tag == 0)) - { - return NULL; - } - else - { - return die->next; - } - } - else - { - do - { - if (die->has_children) - { - nesting_level++; - } - if (die->tag == 0) - { - nesting_level--; - } - die = die->next; - } - while (nesting_level); - if (die && (die->tag == 0)) - { - return NULL; - } - else - { - return die; - } - } + return die->sibling; } /* Get linkage name of a die, return NULL if not found. */ @@ -6936,7 +7068,7 @@ dump_die (struct die_info *die) fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n", dwarf_tag_name (die->tag), die->abbrev, die->offset); fprintf_unfiltered (gdb_stderr, "\thas children: %s\n", - dwarf_bool_name (die->has_children)); + dwarf_bool_name (die->child != NULL)); fprintf_unfiltered (gdb_stderr, "\tattributes:\n"); for (i = 0; i < die->num_attrs; ++i) @@ -6999,7 +7131,10 @@ dump_die_list (struct die_info *die) while (die) { dump_die (die); - die = die->next; + if (die->child != NULL) + dump_die_list (die->child); + if (die->sibling != NULL) + dump_die_list (die->sibling); } } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 8f67f2e..0410311 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2003-05-16 David Carlton <carlton@bactrian.org> + * gdb.c++/rtti.exp: Convert the gdb/488 kfail into a fail, and + delete the <.*BaseN> branches. + +2003-05-16 David Carlton <carlton@bactrian.org> + * carlton_runnamespace: Run gdb.c++/rtti.exp, too. * carlton_runtest (FASTTESTS): Add gdb.c++/breakpoint.exp and gdb.c++/rtti.exp. diff --git a/gdb/testsuite/gdb.c++/rtti.exp b/gdb/testsuite/gdb.c++/rtti.exp index e968e80..1bc9b7a 100644 --- a/gdb/testsuite/gdb.c++/rtti.exp +++ b/gdb/testsuite/gdb.c++/rtti.exp @@ -83,17 +83,12 @@ gdb_continue_to_breakpoint "end of constructors" gdb_test_multiple "print *e1" "print *e1" { -re "warning: can't find class named `n1::D1', as given by C\\+\\+ RTTI.*$gdb_prompt $" { - kfail "gdb/488" "print *e1" + #kfail "gdb/488" "print *e1" + fail "print *e1" } -re "\\$\[0-9\]* = {<n1::Base1> = .*}\r\n$gdb_prompt $" { pass "print *e1" } - -re "\\$\[0-9\]* = {<.*Base1> = .*}\r\n$gdb_prompt $" { - # NOTE: carlton/2003-05-09: Sometimes, the DWARF reader gets - # confused about names. I've seen just Base1 or - # n1::D1::C1::Base1. - kfail "gdb/TBA" "print *e2" - } } # NOTE: carlton/2003-05-02: This test fails on my branch because, @@ -106,7 +101,8 @@ gdb_test_multiple "print *e1" "print *e1" { gdb_test_multiple "print *e2" "print *e2" { -re "warning: can't find class named `n2::D2', as given by C\\+\\+ RTTI.*$gdb_prompt $" { - kfail "gdb/488" "print *e2" + #kfail "gdb/488" "print *e2" + fail "print *e2" } -re "\\$\[0-9\]* = <incomplete type>\r\n$gdb_prompt $" { kfail "gdb/TBA" "print *e2" @@ -114,9 +110,6 @@ gdb_test_multiple "print *e2" "print *e2" { -re "\\$\[0-9\]* = {<n2::Base2> = .*}\r\n$gdb_prompt $" { pass "print *e2" } - -re "\\$\[0-9\]* = {<.*Base2> = .*}\r\n$gdb_prompt $" { - kfail "gdb/TBA" "print *e2" - } } gdb_exit |