This is the mail archive of the gdb-prs@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

pending/1248: [rfa] generate symbols associated to namespaces


>Number:         1248
>Category:       pending
>Synopsis:       [rfa] generate symbols associated to namespaces
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          change-request
>Submitter-Id:   unknown
>Arrival-Date:   Sun Jun 22 17:58:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     
>Release:        
>Organization:
>Environment:
>Description:
 This is the next part of my thrilling series of namespace patches; it
 generates symbols associated to namespaces.  The reason why these
 symbols are necessary is that, when evaluating an expression like
 'C::x', you first evaluate 'C', and then look up 'x' in the class or
 namespace referred to by 'C'; if you don't know what namespaces are
 floating around, you get into trouble.  E.g. given this:
 
 namespace C {
   namespace C {
     int oops;
   }
 
   int x;
 
   void foo()
   {
     C::x;  // error!
   }
 }
 
 the reference to C::x within C::foo is an error, since 'C' refers to
 'C::C', and there's no variable 'C::C::x'.  If we don't know that
 there's a namespace named 'C::C', we run into trouble when carrying
 out this behavior.
 
 This patch doesn't actually use those symbols very much.  There will
 be a followup patch that modifies the parser and associated functions
 to use them, but this patch is already quite complicated enough as it
 is.
 
 Unfortunately, if we don't have DW_TAG_namespace, then we have to work
 harder.  The solution I've chosen here is to look at demangled names
 of objects in that situation: if your object's demangled name is
 'C::x', then maybe C is a namespace.  But the downside is that C might
 be a class instead.  The solution that I've adopted is to maintain two
 collections of namespace symbols: one collection is the ones we know
 to exist (because of DW_TAG_namespace), and the other collection is
 the ones that might be classes or namespaces (we're not sure, we
 deduced their existence via demangled names).  Then the C++-specific
 version of lookup_symbol only searches this latter collection if it
 has tried to look for a class by that name and has failed.
 
 There's (at least) one other piece of strangeness in the
 implementation.  Normally, we store symbols in the symtab associated
 to a file.  But I chose not to do that with namespace symbols, for a
 few reasons.  The main reason is that it makes the machinery to deduce
 possible namespace names from demangled names much more complicated
 and wasteful of memory.  A secondary reason is that namespaces really
 aren't associated to a single file, so why pretend that they are?
 (Also, it saves memory that way, too, since you only ever have one
 symbol associated to a namespace, instead of one symbol for each file
 that mentions the namespace.)  So I put namespaces in an artificial
 block in an artificial symtab; my recent dictionary patch makes this
 quite easy.  (I think that, in the long term, we should consider a
 similar process for C++ classes, especially templated classes, but
 that's a separate issue.)  These symbols are actually created by the
 DWARF 2 psymtab reader instead of the symtab reader.
 
 The dwarf2read.c part of the patch is hard to read: you might just
 want to apply it and compare it to the original.  I've reorganized
 scan_partial_symbols to behave recursively instead of using that
 nesting_level and file_scope_level stuff; it's cleaner this way.
 
 I've tested this on GCC 3.2, DWARF 2, i686-pc-linux-gnu.  I also
 tested gdb.c++/namespace.exp on a version of GCC 3.2 hacked to
 generated DW_TAG_namespace entries.  And I've been using this stuff on
 my branch for months.
 
 This needs symtab and C++ approval.  I'll be on vacation until next
 Tuesday or Wednesday.
 
 David Carlton
 carlton@kealia.com
 
 2003-06-16  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_namespace_symbol,
 	cp_check_possible_namespace_symbols, maint_cplus_cmd_list.
 	* cp-support.c: Make maint_cplus_cmd_list extern.
 	* cp-namespace.c: Include objfiles.h, dictionary.h, command.h.
 	(lookup_symbol_file): Look in namespace blocks when appropriate.
 	(initialize_namespace_blocks): New.
 	(get_namespace_block, get_possible_namespace_block)
 	(free_namespace_blocks, get_namespace_objfile)
 	(cp_check_namespace_symbol, check_namespace_symbol_block)
 	(lookup_namespace_symbol, cp_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.
 	* Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h,
 	dictionary_h, command_h.
 
 2003-06-16  David Carlton  <carlton@kealia.com>
 
 	* gdb.c++/namespace.exp: Add tests for namespace types and maint
 	cp namespace.
 	* 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.407
 diff -u -p -r1.407 Makefile.in
 --- Makefile.in	15 Jun 2003 20:56:46 -0000	1.407
 +++ Makefile.in	16 Jun 2003 19:55:41 -0000
 @@ -1641,7 +1641,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	16 Jun 2003 19:55:41 -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	16 Jun 2003 19:55:41 -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	16 Jun 2003 19:55:43 -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	16 Jun 2003 19:55:43 -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,42 @@ static struct symbol *lookup_symbol_file
  					  struct symtab **symtab,
  					  int anonymous_namespace);
  
 +/* The next three variables are used to store symbols associated to
 +   namespaces.  Don't refer to them directly: use
 +   get_namespace_block(), get_possible_namespace_block(), and
 +   get_namespace_objfile() instead.  */
 +
 +static struct block *namespace_block = NULL;
 +
 +static struct block *possible_namespace_block = NULL;
 +
 +static struct objfile *namespace_objfile = NULL;
 +
 +static void initialize_namespace_blocks (void);
 +
 +static struct block *get_namespace_block (void);
 +
 +static struct block *get_possible_namespace_block (void);
 +
 +static void free_namespace_blocks (struct symtab *symtab);
 +
 +static struct objfile *get_namespace_objfile (void);
 +
 +static int check_namespace_symbol_block (const char *name, int len,
 +					 struct block *block);
 +
 +static struct symbol *lookup_namespace_symbol (const char *name);
 +
 +static int check_possible_namespace_symbols_loop (const char *name,
 +						  int len);
 +
 +static int check_one_possible_namespace_symbol (const char *name,
 +						int len);
 +
 +static struct symbol *lookup_possible_namespace_symbol (const char *name);
 +
 +static void maintenance_print_namespace (char *args, int from_tty);
 +
  /* Set up support for dealing with C++ namespace info in the current
     symtab.  */
  
 @@ -453,13 +493,323 @@ 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);
 +
 +      if (sym == NULL || global_block == NULL)
 +	{
 +	  sym = lookup_namespace_symbol (name);
 +	  if (sym != NULL && symtab != NULL)
 +	    *symtab = NULL;
 +	}
      }
    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, whereas the names in
 +     question might actually correspond to either namespaces or to
 +     classes.  But if they correspond to classes, then we should have
 +     found a match to 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);
 +      if (sym != NULL)
 +	{
 +	  if (symtab != NULL)
 +	    *symtab = 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.)  Since namespaces span files,
 +   we create special blocks to store those symbols in instead of
 +   storing them in blocks associated to actual files.  That avoids
 +   duplication of symbols, among other issues.
 +
 +   Unfortunately, versions of GCC through at least 3.3 don't generate
 +   debugging information to tell us about the existence of namespaces.
 +   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
 +   'possible_namespace_block' instead of 'namespace_block', 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 possible_namespace_block and everything associated to it.  */
 +
 +/* Allocate everything necessary for namespace_block and
 +   possible_namespace_block.  */
 +
 +static void
 +initialize_namespace_blocks (void)
 +{
 +  struct objfile *objfile = get_namespace_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;
 +
 +  /* 2 = three blocks (global = namespace_block, static = NULL, third
 +     block = possible_namespace_block), minus the one block that's
 +     always part of struct blockvector.  */
 +  bv = obstack_alloc (&objfile->symbol_obstack,
 +		      sizeof (struct blockvector)
 +		      + 2 * sizeof (struct block *));
 +  BLOCKVECTOR_NBLOCKS (bv) = 3;
 +  BLOCKVECTOR (namespace_symtab) = bv;
 +  
 +  /* Allocate dummy STATIC_BLOCK. */
 +  bl = allocate_block (&objfile->symbol_obstack);
 +  BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
 +					NULL);
 +  BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
 +
 +  /* Allocate GLOBAL_BLOCK, which is namespace_block.  */
 +  bl = allocate_block (&objfile->symbol_obstack);
 +  BLOCK_DICT (bl) = dict_create_hashed_expandable ();
 +  BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl;
 +  namespace_block = bl;
 +
 +  /* Allocate 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, 2) = bl;
 +  possible_namespace_block = bl;
 +
 +  namespace_symtab->free_func = free_namespace_blocks;
 +}
 +
 +/* Locate namespace_block, allocating it if necessary.  */
 +
 +static struct block *
 +get_namespace_block (void)
 +{
 +  if (namespace_block == NULL)
 +    initialize_namespace_blocks ();
 +
 +  return namespace_block;
 +}
 +
 +/* Locate possible_namespace_block, allocating it if necessary.  */
 +
 +static struct block *
 +get_possible_namespace_block (void)
 +{
 +  if (namespace_block == NULL)
 +    initialize_namespace_blocks ();
 +
 +  return possible_namespace_block;
 +}
 +
 +/* Free the dictionary associated to the namespace block.  */
 +
 +static void
 +free_namespace_blocks (struct symtab *symtab)
 +{
 +  gdb_assert (namespace_block != NULL);
 +  dict_free (BLOCK_DICT (namespace_block));
 +  namespace_block = NULL;
 +  dict_free (BLOCK_DICT (possible_namespace_block));
 +  possible_namespace_block = NULL;
 +  namespace_objfile = NULL;
 +}
 +
 +/* Locate the namespace objfile, allocating it if necessary.  */
 +
 +static struct objfile *
 +get_namespace_objfile (void)
 +{
 +  if (namespace_objfile == NULL)
 +    {
 +      namespace_objfile = allocate_objfile (NULL, 0);
 +      namespace_objfile->name
 +	= mstrsave (namespace_objfile->md, "<<C++-namespaces>>");
      }
 +
 +  return namespace_objfile;
 +}
 +
 +/* Check to see if there's already a namespace symbol whose name is
 +   NAME.  If there isn't one, allocate one and add it to the namespace
 +   symtab.  */
 +
 +void
 +cp_check_namespace_symbol (const char *name)
 +{
 +  check_namespace_symbol_block (name, strlen (name),
 +				get_namespace_block ());
 +}
 +
 +/* A helper function used by cp_check_namespace_symbol and
 +   check_one_possible_namespace_symbol.  Looks to see if there is a
 +   symbol whose name is the initial substring of NAME of length LEN in
 +   block BLOCK; if not, adds it.  Return 1 if the symbol was already
 +   in there, 0 otherwise.  */
 +
 +static int
 +check_namespace_symbol_block (const char *name, int len,
 +			      struct block *block)
 +{
 +  struct objfile *objfile = get_namespace_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 in namespace_block named NAME.  */
 +
 +static struct symbol *
 +lookup_namespace_symbol (const char *name)
 +{
 +  return lookup_block_symbol (get_namespace_block (), name, NULL,
 +			      VAR_DOMAIN);
 +}
 +
 +/* Ensure that there are symbols in possible_namespace_block 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)
 +{
 +  check_possible_namespace_symbols_loop (name,
 +					 cp_find_first_component (name));
 +}
 +
 +/* This is a helper loop for cp_check_possible_namespace_symbols; it
 +   ensures that there are namespace symbols 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)
 +{
 +  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);
 +
 +      if (!done)
 +	{
 +	  done = check_one_possible_namespace_symbol (name, len);
 +	}
 +
 +      return done;
 +    }
 +  else
 +    return 0;
 +}
 +
 +/* Check to see if there's already a possible namespace symbol 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)
 +{
 +  return check_namespace_symbol_block (name, len,
 +				       get_possible_namespace_block ());
 +}
 +
 +/* Look for a symbol in possible_namespace_block named NAME.  */
 +
 +static struct symbol *
 +lookup_possible_namespace_symbol (const char *name)
 +{
 +  return lookup_block_symbol (get_possible_namespace_block (),
 +			      name, NULL, VAR_DOMAIN);
 +}
 +
 +static void
 +maintenance_cplus_namespace (char *args, int from_tty)
 +{
 +  const struct block *namespace_block = get_namespace_block ();
 +  const struct block *possible_namespace_block
 +    = get_possible_namespace_block ();
 +  struct dict_iterator iter;
 +  struct symbol *sym;
 +
 +  printf_unfiltered ("Definite namespaces:\n");
 +  ALL_BLOCK_SYMBOLS (namespace_block, iter, sym)
 +    {
 +      printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym));
 +    }
 +  printf_unfiltered ("Possible namespaces:\n");
 +  ALL_BLOCK_SYMBOLS (possible_namespace_block, 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 current known 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	16 Jun 2003 19:55:44 -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	16 Jun 2003 19:55:44 -0000
 @@ -96,4 +96,12 @@ extern struct symbol *cp_lookup_symbol_n
  						  const domain_enum domain,
  						  struct symtab **symtab);
  
 +extern void cp_check_namespace_symbol (const char *name);
 +
 +extern void cp_check_possible_namespace_symbols (const char *name);
 +
 +/* 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.96
 diff -u -p -r1.96 dwarf2read.c
 --- dwarf2read.c	11 Jun 2003 22:27:11 -0000	1.96
 +++ dwarf2read.c	16 Jun 2003 19:55:52 -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 *);
  
 @@ -1323,9 +1343,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)
 @@ -1354,45 +1382,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)
  	    {
 @@ -1407,93 +1430,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;
  }
  
  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)
      {
 @@ -1502,19 +1509,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:
 @@ -1536,10 +1545,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
  	{
 @@ -1549,10 +1559,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:
 @@ -1592,6 +1603,117 @@ add_partial_symbol (struct partial_die_i
        break;
      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));
 +}
 +
 +/* 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);
 +
 +  /* Make sure that there's a symbol associated to that namespace.  */
 +
 +  cp_check_namespace_symbol (full_name);
 +
 +  /* 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;
 +      gdb_assert (pdi.tag == DW_TAG_enumerator);
 +      gdb_assert (pdi.name != NULL);
 +      add_partial_symbol (&pdi, objfile, cu_header, namespace);
 +    }
 +
 +  return info_ptr;
 +}
 +
 +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next PDI
 +   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);
      }
  }
  
 Index: gdbtypes.c
 ===================================================================
 RCS file: /cvs/src/src/gdb/gdbtypes.c,v
 retrieving revision 1.73
 diff -u -p -r1.73 gdbtypes.c
 --- gdbtypes.c	8 Jun 2003 18:27:13 -0000	1.73
 +++ gdbtypes.c	16 Jun 2003 19:55:56 -0000
 @@ -1896,7 +1896,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);
      }
 @@ -3143,6 +3144,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.47
 diff -u -p -r1.47 gdbtypes.h
 --- gdbtypes.h	14 May 2003 17:43:17 -0000	1.47
 +++ gdbtypes.h	16 Jun 2003 19:55:57 -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	16 Jun 2003 19:55:59 -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;
 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	16 Jun 2003 19:56:01 -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.98
 diff -u -p -r1.98 symfile.c
 --- symfile.c	11 Jun 2003 22:27:13 -0000	1.98
 +++ symfile.c	16 Jun 2003 19:56:05 -0000
 @@ -2635,9 +2635,10 @@ start_psymtab_common (struct objfile *ob
  }
  
  /* 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 */
 @@ -2680,6 +2681,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
 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	16 Jun 2003 19:56:05 -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,
 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	16 Jun 2003 19:56:06 -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	16 Jun 2003 19:56:21 -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\" follo wed 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 current known 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 ma intenance 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 cpl us 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 maintena nce 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<A>::bar" "C<A>"
      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 are some more tests for this command in namespace.exp.
 +
 +    gdb_test "maint cp namespace" "Definite namespaces:\r\nPossible 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	16 Jun 2003 19:56:21 -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.
  
 @@ -217,3 +219,18 @@ gdb_test "print X" "\\$\[0-9\].* = 9"
  gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
  gdb_test "print cXOtherFile" "No symbol \"cXOtherFile\" in current context."
  gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."
 +
 +# Test to make sure that 'maint cplus namespace' is at least picking
 +# up one of the namespaces in this file.
 +
 +# FIXME: carlton/2003-06-16: We should check to make sure it picks up
 +# all of the namespaces.  Unfortunately, I can't guarantee what order
 +# they'll be listed in when you do 'maint cplus namespace'.  Probably
 +# I should stash the output of that command in a variable somewhere
 +# and examine that variable for all of the relevant namespaces.
 +
 +# FIXME: carlton/2003-06-16: This test (like many others in this file,
 +# doubtless) will fail in non-DWARF-2 situations; I need to go through
 +# and audit the tests accordingly at some point.
 +
 +gdb_test "maint cplus namespace" ".*C::C.*"
 
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]