Re: [rfa] generate symbols associated to namespaces

Elena Zannoni
2003-09-09T19:42:57Z

David Carlton writes:
> On Fri, 27 Jun 2003 09:04:13 -0700, David Carlton <carlton@kealia.com> said:
>
> > I've looked at your code comments, and they all seem reasonable. I
> > hope I'll have a revised version of the patch today; job transition
> > issues will take up some of my time (I start full-time work at
> > Kealia today, so I have to figure out what they want me to do other
> > than hack GDB), but it's near the top of my priority list.
>
> Okay, here's the new version. Following Daniel's suggestion, it puts
> symbols associated to DW_TAG_namespace in the symtab where they are
> found, instead of in a special block, and creates one possible
> namespace block for each objfile. This fixes the problem Daniel found
> with the last version of my patch (which, incidentally, turns out also
> to show up under DWARF 2 with pr-1210.exp; the more tests the
> merrier).
>
> Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+,
> and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs.
> No new regressions (though the new tests in gdb.c++/namespace.exp fail
> under stabs+, as expected).
>
> How does this one look to y'all?

It looks ok, but there are a couple of things I'd like to see addressed,
see below.

elena

>
> David Carlton
> carlton@kealia.com
>
> 2003-06-27 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): Do initial setting
> lowpc and highpc ourselves. Add argument to
> scan_partial_symbols_call.
> (scan_partial_symbols): Restructure into a recursive version,
> calling add_partial_namespace and add_partial_enumeration when
> appropriate.
> (add_partial_symbol): If necessary, scan mangled names for names
> of namespaces.
> (add_partial_namespace): New.
> (add_partial_enumeration, locate_pdi_sibling): Ditto.
> * objfiles.h (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-06-27 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.
>
> Index: Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/Makefile.in,v
> retrieving revision 1.410
> diff -u -p -r1.410 Makefile.in
> --- Makefile.in 21 Jun 2003 23:14:43 -0000 1.410
> +++ Makefile.in 27 Jun 2003 21:37:38 -0000
> @@ -1642,7 +1642,8 @@ corelow.o: corelow.c $(defs_h) $(gdb_str
> 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) $(block_h)
> Index: block.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/block.c,v
> retrieving revision 1.7
> diff -u -p -r1.7 block.c
> --- block.c 2 Jun 2003 18:36:33 -0000 1.7
> +++ block.c 27 Jun 2003 21:37:40 -0000
> @@ -268,3 +268,28 @@ block_global_block (const struct 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;
> +}
> Index: block.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/block.h,v
> retrieving revision 1.8
> diff -u -p -r1.8 block.h
> --- block.h 11 Jun 2003 23:29:46 -0000 1.8
> +++ block.h 27 Jun 2003 21:37:40 -0000
> @@ -171,4 +171,6 @@ extern const struct block *block_static_
>
> extern const struct block *block_global_block (const struct block *block);
>
> +extern struct block *allocate_block (struct obstack *obstack);
> +
> #endif /* BLOCK_H */
> Index: c-typeprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/c-typeprint.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 c-typeprint.c
> --- c-typeprint.c 4 Jan 2003 21:54:54 -0000 1.26
> +++ c-typeprint.c 27 Jun 2003 21:37:58 -0000
> @@ -284,6 +284,7 @@ c_type_print_varspec_prefix (struct type
> 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
> 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;
> @@ -1180,6 +1182,11 @@ c_type_print_base (struct type *type, st
> fprintf_filtered (stream, "\n");
> }
> }
> + break;
> +
> + case TYPE_CODE_NAMESPACE:
> + fputs_filtered ("namespace ", stream);
> + fputs_filtered (TYPE_TAG_NAME (type), stream);
> break;
>
> default:
> Index: cp-namespace.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/cp-namespace.c,v
> retrieving revision 1.3
> diff -u -p -r1.3 cp-namespace.c
> --- cp-namespace.c 13 Jun 2003 00:55:43 -0000 1.3
> +++ cp-namespace.c 27 Jun 2003 21:38:02 -0000
> @@ -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
> 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,268 @@ 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
> + {
> + 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 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). */
> +
> + 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)
> {
> - return lookup_symbol_global (name, linkage_name, domain, symtab);
> + 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);
> }
> Index: cp-support.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/cp-support.c,v
> retrieving revision 1.5
> diff -u -p -r1.5 cp-support.c
> --- cp-support.c 12 Jun 2003 15:33:45 -0000 1.5
> +++ cp-support.c 27 Jun 2003 21:38:07 -0000
> @@ -45,7 +45,7 @@ static void overload_list_add_symbol (st
>
> /* 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. */
>
> Index: cp-support.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/cp-support.h,v
> retrieving revision 1.6
> diff -u -p -r1.6 cp-support.h
> --- cp-support.h 12 Jun 2003 15:33:45 -0000 1.6
> +++ cp-support.h 27 Jun 2003 21:38:12 -0000
> @@ -96,4 +96,11 @@ extern struct symbol *cp_lookup_symbol_n
> 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 */
> Index: dwarf2read.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2read.c,v
> retrieving revision 1.97
> diff -u -p -r1.97 dwarf2read.c
> --- dwarf2read.c 26 Jun 2003 21:20:39 -0000 1.97
> +++ dwarf2read.c 27 Jun 2003 21:38:33 -0000
> @@ -678,10 +678,30 @@ static void dwarf2_build_psymtabs_hard (
>
> 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 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 char *namespace);
> +
> +static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
> + char *info_ptr,
> + bfd *abfd,
> + const struct comp_unit_head *cu_header);
>
> static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
>
> @@ -1327,9 +1347,17 @@ dwarf2_build_psymtabs_hard (struct objfi
> If not, there's no more debug_info for this comp unit. */
> if (comp_unit_die.has_children)
> {
> + lowpc = ((CORE_ADDR) -1);
> + 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'. */
> + if (lowpc == ((CORE_ADDR) -1))
> + lowpc = highpc;
> +
> /* If the compilation unit didn't have an explicit address range,
> then use the information extracted from its child dies. */
> if (! comp_unit_die.has_pc_info)
> @@ -1358,45 +1386,40 @@ dwarf2_build_psymtabs_hard (struct objfi
> do_cleanups (back_to);
> }
>
> -/* Read in all interesting dies to the end of the compilation unit. */
> +/* Read in all interesting dies to the end of the compilation unit or
> + 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;
>
> - /* This function is called after we've read in the comp_unit_die in
> - order to read its children. We start the nesting level at 1 since
> - we have pushed 1 level down in order to read the comp unit's children.
> - The comp unit itself is at level 0, so we stop reading when we pop
> - back to that level. */
> -
> - int nesting_level = 1;
> -
> - /* We only want to read in symbols corresponding to variables or
> - other similar objects that are global or static. Normally, these
> - are all children of the DW_TAG_compile_unit die, so are all at
> - level 1. But C++ namespaces give ries to DW_TAG_namespace dies
> - whose children are global objects. So we keep track of what
> - level we currently think of as referring to file scope; this
> - should always equal 1 plus the number of namespaces that we are
> - currently nested within. */
> -
> - int file_scope_level = 1;
> -
> - *lowpc = ((CORE_ADDR) -1);
> - *highpc = ((CORE_ADDR) 0);
> + /* Now, march along the PDI's, descending into ones which have
> + interesting children but skipping the children of the other ones,
> + until we reach the end of the compilation unit. */
>
> - while (nesting_level)
> + while (1)
> {
> + /* This flag tells whether or not info_ptr has gotten updated
> + inside the loop. */
> + int info_ptr_updated = 0;
> +
> info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
>
> - /* Anonymous namespaces have no name but are interesting. */
> + /* Anonymous namespaces have no name but have interesting
> + children, so we need to look at them. Ditto for anonymous
> + enums. */
>
> - if (pdi.name != NULL || pdi.tag == DW_TAG_namespace)
> + if (pdi.name != NULL || pdi.tag == DW_TAG_namespace
> + || pdi.tag == DW_TAG_enumeration_type)
> {
> switch (pdi.tag)
> {
> @@ -1411,93 +1434,77 @@ scan_partial_symbols (char *info_ptr, st
> {
> *highpc = pdi.highpc;
> }
> - if ((pdi.is_external || nesting_level == file_scope_level)
> - && !pdi.is_declaration)
> + if (!pdi.is_declaration)
> {
> - add_partial_symbol (&pdi, objfile, cu_header);
> + add_partial_symbol (&pdi, objfile, cu_header, namespace);
> }
> }
> break;
> case DW_TAG_variable:
> case DW_TAG_typedef:
> + case DW_TAG_union_type:
> case DW_TAG_class_type:
> case DW_TAG_structure_type:
> - case DW_TAG_union_type:
> - case DW_TAG_enumeration_type:
> - if ((pdi.is_external || nesting_level == file_scope_level)
> - && !pdi.is_declaration)
> + if (!pdi.is_declaration)
> {
> - add_partial_symbol (&pdi, objfile, cu_header);
> + add_partial_symbol (&pdi, objfile, cu_header, namespace);
> }
> break;
> - case DW_TAG_enumerator:
> - /* File scope enumerators are added to the partial
> - symbol table. They're children of the enumeration
> - type die, so they occur at a level one higher than we
> - normally look for. */
> - if (nesting_level == file_scope_level + 1)
> - add_partial_symbol (&pdi, objfile, cu_header);
> + case DW_TAG_enumeration_type:
> + if (!pdi.is_declaration)
> + {
> + info_ptr = add_partial_enumeration (&pdi, info_ptr,
> + 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. */
> - if (nesting_level == file_scope_level)
> - add_partial_symbol (&pdi, objfile, cu_header);
> + add_partial_symbol (&pdi, objfile, cu_header, namespace);
> break;
> case DW_TAG_namespace:
> - /* FIXME: carlton/2002-10-16: we're not yet doing
> - anything useful with this, but for now make sure that
> - these tags at least don't cause us to miss any
> - important symbols. */
> - if (pdi.has_children)
> - file_scope_level++;
> + /* 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,
> + namespace);
> + info_ptr_updated = 1;
> + break;
> default:
> break;
> }
> }
>
> - /* If the die has a sibling, skip to the sibling. Do not skip
> - enumeration types, we want to record their enumerators. Do
> - not skip namespaces, we want to record symbols inside
> - them. */
> - if (pdi.sibling
> - && pdi.tag != DW_TAG_enumeration_type
> - && pdi.tag != DW_TAG_namespace)
> - {
> - info_ptr = pdi.sibling;
> - }
> - else if (pdi.has_children)
> - {
> - /* Die has children, but either the optional DW_AT_sibling
> - attribute is missing or we want to look at them. */
> - nesting_level++;
> - }
> -
> if (pdi.tag == 0)
> - {
> - nesting_level--;
> - /* If this is the end of a DW_TAG_namespace entry, then
> - decrease the file_scope_level, too. */
> - if (nesting_level < file_scope_level)
> - {
> - file_scope_level--;
> - gdb_assert (nesting_level == file_scope_level);
> - }
> - }
> + break;
> +
> + /* If the die has a sibling, skip to the sibling, unless another
> + function has already updated info_ptr for us. */
> +
> + /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether
> + or not we want to update this depends on enough stuff (not
> + only pdi.tag but also whether or not pdi.name is NULL) that
> + this seems like the easiest way to handle the issue. */
> +
> + if (!info_ptr_updated)
> + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
> }
>
> - /* If we didn't find a lowpc, set it to highpc to avoid complaints
> - from `maint check'. */
> - if (*lowpc == ((CORE_ADDR) -1))
> - *lowpc = *highpc;
> return info_ptr;
> }

Ok, but, could you check in the algorithm change (the nested_level
stuff) for scan_partial_symbols w/o any namespace changes? So that we
can do a cvs -D if something goes wrong? I have decided that it is
best to have a change per 24hours period to a file, after spending a
couple of days tracking down some other breakage in symfiles, a few
weeks back. Then the rest of the changes.

>
> 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)
> {
> @@ -1506,19 +1513,21 @@ add_partial_symbol (struct partial_die_i
> {
> /*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:
> @@ -1540,10 +1549,11 @@ add_partial_symbol (struct partial_die_i
> 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
> {
> @@ -1553,10 +1563,11 @@ add_partial_symbol (struct partial_die_i
> 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:
> @@ -1597,6 +1608,124 @@ add_partial_symbol (struct partial_die_i
> 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);
> +}
> +

I don't like this too much. I.e. changing add_psymbol_to_list to
return a value so you can get a hold of the psym. After all,
add_psymbol_to_list doesn't change any of the fields of the psymbol,
and cp_check_possible_namespace_symbols uses 2 fields that you already
have around. Would it be possible to do w/o using psym at all? You
might have to set a local variable to the function.

> +/* 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 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, full_name);
> +
> + return info_ptr;
> +}
> +
> +/* Read a partial die corresponding to an enumeration type. */
> +
> +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 char *namespace)
> +{
> + bfd *abfd = objfile->obfd;
> + struct partial_die_info pdi;
> +
> + if (enum_pdi->name != NULL)
> + add_partial_symbol (enum_pdi, objfile, cu_header, namespace);
> +
> + while (1)
> + {
> + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
> + if (pdi.tag == 0)
> + break;
> + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
> + complaint (&symfile_complaints, "malformed enumerator DIE ignored");
> + else
> + add_partial_symbol (&pdi, objfile, cu_header, namespace);
> + }
> +
> + return info_ptr;
> +}
> +

Any enumeration related tests that fail before and pass after this change?

> +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
> + after ORIG_PDI. */
> +
> +static char *
> +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
> + bfd *abfd, const struct comp_unit_head *cu_header)
> +{
> + /* Do we know the sibling already? */
> +
> + if (orig_pdi->sibling)
> + return orig_pdi->sibling;
> +
> + /* Are there any children to deal with? */
> +
> + if (!orig_pdi->has_children)
> + return info_ptr;
> +
> + /* Okay, we don't know the sibling, but we have children that we
> + want to skip. So read children until we run into one without a
> + tag; return whatever follows it. */
> +
> + while (1)
> + {
> + struct partial_die_info pdi;
> +
> + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
> +
> + if (pdi.tag == 0)
> + return info_ptr;
> + else
> + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
> + }
> }
>
> /* Expand this partial symbol table into a full symbol table. */
> @@ -3260,6 +3389,23 @@ read_namespace (struct die_info *die, st
> strlen (previous_namespace),
> strlen (processing_current_namespace));
>
> + /* Add a symbol associated to this if we haven't seen the namespace
> + before. */
> +
> + if (dwarf2_extension (die) == NULL)

Could you use this function in the check before this, in
read_namespace (not in this patch, but already in the file)?

> + {
> + 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 (die->has_children)
> {
> struct die_info *child_die = die->next;
> @@ -5113,7 +5259,11 @@ new_symbol (struct die_info *die, struct
> 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,
> @@ -5291,6 +5441,10 @@ new_symbol (struct die_info *die, struct
> dwarf2_const_value (attr, sym, objfile, cu_header);
> }
> 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
> Index: gdbtypes.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.c,v
> retrieving revision 1.74
> diff -u -p -r1.74 gdbtypes.c
> --- gdbtypes.c 23 Jun 2003 21:05:40 -0000 1.74
> +++ gdbtypes.c 27 Jun 2003 21:38:38 -0000
> @@ -1897,7 +1897,8 @@ init_type (enum type_code code, int leng
> 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);
> }
> @@ -3144,6 +3145,9 @@ recursive_dump_type (struct type *type,
> break;
> 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)");
> Index: gdbtypes.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/gdbtypes.h,v
> retrieving revision 1.48
> diff -u -p -r1.48 gdbtypes.h
> --- gdbtypes.h 23 Jun 2003 21:05:40 -0000 1.48
> +++ gdbtypes.h 27 Jun 2003 21:38:50 -0000
> @@ -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
> Index: jv-lang.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/jv-lang.c,v
> retrieving revision 1.21
> diff -u -p -r1.21 jv-lang.c
> --- jv-lang.c 11 Jun 2003 23:29:47 -0000 1.21
> +++ jv-lang.c 27 Jun 2003 21:38:55 -0000
> @@ -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;

I think it would make sense, in a next pass, to have all the creation
of blocks go through the new function.

> Index: objfiles.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/objfiles.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 objfiles.c
> --- objfiles.c 11 Jun 2003 23:29:47 -0000 1.33
> +++ objfiles.c 27 Jun 2003 21:38:55 -0000
> @@ -332,10 +332,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. */
>
> Index: objfiles.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/objfiles.h,v
> retrieving revision 1.22
> diff -u -p -r1.22 objfiles.h
> --- objfiles.h 24 Mar 2003 03:54:48 -0000 1.22
> +++ objfiles.h 27 Jun 2003 21:39:07 -0000
> @@ -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
> @@ -436,6 +437,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. */
> Index: printcmd.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/printcmd.c,v
> retrieving revision 1.63
> diff -u -p -r1.63 printcmd.c
> --- printcmd.c 9 Jun 2003 15:20:21 -0000 1.63
> +++ printcmd.c 27 Jun 2003 21:39:09 -0000
> @@ -315,7 +315,8 @@ print_formatted (struct value *val, regi
> || 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
> Index: symfile.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/symfile.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 symfile.c
> --- symfile.c 27 Jun 2003 13:11:17 -0000 1.101
> +++ symfile.c 27 Jun 2003 21:39:23 -0000
> @@ -2631,9 +2631,10 @@ start_psymtab_common (struct objfile *ob
> }
> \f
> /* 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). */
> + Since one arg is a struct, we pass in a ptr and deref it (sigh).
> + Return the partial symbol that has been added. */
>
> -void
> +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 */
> @@ -2676,6 +2677,8 @@ add_psymbol_to_list (char *name, int nam
> }
> *list->next++ = psym;
> OBJSTAT (objfile, n_psyms++);
> +
> + return psym;
> }
>
> /* Add a symbol with a long value to a psymtab. This differs from

See the comments about the dwarf2read.c changes, to see if we can
avoid doing this.

> Index: symfile.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/symfile.h,v
> retrieving revision 1.24
> diff -u -p -r1.24 symfile.h
> --- symfile.h 11 Jun 2003 22:27:13 -0000 1.24
> +++ symfile.h 27 Jun 2003 21:39:26 -0000
> @@ -152,9 +152,12 @@ extern void extend_psymbol_list (struct
>
> /* #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,

Ditto.

> Index: typeprint.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/typeprint.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 typeprint.c
> --- typeprint.c 8 Jun 2003 18:27:14 -0000 1.18
> +++ typeprint.c 27 Jun 2003 21:39:28 -0000
> @@ -307,6 +307,7 @@ print_type_scalar (struct type *type, LO
> 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;
>
> Index: testsuite/gdb.c++/maint.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/maint.exp,v
> retrieving revision 1.2
> diff -u -p -r1.2 maint.exp
> --- testsuite/gdb.c++/maint.exp 23 Apr 2003 23:45:24 -0000 1.2
> +++ testsuite/gdb.c++/maint.exp 27 Jun 2003 21:39:29 -0000
> @@ -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
> @@ -79,6 +85,12 @@ proc test_first_component {} {
> gdb_test "maint cp first_component foo::bar::baz" "foo"
> gdb_test "maint cp first_component C::bar" "C"
> gdb_test "maint cp first_component C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >::bar" "C<std::basic_streambuf<wchar_t,std::char_traits<wchar_t> > >"
> +}
> +
> +proc test_namespace {} {
> + # There's not a lot we can do to test this.
> +
> + gdb_test "maint cp namespace" "Possible namespaces:"
> }
>
> gdb_exit
> Index: testsuite/gdb.c++/namespace.exp
> ===================================================================
> RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.exp,v
> retrieving revision 1.13
> diff -u -p -r1.13 namespace.exp
> --- testsuite/gdb.c++/namespace.exp 20 May 2003 03:56:29 -0000 1.13
> +++ testsuite/gdb.c++/namespace.exp 27 Jun 2003 21:39:29 -0000
> @@ -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.
>