diff options
author | David Carlton <carlton@bactrian.org> | 2003-09-11 19:49:20 +0000 |
---|---|---|
committer | David Carlton <carlton@bactrian.org> | 2003-09-11 19:49:20 +0000 |
commit | 5c4e30cabe34c872ef8f456103de180c8d7414da (patch) | |
tree | cf449086667cca2d179f8a2f4b8370904ce75b45 | |
parent | 33a7c2fc4d40cc53f649c9bbb3780826dd56fe1b (diff) | |
download | gdb-5c4e30cabe34c872ef8f456103de180c8d7414da.zip gdb-5c4e30cabe34c872ef8f456103de180c8d7414da.tar.gz gdb-5c4e30cabe34c872ef8f456103de180c8d7414da.tar.bz2 |
2003-09-11 David Carlton <carlton@kealia.com>
* gdbtypes.h: Add TYPE_CODE_NAMESPACE.
* gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE.
(recursive_dump_type): Ditto.
* printcmd.c (print_formatted): Ditto.
* typeprint.c (print_type_scalar): Ditto.
* c-typeprint.c (c_type_print_varspec_prefix): Ditto.
(c_type_print_varspec_suffix, c_type_print_base): Ditto.
* cp-support.h: Declare cp_check_possible_namespace_symbols,
maint_cplus_cmd_list.
* cp-support.c: Make maint_cplus_cmd_list extern.
* cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h,
command.h.
(lookup_symbol_file): Look in possible namespace blocks when
appropriate.
(initialize_namespace_symtab): New.
(get_possible_namespace_block, free_namespace_block)
(check_possible_namespace_symbols)
(check_possible_namespace_symbols_loop)
(check_one_possible_namespace_symbol)
(lookup_possible_namespace_symbol, maintenance_cplus_namespace)
(_initialize_cp_namespace): Ditto.
* block.h: Declare allocate_block.
* block.c (allocate_block): New.
* jv-lang.c (get_java_class_symtab): Allocate blocks via
allocate_block.
* symfile.h: Update declaration of add_psymbol_to_list.
* symfile.c (add_psymbol_to_list): Return the partial symbol in
question.
* dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to
scan_partial_symbols_call.
(scan_partial_symbols): Add NAMESPACE argument; update calls to
helper functions.
(add_partial_symbol): If necessary, scan mangled names for names
of namespaces.
(add_partial_namespace): Add NAMESPACE argument; generate partial
symbols associated to namespaces.
(add_partial_enumeration): Add NAMESPACE argument.
(new_symbol): Allow namespace syms.
(read_namespace): Generate namespace syms.
* objfiles.h: Add opaque declaration of struct symtab.
(struct objfile): Add cp_namespace_symtab member.
* objfiles.c (allocate_objfile): Set
objfile->cp_namespace_symtab.
* Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h,
dictionary_h, command_h.
2003-09-11 David Carlton <carlton@kealia.com>
* gdb.c++/namespace.exp: Add tests for namespace types.
* gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'.
(test_namespace): New.
-rw-r--r-- | gdb/ChangeLog | 48 | ||||
-rw-r--r-- | gdb/Makefile.in | 3 | ||||
-rw-r--r-- | gdb/block.c | 25 | ||||
-rw-r--r-- | gdb/block.h | 2 | ||||
-rw-r--r-- | gdb/c-typeprint.c | 7 | ||||
-rw-r--r-- | gdb/cp-namespace.c | 298 | ||||
-rw-r--r-- | gdb/cp-support.c | 2 | ||||
-rw-r--r-- | gdb/cp-support.h | 7 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 172 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 6 | ||||
-rw-r--r-- | gdb/gdbtypes.h | 3 | ||||
-rw-r--r-- | gdb/jv-lang.c | 15 | ||||
-rw-r--r-- | gdb/objfiles.c | 12 | ||||
-rw-r--r-- | gdb/objfiles.h | 8 | ||||
-rw-r--r-- | gdb/printcmd.c | 3 | ||||
-rw-r--r-- | gdb/symfile.c | 20 | ||||
-rw-r--r-- | gdb/symfile.h | 9 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/maint.exp | 21 | ||||
-rw-r--r-- | gdb/testsuite/gdb.cp/namespace.exp | 2 | ||||
-rw-r--r-- | gdb/typeprint.c | 1 |
21 files changed, 590 insertions, 80 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 642ec3a..a59d05b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,51 @@ +2003-09-11 David Carlton <carlton@kealia.com> + + * gdbtypes.h: Add TYPE_CODE_NAMESPACE. + * gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE. + (recursive_dump_type): Ditto. + * printcmd.c (print_formatted): Ditto. + * typeprint.c (print_type_scalar): Ditto. + * c-typeprint.c (c_type_print_varspec_prefix): Ditto. + (c_type_print_varspec_suffix, c_type_print_base): Ditto. + * cp-support.h: Declare cp_check_possible_namespace_symbols, + maint_cplus_cmd_list. + * cp-support.c: Make maint_cplus_cmd_list extern. + * cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h, + command.h. + (lookup_symbol_file): Look in possible namespace blocks when + appropriate. + (initialize_namespace_symtab): New. + (get_possible_namespace_block, free_namespace_block) + (check_possible_namespace_symbols) + (check_possible_namespace_symbols_loop) + (check_one_possible_namespace_symbol) + (lookup_possible_namespace_symbol, maintenance_cplus_namespace) + (_initialize_cp_namespace): Ditto. + * block.h: Declare allocate_block. + * block.c (allocate_block): New. + * jv-lang.c (get_java_class_symtab): Allocate blocks via + allocate_block. + * symfile.h: Update declaration of add_psymbol_to_list. + * symfile.c (add_psymbol_to_list): Return the partial symbol in + question. + * dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to + scan_partial_symbols_call. + (scan_partial_symbols): Add NAMESPACE argument; update calls to + helper functions. + (add_partial_symbol): If necessary, scan mangled names for names + of namespaces. + (add_partial_namespace): Add NAMESPACE argument; generate partial + symbols associated to namespaces. + (add_partial_enumeration): Add NAMESPACE argument. + (new_symbol): Allow namespace syms. + (read_namespace): Generate namespace syms. + * objfiles.h: Add opaque declaration of struct symtab. + (struct objfile): Add cp_namespace_symtab member. + * objfiles.c (allocate_objfile): Set + objfile->cp_namespace_symtab. + * Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h, + dictionary_h, command_h. + 2003-09-11 Andrew Cagney <cagney@redhat.com> * rs6000-tdep.c (rs6000_push_dummy_call): Use diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ad0d30c..bbf57ba 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1657,7 +1657,8 @@ core-sol2.o: core-sol2.c $(defs_h) $(gdb_string_h) $(regcache_h) \ cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(command_h) $(gdbcmd_h) \ $(ui_out_h) $(gdb_string_h) cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \ - $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) + $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) $(objfiles_h) \ + $(gdbtypes_h) $(dictionary_h) $(command_h) cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \ $(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \ $(objfiles_h) $(frame_h) $(symtab_h) $(block_h) $(complaints_h) diff --git a/gdb/block.c b/gdb/block.c index 98b6ccb..8729a24 100644 --- a/gdb/block.c +++ b/gdb/block.c @@ -268,3 +268,28 @@ block_global_block (const struct block *block) return block; } + +/* Allocate a block on OBSTACK, and initialize its elements to + zero/NULL. This is useful for creating "dummy" blocks that don't + correspond to actual source files. + + Warning: it sets the block's BLOCK_DICT to NULL, which isn't a + valid value. If you really don't want the block to have a + dictionary, then you should subsequently set its BLOCK_DICT to + dict_create_linear (obstack, NULL). */ + +struct block * +allocate_block (struct obstack *obstack) +{ + struct block *bl = obstack_alloc (obstack, sizeof (struct block)); + + BLOCK_START (bl) = 0; + BLOCK_END (bl) = 0; + BLOCK_FUNCTION (bl) = NULL; + BLOCK_SUPERBLOCK (bl) = NULL; + BLOCK_DICT (bl) = NULL; + BLOCK_NAMESPACE (bl) = NULL; + BLOCK_GCC_COMPILED (bl) = 0; + + return bl; +} diff --git a/gdb/block.h b/gdb/block.h index aa69a89..38d037e 100644 --- a/gdb/block.h +++ b/gdb/block.h @@ -171,4 +171,6 @@ extern const struct block *block_static_block (const struct block *block); extern const struct block *block_global_block (const struct block *block); +extern struct block *allocate_block (struct obstack *obstack); + #endif /* BLOCK_H */ diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index b1e3019..75e581f 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -284,6 +284,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types need no prefix. They are listed here so that gcc -Wall will reveal any types that haven't been handled. */ break; @@ -624,6 +625,7 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types do not need a suffix. They are listed so that gcc -Wall will report types that may not have been considered. */ break; @@ -1182,6 +1184,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, } break; + case TYPE_CODE_NAMESPACE: + fputs_filtered ("namespace ", stream); + fputs_filtered (TYPE_TAG_NAME (type), stream); + break; + default: /* Handle types not explicitly handled by the other cases, such as fundamental types. For these, just print whatever diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c index db0839f..40959a5 100644 --- a/gdb/cp-namespace.c +++ b/gdb/cp-namespace.c @@ -27,6 +27,10 @@ #include "symfile.h" #include "gdb_assert.h" #include "block.h" +#include "objfiles.h" +#include "gdbtypes.h" +#include "dictionary.h" +#include "command.h" /* When set, the file that we're processing seems to have debugging info for C++ namespaces, so cp-namespace.c shouldn't try to guess @@ -70,6 +74,26 @@ static struct symbol *lookup_symbol_file (const char *name, struct symtab **symtab, int anonymous_namespace); +static void initialize_namespace_symtab (struct objfile *objfile); + +static struct block *get_possible_namespace_block (struct objfile *objfile); + +static void free_namespace_block (struct symtab *symtab); + +static int check_possible_namespace_symbols_loop (const char *name, + int len, + struct objfile *objfile); + +static int check_one_possible_namespace_symbol (const char *name, + int len, + struct objfile *objfile); + +static +struct symbol *lookup_possible_namespace_symbol (const char *name, + struct symtab **symtab); + +static void maintenance_cplus_namespace (char *args, int from_tty); + /* Set up support for dealing with C++ namespace info in the current symtab. */ @@ -453,13 +477,277 @@ lookup_symbol_file (const char *name, const struct block *global_block = block_global_block (block); if (global_block != NULL) - return lookup_symbol_aux_block (name, linkage_name, global_block, - domain, symtab); - else - return NULL; + sym = lookup_symbol_aux_block (name, linkage_name, global_block, + domain, symtab); } else { - return lookup_symbol_global (name, linkage_name, domain, symtab); + sym = lookup_symbol_global (name, linkage_name, domain, symtab); + } + + if (sym != NULL) + return sym; + + /* Now call "lookup_possible_namespace_symbol". Symbols in here + claim to be associated to namespaces, but this claim might be + incorrect: the names in question might actually correspond to + classes instead of namespaces. But if they correspond to + classes, then we should have found a match for them above. So if + we find them now, they should be genuine. */ + + /* FIXME: carlton/2003-06-12: This is a hack and should eventually + be deleted: see comments below. */ + + if (domain == VAR_DOMAIN) + { + sym = lookup_possible_namespace_symbol (name, symtab); + if (sym != NULL) + return sym; + } + + return NULL; +} + +/* Now come functions for dealing with symbols associated to + namespaces. (They're used to store the namespaces themselves, not + objects that live in the namespaces.) These symbols come in two + varieties: if we run into a DW_TAG_namespace DIE, then we know that + we have a namespace, so dwarf2read.c creates a symbol for it just + like normal. But, unfortunately, versions of GCC through at least + 3.3 don't generate those DIE's. Our solution is to try to guess + their existence by looking at demangled names. This might cause us + to misidentify classes as namespaces, however. So we put those + symbols in a special block (one per objfile), and we only search + that block as a last resort. */ + +/* FIXME: carlton/2003-06-12: Once versions of GCC that generate + DW_TAG_namespace have been out for a year or two, we should get rid + of all of this "possible namespace" nonsense. */ + +/* Allocate everything necessary for the possible namespace block + associated to OBJFILE. */ + +static void +initialize_namespace_symtab (struct objfile *objfile) +{ + struct symtab *namespace_symtab; + struct blockvector *bv; + struct block *bl; + + namespace_symtab = allocate_symtab ("<<C++-namespaces>>", objfile); + namespace_symtab->language = language_cplus; + namespace_symtab->free_code = free_nothing; + namespace_symtab->dirname = NULL; + + bv = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct blockvector) + + FIRST_LOCAL_BLOCK * sizeof (struct block *)); + BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1; + BLOCKVECTOR (namespace_symtab) = bv; + + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ + + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, + NULL); + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, + NULL); + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; + + /* Allocate the possible namespace block; we put it where the first + local block will live, though I don't think there's any need to + pretend that it's actually a local block (e.g. by setting + BLOCK_SUPERBLOCK appropriately). We don't use the global or + static block because we don't want it searched during the normal + search of all global/static blocks in lookup_symbol: we only want + it used as a last resort. */ + + /* NOTE: carlton/2003-09-11: I considered not associating the fake + symbols to a block/symtab at all. But that would cause problems + with lookup_symbol's SYMTAB argument and with block_found, so + having a symtab/block for this purpose seems like the best + solution for now. */ + + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_hashed_expandable (); + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; + + namespace_symtab->free_func = free_namespace_block; + + objfile->cp_namespace_symtab = namespace_symtab; +} + +/* Locate the possible namespace block associated to OBJFILE, + allocating it if necessary. */ + +static struct block * +get_possible_namespace_block (struct objfile *objfile) +{ + if (objfile->cp_namespace_symtab == NULL) + initialize_namespace_symtab (objfile); + + return BLOCKVECTOR_BLOCK (BLOCKVECTOR (objfile->cp_namespace_symtab), + FIRST_LOCAL_BLOCK); +} + +/* Free the dictionary associated to the possible namespace block. */ + +static void +free_namespace_block (struct symtab *symtab) +{ + struct block *possible_namespace_block; + + possible_namespace_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), + FIRST_LOCAL_BLOCK); + gdb_assert (possible_namespace_block != NULL); + dict_free (BLOCK_DICT (possible_namespace_block)); +} + +/* Ensure that there are symbols in the possible namespace block + associated to OBJFILE for all initial substrings of NAME that look + like namespaces or classes. NAME should end in a member variable: + it shouldn't consist solely of namespaces. */ + +void +cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile) +{ + check_possible_namespace_symbols_loop (name, + cp_find_first_component (name), + objfile); +} + +/* This is a helper loop for cp_check_possible_namespace_symbols; it + ensures that there are symbols in the possible namespace block + associated to OBJFILE for all namespaces that are initial + substrings of NAME of length at least LEN. It returns 1 if a + previous loop had already created the shortest such symbol and 0 + otherwise. + + This function assumes that if there is already a symbol associated + to a substring of NAME of a given length, then there are already + symbols associated to all substrings of NAME whose length is less + than that length. So if cp_check_possible_namespace_symbols has + been called once with argument "A::B::C::member", then that will + create symbols "A", "A::B", and "A::B::C". If it is then later + called with argument "A::B::D::member", then the new call will + generate a new symbol for "A::B::D", but once it sees that "A::B" + has already been created, it doesn't bother checking to see if "A" + has also been created. */ + +static int +check_possible_namespace_symbols_loop (const char *name, int len, + struct objfile *objfile) +{ + if (name[len] == ':') + { + int done; + int next_len = len + 2; + + next_len += cp_find_first_component (name + next_len); + done = check_possible_namespace_symbols_loop (name, next_len, + objfile); + + if (!done) + done = check_one_possible_namespace_symbol (name, len, objfile); + + return done; } + else + return 0; +} + +/* Check to see if there's already a possible namespace symbol in + OBJFILE whose name is the initial substring of NAME of length LEN. + If not, create one and return 0; otherwise, return 1. */ + +static int +check_one_possible_namespace_symbol (const char *name, int len, + struct objfile *objfile) +{ + struct block *block = get_possible_namespace_block (objfile); + char *name_copy = obsavestring (name, len, &objfile->symbol_obstack); + struct symbol *sym = lookup_block_symbol (block, name_copy, NULL, + VAR_DOMAIN); + + if (sym == NULL) + { + struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + name_copy, objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_LANGUAGE (sym) = language_cplus; + SYMBOL_SET_NAMES (sym, name_copy, len, objfile); + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_TYPE (sym) = type; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + + dict_add_symbol (BLOCK_DICT (block), sym); + + return 0; + } + else + { + obstack_free (&objfile->symbol_obstack, name_copy); + + return 1; + } +} + +/* Look for a symbol named NAME in all the possible namespace blocks. + If one is found, return it; if SYMTAB is non-NULL, set *SYMTAB to + equal the symtab where it was found. */ + +static struct symbol * +lookup_possible_namespace_symbol (const char *name, struct symtab **symtab) +{ + struct objfile *objfile; + + ALL_OBJFILES (objfile) + { + struct symbol *sym; + + sym = lookup_block_symbol (get_possible_namespace_block (objfile), + name, NULL, VAR_DOMAIN); + + if (sym != NULL) + { + if (symtab != NULL) + *symtab = objfile->cp_namespace_symtab; + + return sym; + } + } + + return NULL; +} + +/* Print out all the possible namespace symbols. */ + +static void +maintenance_cplus_namespace (char *args, int from_tty) +{ + struct objfile *objfile; + printf_unfiltered ("Possible namespaces:\n"); + ALL_OBJFILES (objfile) + { + struct dict_iterator iter; + struct symbol *sym; + + ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym) + { + printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); + } + } +} + +void +_initialize_cp_namespace (void) +{ + add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace, + "Print the list of possible C++ namespaces.", + &maint_cplus_cmd_list); } diff --git a/gdb/cp-support.c b/gdb/cp-support.c index feea103..10e7836 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -55,7 +55,7 @@ static void overload_list_add_symbol (struct symbol *sym, char *oload_name); /* The list of "maint cplus" commands. */ -static struct cmd_list_element *maint_cplus_cmd_list = NULL; +struct cmd_list_element *maint_cplus_cmd_list = NULL; /* The actual commands. */ diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 339981c..5446794 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -96,4 +96,11 @@ extern struct symbol *cp_lookup_symbol_namespace (const char *namespace, const domain_enum domain, struct symtab **symtab); +extern void cp_check_possible_namespace_symbols (const char *name, + struct objfile *objfile); + +/* The list of "maint cplus" commands. */ + +extern struct cmd_list_element *maint_cplus_cmd_list; + #endif /* CP_SUPPORT_H */ diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 18b67a6..b432f12 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -672,21 +672,25 @@ static void dwarf2_build_psymtabs_hard (struct objfile *, int); static char *scan_partial_symbols (char *, struct objfile *, CORE_ADDR *, CORE_ADDR *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); static void add_partial_symbol (struct partial_die_info *, struct objfile *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); static char *add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, struct objfile *objfile, CORE_ADDR *lowpc, CORE_ADDR *highpc, - const struct comp_unit_head *cu_header); + const struct comp_unit_head *cu_header, + const char *namespace); static char *add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, struct objfile *objfile, - const struct comp_unit_head *cu_header); + const struct comp_unit_head *cu_header, + const char *namespace); static char *locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, @@ -1341,7 +1345,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) highpc = ((CORE_ADDR) 0); info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, - &cu_header); + &cu_header, NULL); /* If we didn't find a lowpc, set it to highpc to avoid complaints from `maint check'. */ @@ -1377,12 +1381,17 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline) } /* Read in all interesting dies to the end of the compilation unit or - to the end of the current namespace. */ + to the end of the current namespace. NAMESPACE is NULL if we + haven't yet encountered any DW_TAG_namespace entries; otherwise, + it's the name of the current namespace. In particular, it's the + empty string if we're currently in the global namespace but have + previously encountered a DW_TAG_namespace. */ static char * scan_partial_symbols (char *info_ptr, struct objfile *objfile, CORE_ADDR *lowpc, CORE_ADDR *highpc, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { bfd *abfd = objfile->obfd; struct partial_die_info pdi; @@ -1421,7 +1430,7 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, } if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } } break; @@ -1432,25 +1441,32 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, case DW_TAG_structure_type: if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } break; case DW_TAG_enumeration_type: if (!pdi.is_declaration) { info_ptr = add_partial_enumeration (&pdi, info_ptr, - objfile, cu_header); + objfile, cu_header, + namespace); info_ptr_updated = 1; } break; case DW_TAG_base_type: /* File scope base type definitions are added to the partial symbol table. */ - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); break; case DW_TAG_namespace: + /* We've hit a DW_TAG_namespace entry, so we know this + file has been compiled using a compiler that + generates them; update NAMESPACE to reflect that. */ + if (namespace == NULL) + namespace = ""; info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, - lowpc, highpc, cu_header); + lowpc, highpc, cu_header, + namespace); info_ptr_updated = 1; break; default: @@ -1478,9 +1494,11 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, static void add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { CORE_ADDR addr = 0; + const struct partial_symbol *psym = NULL; switch (pdi->tag) { @@ -1489,19 +1507,21 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->global_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } else { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_file_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->static_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } break; case DW_TAG_variable: @@ -1523,10 +1543,11 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, if (pdi->locdesc) addr = decode_locdesc (pdi->locdesc, objfile, cu_header); if (pdi->locdesc || pdi->has_type) - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->global_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } else { @@ -1536,10 +1557,11 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, addr = decode_locdesc (pdi->locdesc, objfile, cu_header); /*prim_record_minimal_symbol (pdi->name, addr + baseaddr, mst_file_data, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->static_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } break; case DW_TAG_typedef: @@ -1580,22 +1602,60 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, default: break; } + + /* Check to see if we should scan the name for possible namespace + info. Only do this if this is C++, if we don't have namespace + debugging info in the file, if the psym is of an appropriate type + (otherwise we'll have psym == NULL), and if we actually had a + mangled name to begin with. */ + + if (cu_language == language_cplus + && namespace == NULL + && psym != NULL + && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) + cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym), + objfile); } -/* Read a partial die corresponding to a namespace. For now, we don't - do anything with the fact that we're in a namespace; we just read - the symbols inside of it. */ +/* 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. */ static char * add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, struct objfile *objfile, CORE_ADDR *lowpc, CORE_ADDR *highpc, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { + /* Calculate the full name of the namespace that we just entered. */ + + const char *new_name = pdi->name; + char *full_name; + + if (new_name == NULL) + new_name = "(anonymous namespace)"; + full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1); + strcpy (full_name, namespace); + if (*namespace != '\0') + 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. */ + + add_psymbol_to_list (full_name, strlen (full_name), + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->global_psymbols, + 0, 0, cu_language, objfile); + + /* Now scan partial symbols in that namespace. */ + if (pdi->has_children) info_ptr = scan_partial_symbols (info_ptr, objfile, lowpc, highpc, - cu_header); + cu_header, full_name); return info_ptr; } @@ -1605,13 +1665,14 @@ add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, static char * add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, struct objfile *objfile, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { bfd *abfd = objfile->obfd; struct partial_die_info pdi; if (enum_pdi->name != NULL) - add_partial_symbol (enum_pdi, objfile, cu_header); + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); while (1) { @@ -1621,7 +1682,7 @@ add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) complaint (&symfile_complaints, "malformed enumerator DIE ignored"); else - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } return info_ptr; @@ -3314,13 +3375,28 @@ read_namespace (struct die_info *die, struct objfile *objfile, processing_current_namespace = temp_name; } - /* If it's an anonymous namespace that we're seeing for the first - time, add a using directive. */ + /* Add a symbol associated to this if we haven't seen the namespace + before. Also, add a using directive if it's an anonymous + namespace. */ - if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL) - cp_add_using_directive (processing_current_namespace, - strlen (previous_namespace), - strlen (processing_current_namespace)); + if (dwarf2_extension (die) == NULL) + { + struct type *type; + + /* FIXME: carlton/2003-06-27: Once GDB is more const-correct, + this cast will hopefully become unnecessary. */ + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + (char *) processing_current_namespace, + objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + new_symbol (die, type, objfile, cu_header); + + if (is_anonymous) + cp_add_using_directive (processing_current_namespace, + strlen (previous_namespace), + strlen (processing_current_namespace)); + } if (die->has_children) { @@ -5175,7 +5251,11 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, struct attribute *attr2 = NULL; CORE_ADDR addr = 0; - name = dwarf2_linkage_name (die); + if (die->tag != DW_TAG_namespace) + name = dwarf2_linkage_name (die); + else + name = TYPE_NAME (type); + if (name) { sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, @@ -5332,6 +5412,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile, } add_symbol_to_list (sym, list_in_scope); break; + case DW_TAG_namespace: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + add_symbol_to_list (sym, &global_symbols); + break; default: /* Not a tag we recognize. Hopefully we aren't processing trash data, but since we must specifically ignore things diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 4ce6cc7..a0fe55c 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1897,7 +1897,8 @@ init_type (enum type_code code, int length, int flags, char *name, if (name && strcmp (name, "char") == 0) TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; - if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION + || code == TYPE_CODE_NAMESPACE) { INIT_CPLUS_SPECIFIC (type); } @@ -3145,6 +3146,9 @@ recursive_dump_type (struct type *type, int spaces) case TYPE_CODE_TEMPLATE_ARG: printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)"); break; + case TYPE_CODE_NAMESPACE: + printf_filtered ("(TYPE_CODE_NAMESPACE)"); + break; default: printf_filtered ("(UNKNOWN TYPE CODE)"); break; diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index c7036f5..acd0ffd 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -134,8 +134,9 @@ enum type_code TYPE_CODE_TYPEDEF, TYPE_CODE_TEMPLATE, /* C++ template */ - TYPE_CODE_TEMPLATE_ARG /* C++ template arg */ + TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */ + TYPE_CODE_NAMESPACE, /* C++ namespace. */ }; /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index b767963..e9b86d2 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -111,22 +111,13 @@ get_java_class_symtab (void) BLOCKVECTOR (class_symtab) = bv; /* Allocate dummy STATIC_BLOCK. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, NULL); - BLOCK_START (bl) = 0; - BLOCK_END (bl) = 0; - BLOCK_FUNCTION (bl) = NULL; - BLOCK_SUPERBLOCK (bl) = NULL; - BLOCK_NAMESPACE (bl) = NULL; - BLOCK_GCC_COMPILED (bl) = 0; BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; - /* Allocate GLOBAL_BLOCK. This has to be relocatable. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); - *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + /* Allocate GLOBAL_BLOCK. */ + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_hashed_expandable (); BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; class_symtab->free_func = free_class_block; diff --git a/gdb/objfiles.c b/gdb/objfiles.c index ee4cdc4..c62c9a0 100644 --- a/gdb/objfiles.c +++ b/gdb/objfiles.c @@ -338,10 +338,14 @@ allocate_objfile (bfd *abfd, int flags) /* Initialize the section indexes for this objfile, so that we can later detect if they are used w/o being properly assigned to. */ - objfile->sect_index_text = -1; - objfile->sect_index_data = -1; - objfile->sect_index_bss = -1; - objfile->sect_index_rodata = -1; + objfile->sect_index_text = -1; + objfile->sect_index_data = -1; + objfile->sect_index_bss = -1; + objfile->sect_index_rodata = -1; + + /* We don't yet have a C++-specific namespace symtab. */ + + objfile->cp_namespace_symtab = NULL; /* Add this file onto the tail of the linked list of other such files. */ diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 80e61c5..c52b95f 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -28,6 +28,7 @@ struct bcache; struct htab; +struct symtab; /* This structure maintains information on a per-objfile basis about the "entry point" of the objfile, and the scope within which the entry point @@ -443,6 +444,13 @@ struct objfile /* Place to stash various statistics about this objfile */ OBJSTATS; + + /* A symtab that the C++ code uses to stash special symbols + associated to namespaces. */ + + /* FIXME/carlton-2003-06-27: Delete this in a few years once + "possible namespace symbols" go away. */ + struct symtab *cp_namespace_symtab; }; /* Defines for the objfile flag word. */ diff --git a/gdb/printcmd.c b/gdb/printcmd.c index dd7f636..3838f5d 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -315,7 +315,8 @@ print_formatted (struct value *val, register int format, int size, || TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_CODE (type) == TYPE_CODE_STRING || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) /* If format is 0, use the 'natural' format for * that type of value. If the type is non-scalar, * we have to use language rules to print it as diff --git a/gdb/symfile.c b/gdb/symfile.c index 04c6b88..02b2c36 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -2632,9 +2632,21 @@ start_psymtab_common (struct objfile *objfile, } /* Add a symbol with a long value to a psymtab. - Since one arg is a struct, we pass in a ptr and deref it (sigh). */ - -void + Since one arg is a struct, we pass in a ptr and deref it (sigh). + Return the partial symbol that has been added. */ + +/* NOTE: carlton/2003-09-11: The reason why we return the partial + symbol is so that callers can get access to the symbol's demangled + name, which they don't have any cheap way to determine otherwise. + (Currenly, dwarf2read.c is the only file who uses that information, + though it's possible that other readers might in the future.) + Elena wasn't thrilled about that, and I don't blame her, but we + couldn't come up with a better way to get that information. If + it's needed in other situations, we could consider breaking up + SYMBOL_SET_NAMES to provide access to the demangled name lookup + cache. */ + +const struct partial_symbol * add_psymbol_to_list (char *name, int namelength, domain_enum domain, enum address_class class, struct psymbol_allocation_list *list, long val, /* Value as a long */ @@ -2677,6 +2689,8 @@ add_psymbol_to_list (char *name, int namelength, domain_enum domain, } *list->next++ = psym; OBJSTAT (objfile, n_psyms++); + + return psym; } /* Add a symbol with a long value to a psymtab. This differs from diff --git a/gdb/symfile.h b/gdb/symfile.h index 5339253..40aa8dd 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -152,9 +152,12 @@ extern void extend_psymbol_list (struct psymbol_allocation_list *, /* #include "demangle.h" */ -extern void add_psymbol_to_list (char *, int, domain_enum, enum address_class, - struct psymbol_allocation_list *, long, - CORE_ADDR, enum language, struct objfile *); +extern const +struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum, + enum address_class, + struct psymbol_allocation_list *, + long, CORE_ADDR, + enum language, struct objfile *); extern void add_psymbol_with_dem_name_to_list (char *, int, char *, int, domain_enum, diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index ca5fee2..324c8b3 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-09-11 David Carlton <carlton@kealia.com> + + * gdb.c++/namespace.exp: Add tests for namespace types. + * gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'. + (test_namespace): New. + 2003-09-11 Elena Zannoni <ezannoni@redhat.com> * gdb.base/relocate.exp: Handle new gdb output at startup. diff --git a/gdb/testsuite/gdb.cp/maint.exp b/gdb/testsuite/gdb.cp/maint.exp index 1042c91..710e14a 100644 --- a/gdb/testsuite/gdb.cp/maint.exp +++ b/gdb/testsuite/gdb.cp/maint.exp @@ -29,13 +29,19 @@ if $tracelevel then { # Test the help messages. proc test_help {} { - gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set first_component_help "Print the first class/namespace component of NAME" + set namespace_help "Print the list of possible C\\+\\+ namespaces" - gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." - gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}" - gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME." + gdb_test "help maintenance cplus" "${help_maint_cp}" + gdb_test "help maint cp" "${help_maint_cp}" + gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}" + + gdb_test "help maint cp first_component" "${first_component_help}." + gdb_test "help maint cp namespace" "${namespace_help}." } # This is used when NAME should contain only a single component. Be @@ -103,11 +109,18 @@ proc test_first_component {} { test_invalid_name "bool operator<<char>" } +proc test_namespace {} { + # There's not a lot we can do to test this. + + gdb_test "maint cp namespace" "Possible namespaces:" +} + gdb_exit gdb_start test_help test_first_component +test_namespace gdb_exit return 0 diff --git a/gdb/testsuite/gdb.cp/namespace.exp b/gdb/testsuite/gdb.cp/namespace.exp index f4efaf6..6952c8f 100644 --- a/gdb/testsuite/gdb.cp/namespace.exp +++ b/gdb/testsuite/gdb.cp/namespace.exp @@ -208,6 +208,8 @@ gdb_test "print cd" "\\$\[0-9\].* = 3" gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5" gdb_test "print shadow" "\\$\[0-9\].* = 13" gdb_test "print cOtherFile" "\\$\[0-9\].* = 316" +gdb_test "ptype C" "type = namespace C::C" +gdb_test "ptype E" "type = namespace C::D::E" # Some anonymous namespace tests. diff --git a/gdb/typeprint.c b/gdb/typeprint.c index a9a74473..a8d67cc 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -307,6 +307,7 @@ print_type_scalar (struct type *type, LONGEST val, struct ui_file *stream) case TYPE_CODE_MEMBER: case TYPE_CODE_METHOD: case TYPE_CODE_REF: + case TYPE_CODE_NAMESPACE: error ("internal error: unhandled type in print_type_scalar"); break; |