diff options
author | David Carlton <carlton@bactrian.org> | 2004-01-14 16:54:43 +0000 |
---|---|---|
committer | David Carlton <carlton@bactrian.org> | 2004-01-14 16:54:43 +0000 |
commit | 63d06c5c42c2367dcafe44679742b5435463418b (patch) | |
tree | 3b8ffe8095efd54a0b6d13ade03177bd8dbcf216 /gdb/dwarf2read.c | |
parent | a51dab8874fc8a1775adc510e9f867270966805e (diff) | |
download | gdb-63d06c5c42c2367dcafe44679742b5435463418b.zip gdb-63d06c5c42c2367dcafe44679742b5435463418b.tar.gz gdb-63d06c5c42c2367dcafe44679742b5435463418b.tar.bz2 |
2004-01-14 David Carlton <carlton@kealia.com>
Change symbols for C++ nested types to contain the fully qualified
name, if possible. (At least in the DWARF-2 case.) Partial fix
for PR's c++/57, c++/488, c++/539, c++/573, c++/609, c++/832,
c++/895.
* c-exp.y: Update copyright:
(qualified_type): Handle types nested within classes.
* cp-namespace.c: Update comments.
(cp_set_block_scope): Delete #if 0.
(cp_lookup_nested_type): Handle types nested within classes.
* dwarf2read.c: (scan_partial_symbols): Call add_partial_structure
when appropriate.
(add_partial_symbol): Add the name of the enclosing namespace to
types.
(pdi_needs_namespace): New.
(add_partial_namespace): Tweak comment.
(add_partial_structure): New.
(psymtab_to_symtab_1): Initialize processing_current_prefix
here...
(process_die): instead of here.
(read_structure_scope): Try to figure out the name of the class or
namespace that the structure might be defined within.
(read_enumeration): Generate fully-qualified names, if possible.
(read_namespace): Don't set name to NULL.
(die_specification): New.
(new_symbol): Generate fully-qualified names for types.
(read_type_die): Determine appropriate prefix.
(determine_prefix): New.
(typename_concat): New.
(class_name): New.
* valops.c: Update copyright.
(value_aggregate_elt): Pass NOSIDE to
value_struct_elt_for_reference.
(value_struct_elt_for_reference): Make static, add NOSIDE
parameter, call value_maybe_namespace_elt as a last resort.
(value_namespace_elt): Break out code into
value_maybe_namespace_elt.
(value_maybe_namespace_elt): New.
2004-01-14 David Carlton <carlton@kealia.com>
* gdb.cp/namespace.exp: Add tests involving classes defined within
namespaces.
* gdb.cp/namespace.cc (C::CClass): New.
* gdb.cp/namespace1.cc: Update copyright.
(C::OtherFileClass): New.
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 481 |
1 files changed, 441 insertions, 40 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 765ac7d..b2c34a5 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -666,12 +666,19 @@ static char *scan_partial_symbols (char *, CORE_ADDR *, CORE_ADDR *, static void add_partial_symbol (struct partial_die_info *, struct dwarf2_cu *, const char *namespace); +static int pdi_needs_namespace (enum dwarf_tag tag, const char *namespace); + static char *add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, CORE_ADDR *lowpc, CORE_ADDR *highpc, struct dwarf2_cu *cu, const char *namespace); +static char *add_partial_structure (struct partial_die_info *struct_pdi, + char *info_ptr, + struct dwarf2_cu *cu, + const char *namespace); + static char *add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, struct dwarf2_cu *cu, @@ -743,6 +750,8 @@ static struct attribute *dwarf_attr (struct die_info *, unsigned int); static int die_is_declaration (struct die_info *); +static struct die_info *die_specification (struct die_info *die); + static void free_line_header (struct line_header *lh); static struct line_header *(dwarf_decode_line_header @@ -777,6 +786,12 @@ static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *); static void read_type_die (struct die_info *, struct dwarf2_cu *); +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 dwarf2_cu *); static void read_base_type (struct die_info *, struct dwarf2_cu *); @@ -1368,11 +1383,18 @@ scan_partial_symbols (char *info_ptr, CORE_ADDR *lowpc, case DW_TAG_variable: case DW_TAG_typedef: case DW_TAG_union_type: + if (!pdi.is_declaration) + { + add_partial_symbol (&pdi, cu, namespace); + } + break; case DW_TAG_class_type: case DW_TAG_structure_type: if (!pdi.is_declaration) { - add_partial_symbol (&pdi, cu, namespace); + info_ptr = add_partial_structure (&pdi, info_ptr, cu, + namespace); + info_ptr_updated = 1; } break; case DW_TAG_enumeration_type: @@ -1430,6 +1452,17 @@ add_partial_symbol (struct partial_die_info *pdi, char *actual_name = pdi->name; const struct partial_symbol *psym = NULL; + /* If we're not in the global namespace and if the namespace name + isn't encoded in a mangled actual_name, add it. */ + + if (pdi_needs_namespace (pdi->tag, namespace)) + { + actual_name = alloca (strlen (pdi->name) + 2 + strlen (namespace) + 1); + strcpy (actual_name, namespace); + strcat (actual_name, "::"); + strcat (actual_name, pdi->name); + } + switch (pdi->tag) { case DW_TAG_subprogram: @@ -1507,11 +1540,15 @@ add_partial_symbol (struct partial_die_info *pdi, case DW_TAG_enumeration_type: /* Skip aggregate types without children, these are external references. */ + /* NOTE: carlton/2003-10-07: See comment in new_symbol about + static vs. global. */ if (pdi->has_children == 0) return; add_psymbol_to_list (actual_name, strlen (actual_name), STRUCT_DOMAIN, LOC_TYPEDEF, - &objfile->static_psymbols, + cu_language == language_cplus + ? &objfile->global_psymbols + : &objfile->static_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); if (cu_language == language_cplus) @@ -1519,14 +1556,16 @@ add_partial_symbol (struct partial_die_info *pdi, /* For C++, these implicitly act as typedefs as well. */ add_psymbol_to_list (actual_name, strlen (actual_name), VAR_DOMAIN, LOC_TYPEDEF, - &objfile->static_psymbols, + &objfile->global_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); } break; case DW_TAG_enumerator: add_psymbol_to_list (actual_name, strlen (actual_name), VAR_DOMAIN, LOC_CONST, - &objfile->static_psymbols, + cu_language == language_cplus + ? &objfile->static_psymbols + : &objfile->global_psymbols, 0, (CORE_ADDR) 0, cu_language, objfile); break; default: @@ -1547,6 +1586,30 @@ add_partial_symbol (struct partial_die_info *pdi, objfile); } +/* Determine whether a die of type TAG living in the C++ namespace + NAMESPACE needs to have the name of the namespace prepended to the + name listed in the die. */ + +static int +pdi_needs_namespace (enum dwarf_tag tag, const char *namespace) +{ + if (namespace == NULL || namespace[0] == '\0') + return 0; + + switch (tag) + { + case DW_TAG_typedef: + case DW_TAG_class_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + case DW_TAG_enumerator: + return 1; + default: + return 0; + } +} + /* Read a partial die corresponding to a namespace; also, add a symbol corresponding to that namespace to the symbol table. NAMESPACE is the name of the enclosing namespace. */ @@ -1570,9 +1633,10 @@ add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, strcat (full_name, "::"); strcat (full_name, new_name); - /* FIXME: carlton/2003-06-27: Once we build qualified names for more - symbols than just namespaces, we should replace this by a call to - add_partial_symbol. */ + /* FIXME: carlton/2003-10-07: We can't just replace this by a call + to add_partial_symbol, because we don't have a way to pass in the + full name to that function; that might be a flaw in + add_partial_symbol's interface. */ add_psymbol_to_list (full_name, strlen (full_name), VAR_DOMAIN, LOC_TYPEDEF, @@ -1587,6 +1651,63 @@ add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, return info_ptr; } +/* Read a partial die corresponding to a class or structure. */ + +static char * +add_partial_structure (struct partial_die_info *struct_pdi, char *info_ptr, + struct dwarf2_cu *cu, + const char *namespace) +{ + bfd *abfd = cu->objfile->obfd; + char *actual_class_name = NULL; + + if (cu_language == language_cplus + && namespace == NULL + && struct_pdi->name != NULL + && struct_pdi->has_children) + { + /* We don't have namespace debugging information, so see if we + can figure out if this structure lives in a namespace. Look + for a member function; its demangled name will contain + namespace info, if there is any. */ + + /* NOTE: carlton/2003-10-07: Getting the info this way changes + what template types look like, because the demangler + frequently doesn't give the same name as the debug info. We + could fix this by only using the demangled name to get the + prefix (but see comment in read_structure_scope). */ + + char *next_child = info_ptr; + + while (1) + { + struct partial_die_info child_pdi; + + next_child = read_partial_die (&child_pdi, abfd, next_child, + cu); + if (!child_pdi.tag) + break; + if (child_pdi.tag == DW_TAG_subprogram) + { + actual_class_name = class_name_from_physname (child_pdi.name); + if (actual_class_name != NULL) + struct_pdi->name = actual_class_name; + break; + } + else + { + next_child = locate_pdi_sibling (&child_pdi, next_child, + abfd, cu); + } + } + } + + add_partial_symbol (struct_pdi, cu, namespace); + xfree(actual_class_name); + + return locate_pdi_sibling (struct_pdi, info_ptr, abfd, cu); +} + /* Read a partial die corresponding to an enumeration type. */ static char * @@ -1711,6 +1832,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; + /* We're in the global namespace. */ + processing_current_prefix = ""; + obstack_init (&dwarf2_tmp_obstack); back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); @@ -1864,11 +1988,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_common_inclusion: break; case DW_TAG_namespace: - if (!processing_has_namespace_info) - { - processing_has_namespace_info = 1; - processing_current_prefix = ""; - } + processing_has_namespace_info = 1; read_namespace (die, cu); break; case DW_TAG_imported_declaration: @@ -1879,11 +1999,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) shouldn't in the C++ case, but conceivably could in the Fortran case, so we'll have to replace this gdb_assert if Fortran compilers start generating that info. */ - if (!processing_has_namespace_info) - { - processing_has_namespace_info = 1; - processing_current_prefix = ""; - } + processing_has_namespace_info = 1; gdb_assert (die->child == NULL); break; default: @@ -2777,6 +2893,13 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) struct objfile *objfile = cu->objfile; struct type *type; struct attribute *attr; + const char *name = NULL; + const char *previous_prefix = processing_current_prefix; + struct cleanup *back_to = NULL; + /* This says whether or not we want to try to update the structure's + name to include enclosing namespace/class information, if + any. */ + int need_to_update_name = 0; type = alloc_type (objfile); @@ -2784,9 +2907,41 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf_attr (die, DW_AT_name); if (attr && DW_STRING (attr)) { - TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), - strlen (DW_STRING (attr)), - &objfile->type_obstack); + name = DW_STRING (attr); + + if (cu_language == language_cplus) + { + struct die_info *spec_die = die_specification (die); + + if (spec_die != NULL) + { + char *specification_prefix = determine_prefix (spec_die); + processing_current_prefix = specification_prefix; + back_to = make_cleanup (xfree, specification_prefix); + } + } + + if (processing_has_namespace_info) + { + /* FIXME: carlton/2003-11-10: This variable exists only for + const-correctness reasons. When I tried to change + TYPE_TAG_NAME to be a const char *, I ran into a cascade + of changes which would have forced decode_line_1 to take + a const char **. */ + char *new_prefix = obconcat (&objfile->type_obstack, + processing_current_prefix, + processing_current_prefix[0] == '\0' + ? "" : "::", + name); + TYPE_TAG_NAME (type) = new_prefix; + processing_current_prefix = new_prefix; + } + else + { + TYPE_TAG_NAME (type) = obsavestring (name, strlen (name), + &objfile->type_obstack); + need_to_update_name = (cu_language == language_cplus); + } } if (die->tag == DW_TAG_structure_type) @@ -2846,6 +3001,41 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) /* C++ member function. */ process_die (child_die, cu); dwarf2_add_member_fn (&fi, child_die, type, cu); + if (need_to_update_name) + { + /* The demangled names of member functions contain + information about enclosing namespaces/classes, + if any. */ + + /* FIXME: carlton/2003-11-10: The excessive + demangling here is a bit wasteful, as is the + memory usage for names. */ + + /* NOTE: carlton/2003-11-10: As commented in + add_partial_structure, the demangler sometimes + prints the type info in a different form from the + debug info. We could solve this by using the + demangled name to get the prefix; if doing so, + however, we'd need to be careful when reading a + class that's nested inside a template class. + That would also cause problems when trying to + determine RTTI information, since we use the + demangler to determine the appropriate class + name. */ + char *actual_class_name + = class_name_from_physname (dwarf2_linkage_name + (child_die)); + if (actual_class_name != NULL + && strcmp (actual_class_name, name) != 0) + { + TYPE_TAG_NAME (type) + = obsavestring (actual_class_name, + strlen (actual_class_name), + &objfile->type_obstack); + } + xfree (actual_class_name); + need_to_update_name = 0; + } } else if (child_die->tag == DW_TAG_inheritance) { @@ -2921,6 +3111,10 @@ read_structure_scope (struct die_info *die, struct dwarf2_cu *cu) /* No children, must be stub. */ TYPE_FLAGS (type) |= TYPE_FLAG_STUB; } + + processing_current_prefix = previous_prefix; + if (back_to != NULL) + do_cleanups (back_to); } /* Given a pointer to a die which begins an enumeration, process all @@ -2950,9 +3144,21 @@ read_enumeration (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf_attr (die, DW_AT_name); if (attr && DW_STRING (attr)) { - TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr), - strlen (DW_STRING (attr)), - &objfile->type_obstack); + const char *name = DW_STRING (attr); + + if (processing_has_namespace_info) + { + TYPE_TAG_NAME (type) = obconcat (&objfile->type_obstack, + processing_current_prefix, + processing_current_prefix[0] == '\0' + ? "" : "::", + name); + } + else + { + TYPE_TAG_NAME (type) = obsavestring (name, strlen (name), + &objfile->type_obstack); + } } attr = dwarf_attr (die, DW_AT_byte_size); @@ -3223,7 +3429,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; const char *previous_prefix = processing_current_prefix; - const char *name = NULL; + const char *name; int is_anonymous; struct die_info *current_die; @@ -4679,6 +4885,19 @@ die_is_declaration (struct die_info *die) && ! dwarf_attr (die, DW_AT_specification)); } +/* Return the die giving the specification for DIE, if there is + one. */ + +static struct die_info * +die_specification (struct die_info *die) +{ + struct attribute *spec_attr = dwarf_attr (die, DW_AT_specification); + + if (spec_attr == NULL) + return NULL; + else + return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr)); +} /* Free the line_header structure *LH, and any arrays and strings it refers to. */ @@ -5322,39 +5541,108 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu) case DW_TAG_enumeration_type: SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; - add_symbol_to_list (sym, list_in_scope); - /* The semantics of C++ state that "struct foo { ... }" also - defines a typedef for "foo". Synthesize a typedef symbol so - that "ptype foo" works as expected. */ + /* Make sure that the symbol includes appropriate enclosing + classes/namespaces in its name. These are calculated in + read_structure_scope, and the correct name is saved in + the type. */ + if (cu_language == language_cplus) { - struct symbol *typedef_sym = (struct symbol *) - obstack_alloc (&objfile->symbol_obstack, - sizeof (struct symbol)); - *typedef_sym = *sym; - SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN; - if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) - TYPE_NAME (SYMBOL_TYPE (sym)) = - obsavestring (DEPRECATED_SYMBOL_NAME (sym), - strlen (DEPRECATED_SYMBOL_NAME (sym)), - &objfile->type_obstack); - add_symbol_to_list (typedef_sym, list_in_scope); + struct type *type = SYMBOL_TYPE (sym); + + if (TYPE_TAG_NAME (type) != NULL) + { + /* FIXME: carlton/2003-11-10: Should this use + SYMBOL_SET_NAMES instead? (The same problem also + arises a further down in the function.) */ + SYMBOL_LINKAGE_NAME (sym) + = obsavestring (TYPE_TAG_NAME (type), + strlen (TYPE_TAG_NAME (type)), + &objfile->symbol_obstack); + } } + + { + /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't + really ever be static objects: otherwise, if you try + to, say, break of a class's method and you're in a file + which doesn't mention that class, it won't work unless + the check for all static symbols in lookup_symbol_aux + saves you. See the OtherFileClass tests in + gdb.c++/namespace.exp. */ + + struct pending **list_to_add; + + list_to_add = (list_in_scope == &file_symbols + && cu_language == language_cplus + ? &global_symbols : list_in_scope); + + add_symbol_to_list (sym, list_to_add); + + /* The semantics of C++ state that "struct foo { ... }" also + defines a typedef for "foo". Synthesize a typedef symbol so + that "ptype foo" works as expected. */ + if (cu_language == language_cplus) + { + struct symbol *typedef_sym = (struct symbol *) + obstack_alloc (&objfile->symbol_obstack, + sizeof (struct symbol)); + *typedef_sym = *sym; + SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN; + if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0) + TYPE_NAME (SYMBOL_TYPE (sym)) = + obsavestring (SYMBOL_NATURAL_NAME (sym), + strlen (SYMBOL_NATURAL_NAME (sym)), + &objfile->type_obstack); + add_symbol_to_list (typedef_sym, list_to_add); + } + } break; case DW_TAG_typedef: + if (processing_has_namespace_info + && processing_current_prefix[0] != '\0') + { + SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->symbol_obstack, + processing_current_prefix, + "::", + name); + } + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + add_symbol_to_list (sym, list_in_scope); + break; case DW_TAG_base_type: SYMBOL_CLASS (sym) = LOC_TYPEDEF; SYMBOL_DOMAIN (sym) = VAR_DOMAIN; add_symbol_to_list (sym, list_in_scope); break; case DW_TAG_enumerator: + if (processing_has_namespace_info + && processing_current_prefix[0] != '\0') + { + SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->symbol_obstack, + processing_current_prefix, + "::", + name); + } attr = dwarf_attr (die, DW_AT_const_value); if (attr) { dwarf2_const_value (attr, sym, cu); } - add_symbol_to_list (sym, list_in_scope); + { + /* NOTE: carlton/2003-11-10: See comment above in the + DW_TAG_class_type, etc. block. */ + + struct pending **list_to_add; + + list_to_add = (list_in_scope == &file_symbols + && cu_language == language_cplus + ? &global_symbols : list_in_scope); + + add_symbol_to_list (sym, list_to_add); + } break; case DW_TAG_namespace: SYMBOL_CLASS (sym) = LOC_TYPEDEF; @@ -5588,6 +5876,11 @@ tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu) static void read_type_die (struct die_info *die, struct dwarf2_cu *cu) { + 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: @@ -5634,6 +5927,114 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu) dwarf_tag_name (die->tag)); break; } + + processing_current_prefix = old_prefix; + do_cleanups (back_to); +} + +/* Return 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); + char *retval; + + switch (parent->tag) { + case DW_TAG_namespace: + { + int dummy; + + retval = typename_concat (parent_prefix, + namespace_name (parent, &dummy)); + } + break; + case DW_TAG_class_type: + case DW_TAG_structure_type: + { + if (parent_prefix != NULL) + { + const char *parent_name = dwarf2_name (parent); + + if (parent_name != NULL) + retval = typename_concat (parent_prefix, dwarf2_name (parent)); + else + /* FIXME: carlton/2003-11-10: I'm not sure what the + best thing to do here is. */ + retval = typename_concat (parent_prefix, + "<<anonymous class>>"); + } + else + retval = class_name (parent); + } + break; + default: + retval = parent_prefix; + break; + } + + if (retval != parent_prefix) + xfree (parent_prefix); + return retval; + } +} + +/* 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 * |