2003-09-11 David Carlton <carlton@kealia.com>
authorDavid Carlton <carlton@bactrian.org>
Thu, 11 Sep 2003 19:49:20 +0000 (19:49 +0000)
committerDavid Carlton <carlton@bactrian.org>
Thu, 11 Sep 2003 19:49:20 +0000 (19:49 +0000)
* gdbtypes.h: Add TYPE_CODE_NAMESPACE.
* gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE.
(recursive_dump_type): Ditto.
* printcmd.c (print_formatted): Ditto.
* typeprint.c (print_type_scalar): Ditto.
* c-typeprint.c (c_type_print_varspec_prefix): Ditto.
(c_type_print_varspec_suffix, c_type_print_base): Ditto.
* cp-support.h: Declare cp_check_possible_namespace_symbols,
maint_cplus_cmd_list.
* cp-support.c: Make maint_cplus_cmd_list extern.
* cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h,
command.h.
(lookup_symbol_file): Look in possible namespace blocks when
appropriate.
(initialize_namespace_symtab): New.
(get_possible_namespace_block, free_namespace_block)
(check_possible_namespace_symbols)
(check_possible_namespace_symbols_loop)
(check_one_possible_namespace_symbol)
(lookup_possible_namespace_symbol, maintenance_cplus_namespace)
(_initialize_cp_namespace): Ditto.
* block.h: Declare allocate_block.
* block.c (allocate_block): New.
* jv-lang.c (get_java_class_symtab): Allocate blocks via
allocate_block.
* symfile.h: Update declaration of add_psymbol_to_list.
* symfile.c (add_psymbol_to_list): Return the partial symbol in
question.
* dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to
scan_partial_symbols_call.
(scan_partial_symbols): Add NAMESPACE argument; update calls to
helper functions.
(add_partial_symbol): If necessary, scan mangled names for names
of namespaces.
(add_partial_namespace): Add NAMESPACE argument; generate partial
symbols associated  to namespaces.
(add_partial_enumeration): Add NAMESPACE argument.
(new_symbol): Allow namespace syms.
(read_namespace): Generate namespace syms.
* objfiles.h: Add opaque declaration of struct symtab.
(struct objfile): Add cp_namespace_symtab member.
* objfiles.c (allocate_objfile): Set
objfile->cp_namespace_symtab.
* Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h,
dictionary_h, command_h.

2003-09-11  David Carlton  <carlton@kealia.com>

* gdb.c++/namespace.exp: Add tests for namespace types.
* gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'.
(test_namespace): New.

21 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/block.c
gdb/block.h
gdb/c-typeprint.c
gdb/cp-namespace.c
gdb/cp-support.c
gdb/cp-support.h
gdb/dwarf2read.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/jv-lang.c
gdb/objfiles.c
gdb/objfiles.h
gdb/printcmd.c
gdb/symfile.c
gdb/symfile.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/maint.exp
gdb/testsuite/gdb.cp/namespace.exp
gdb/typeprint.c

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