* [rfa] generate symbols associated to namespaces
@ 2003-06-16 20:22 David Carlton
2003-06-22 17:42 ` Daniel Jacobowitz
0 siblings, 1 reply; 23+ messages in thread
From: David Carlton @ 2003-06-16 20:22 UTC (permalink / raw)
To: gdb-patches; +Cc: Elena Zannoni, Daniel Jacobowitz, Jim Blandy
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
}
\f
/* Add a symbol with a long value to a psymtab.
- Since one arg is a struct, we pass in a ptr and deref it (sigh). */
+ Since one arg is a struct, we pass in a ptr and deref it (sigh).
+ Return the partial symbol that has been added. */
-void
+const struct partial_symbol *
add_psymbol_to_list (char *name, int namelength, domain_enum domain,
enum address_class class,
struct psymbol_allocation_list *list, long val, /* Value as a long */
@@ -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\" 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 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 maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+ set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
- gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous."
+ set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}"
- gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME."
+ gdb_test "help maintenance cplus" "${help_maint_cp}"
+ gdb_test "help maint cp" "${help_maint_cp}"
+ gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}"
+
+ gdb_test "help maint cp first_component" "${first_component_help}."
+ gdb_test "help maint cp namespace" "${namespace_help}."
}
# This is used when NAME should contain only a single component. Be
@@ -79,6 +85,12 @@ proc test_first_component {} {
gdb_test "maint cp first_component foo::bar::baz" "foo"
gdb_test "maint cp first_component C<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.*"
^ permalink raw reply [flat|nested] 23+ messages in thread* Re: [rfa] generate symbols associated to namespaces 2003-06-16 20:22 [rfa] generate symbols associated to namespaces David Carlton @ 2003-06-22 17:42 ` Daniel Jacobowitz 2003-06-24 19:00 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: Daniel Jacobowitz @ 2003-06-22 17:42 UTC (permalink / raw) To: David Carlton; +Cc: gdb-patches, Elena Zannoni, Jim Blandy [First, a request: could your next namespace patch be the fully-qualified name inference code for full symbols? Before I end up hacking together something similar. i.e. add_partial_structure, and then all the determine_prefix related code. I'd really, really like to see that in the next release of GDB; we'll see...] On Mon, Jun 16, 2003 at 01:21:36PM -0700, David Carlton wrote: > 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. OK. I see why these symbols are necessary. > 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. This makes sense. I was worried about what we'd have to do with the "potential" namespaces. > 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. Hold on a second. There's a fundamental problem here. While it is true that namespaces may be shared across objfiles, and it is true that it's more elegant to hold them separately from any objefile, you're creating an always-expanding list of namespaces. They will never be freed. Consider the problems this can cause: prog1.cc: namespace A { namespace A { int oops; } int x; void foo() { /* A::x; error */ x; } } prog2.cc: namespace A { int x; void foo() { A::x; /* no error */ } } ./gdb prog1 ... (gdb) maint cplus namespace Definite namespaces: Possible namespaces: A::A A (gdb) file ./prog2 Load new symbol table from "./prog2"? (y or n) y Reading symbols from ./prog2...done. (gdb) maint cplus namespace Definite namespaces: Possible namespaces: A::A A Oops! You've still got A::A as a namespace. In addition there are memory concerns with this fake objfile. All in all, I don't think this use of fake objfiles is legitimate. I think you're going to have to tie a fake block to each objfile instead, which should be an acceptable compromise. Definite namespaces would go in the global block of any objfile where they are found, possible namespaces would go in a special block in any objfile in which they are inferred. lookup_possible_namespace_symbol will gain a loop over all objfiles. A few functions will have to take an objfile parameter. > 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. I'd really appreciate it if you did this differently in the future. Believe it or not, I had C++ debugging working very nicely with stabs; you don't need to make new tests pass with stabs, but please check that you do not cause existing tests to regress. The runtest invocation you'd need for this is "runtest --target_board unix/gdb:debug_flags=-gstabs+". It appears that your new code does not work with stabs debugging. When dwarf2-frame.c reaches the fake objfile, it gets an internal error because SECT_OFF_TEXT is not initialized. This appears to be a problem in the dwarf2-frame code and I just sent a separate message about it. With a workaround for that in place, the results for stabs look OK. The three new tests fail: +FAIL: gdb.c++/namespace.exp: ptype C +FAIL: gdb.c++/namespace.exp: ptype E +FAIL: gdb.c++/namespace.exp: maint cplus namespace (Most of the other tests in namespace.exp fail too.) By the way, the comment above lookup_namespace_scope is wrong, I think: For example, if we're within a function A::B::f and looking for a symbol f, this will get called with NAME = "f", SCOPE = "A::B", and SCOPE_LEN = 0. It then calls itself with NAME and SCOPE the same, but with SCOPE_LEN = 1. And then it calls itself with NAME and SCOPE the same, but with SCOPE_LEN = 4. This third call looks for "A::B::x"; if it doesn't find it, then the second call looks for "A::x", and if that call fails, then the first call looks for "x". */ Shouldn't it be "looking for a symbol x" and "NAME = "x""? Much clearer that way. Comments on the actual code follow. They're mostly minor. > 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. > @@ -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; > + } Nit: You can just say if (sym == NULL) here, and it's a little clearer, IMO. Sym will be NULL from the call above this chunk. > } > else > { > - return lookup_symbol_global (name, linkage_name, domain, symtab); > + sym = lookup_symbol_global (name, linkage_name, domain, symtab); > + } > +/* 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. */ I don't think that's realistic. But we can discuss it again in three years :) Also, if I bother to add stabs support for this, we'll need this code even longer. > + > +/* Allocate everything necessary for namespace_block and > + possible_namespace_block. */ > + > +static void > +initialize_namespace_blocks (void) > +/* 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) Hmm, the name doesn't really match what this function does. How about maybe_add_namespace_symbol? > +{ > + 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; > + } > +} > +/* 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); > + } No braces here, please. > + > + 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); > +} This function is less than the size of the comment describing why we call it, a few pages up, and only called once. Please just inline it there, unless you have plans for it... > +/* 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); No, that's not right. Bad debug information should not cause GDB to crash. Complain and skip it instead. > + 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. */ Strictly speaking INFO_PTR points to a DIE, not to a "PDI" which is this GDB-internal construction. > + > +static char * > +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, > + bfd *abfd, const struct comp_unit_head *cu_header) > +{ > @@ -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. Yeah, that would be nice. It's not terribly hard but it requires a little bit of TCL fu. > +# 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.*" As I mentioned above, I'd rather fix this than add the FIXME. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-22 17:42 ` Daniel Jacobowitz @ 2003-06-24 19:00 ` David Carlton 2003-06-24 19:02 ` Daniel Jacobowitz 0 siblings, 1 reply; 23+ messages in thread From: David Carlton @ 2003-06-24 19:00 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: gdb-patches, Elena Zannoni, Jim Blandy On Sun, 22 Jun 2003 13:35:47 -0400, Daniel Jacobowitz <drow@mvista.com> said: > [First, a request: could your next namespace patch be the > fully-qualified name inference code for full symbols? [ I'm only sort of back from vacation; I'll be really back tomorrow. Anyways... ] My plan is for the next patch to be a smallish one which has the parser handle :: better. But fully-qualified name inference, nested types, and all that fun stuff will come after that. Having said that: > I'd really, really like to see that in the next release of GDB; we'll > see...] I don't think this is a good idea. First, looking through my mailbox, the branch is about to happen (or has just happened?), and we're not supposed to add new features. More importantly, though, fully qualified types is a really large change. It's much larger than I realized it was before I started working at Kealia: if we don't have DW_TAG_namespace, then there is a quite subtle balancing act going on between the demangler and the names that are in DW_AT_name, and between getting type names right whenever possible and resigning ourselves to some lookup_transparent_type failures. If we do have DW_TAG_namespace, then I'm still not done tracing down situations where we run into problems because of DIE cross-references. The number of bug reports that I'm getting is definitely dwindling; on the other hand, I know some areas that the branch probably gets wrong currently that Kealia doesn't happen to use in its code. So I really want this stuff to go in earlier in a release cycle, so we can test it in more real-world environments before releasing it at large. It also doesn't help that the bugs that I've been seeing are really, really hard to reduce to a small test case: they frequently involve psymtab/symtab interactions, and they also frequently involve large files that happen to cause certain versions of GCC to generate the DIEs in some particular, unfortunate order. If we release a version without a lot of testing, we'll get a lot of bug reports from people who say "GDB fails in this situation, but I have no idea how to reduce the bug report in order to make it possible for you to fix it." > While it is true that namespaces may be shared across objfiles, and > it is true that it's more elegant to hold them separately from any > objefile, you're creating an always-expanding list of namespaces. > They will never be freed. Consider the problems this can cause: > prog1.cc: > namespace A { > namespace A { int oops; } > int x; > void foo() { /* A::x; error */ x; } > } > prog2.cc: > namespace A { > int x; > void foo() { A::x; /* no error */ } > } > ./gdb prog1 > ... > (gdb) maint cplus namespace > Definite namespaces: > Possible namespaces: > A::A > A > (gdb) file ./prog2 > Load new symbol table from "./prog2"? (y or n) y > Reading symbols from ./prog2...done. > (gdb) maint cplus namespace > Definite namespaces: > Possible namespaces: > A::A > A > Oops! You've still got A::A as a namespace. > In addition there are memory concerns with this fake objfile. All > in all, I don't think this use of fake objfiles is legitimate. I > think you're going to have to tie a fake block to each objfile > instead, which should be an acceptable compromise. Definite > namespaces would go in the global block of any objfile where they > are found, possible namespaces would go in a special block in any > objfile in which they are inferred. > lookup_possible_namespace_symbol will gain a loop over all objfiles. > A few functions will have to take an objfile parameter. That sounds sensible: I guess I hadn't really realized how objfiles work. I understand and agree with you about the possible namespace symbol stuff, but let me double-check on what you want with definite namespace symbols: should I stick those in each symtab where they're found, or should I put them in a special symtab (one per objfile, of course)? Either way is fine with me. > I'd really appreciate it if you did this differently in the future. > Believe it or not, I had C++ debugging working very nicely with stabs; > you don't need to make new tests pass with stabs, but please check that > you do not cause existing tests to regress. > The runtest invocation you'd need for this is "runtest --target_board > unix/gdb:debug_flags=-gstabs+". Thanks, will do. > It appears that your new code does not work with stabs debugging. When > dwarf2-frame.c reaches the fake objfile, it gets an internal error > because SECT_OFF_TEXT is not initialized. Whoops, sorry about that. For what it's worth, any problems that occur here would probably also occur with Java debugging, because they also use a fake objfile, so it's just as well that you're fixing that, even though I'll get rid of the objfile. > This appears to be a problem > in the dwarf2-frame code and I just sent a separate message about it. > With a workaround for that in place, the results for stabs look OK. Great. > The three new tests fail: > +FAIL: gdb.c++/namespace.exp: ptype C > +FAIL: gdb.c++/namespace.exp: ptype E > +FAIL: gdb.c++/namespace.exp: maint cplus namespace > (Most of the other tests in namespace.exp fail too.) Yeah. There are at least three problems with stabs namespace tests that I'm aware of: 1) Some of what I'm doing (e.g. this patch) requires modifying the actual reader to get the new functionality; I've only done that with DWARF 2. That's why the above new tests fail. 2) Some of the generic buildsym code depends on having access to mangled names; GCC 3.x doesn't give us those when doing stabs debugging. 3) In GCC 2.95.3 (with stabs, probably also with DWARF 2), anonymous namespaces get demangled to "{anonymous}" instead of "(anonymous namespace)", so I'm looking for the wrong string. (This isn't a big deal, since GCC 2.95.3's namespace support is bad enough that any serious namespace users will be using 3.x.) Parts 1 and 2 will wait until somebody with the appropriate motivation addresses them; we've talked about that before, of course. I assume part 3 is trivial to fix, so I'll deal with that at some point when I have a free moment. (I have, reluctantly, come to the conclusion that I'll have to start tweaking the various demanglers' outputs. Sigh.) Thanks for the comments on the code; I'll look at them in more detail tomorrow. David Carlton carlton@math.stanford.edu ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-24 19:00 ` David Carlton @ 2003-06-24 19:02 ` Daniel Jacobowitz 2003-06-27 16:04 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: Daniel Jacobowitz @ 2003-06-24 19:02 UTC (permalink / raw) To: David Carlton; +Cc: gdb-patches, Elena Zannoni, Jim Blandy On Tue, Jun 24, 2003 at 11:31:36AM -0700, David Carlton wrote: > On Sun, 22 Jun 2003 13:35:47 -0400, Daniel Jacobowitz <drow@mvista.com> said: > > > [First, a request: could your next namespace patch be the > > fully-qualified name inference code for full symbols? > > [ I'm only sort of back from vacation; I'll be really back tomorrow. > Anyways... ] > > My plan is for the next patch to be a smallish one which has the > parser handle :: better. But fully-qualified name inference, nested > types, and all that fun stuff will come after that. Having said that: > > > I'd really, really like to see that in the next release of GDB; we'll > > see...] > > I don't think this is a good idea. First, looking through my mailbox, I'll bow to your judgement on this. Right now it's our second-most-often reported bug in C++, after the constructor breakpoints thing. However, if we do a limited form of inference - just DW_AT_MIPS_linkage_name based - I think the risk is much smaller. If we have time to play with it... > the branch is about to happen (or has just happened?), and we're not > supposed to add new features. More importantly, though, fully > qualified types is a really large change. It's much larger than I > realized it was before I started working at Kealia: if we don't have > DW_TAG_namespace, then there is a quite subtle balancing act going on > between the demangler and the names that are in DW_AT_name, and > between getting type names right whenever possible and resigning > ourselves to some lookup_transparent_type failures. If we do have > DW_TAG_namespace, then I'm still not done tracing down situations > where we run into problems because of DIE cross-references. The No, you definitely aren't. I noticed another looking at your branch the other day, I think. > > While it is true that namespaces may be shared across objfiles, and > > it is true that it's more elegant to hold them separately from any > > objefile, you're creating an always-expanding list of namespaces. > > They will never be freed. Consider the problems this can cause: > > > prog1.cc: > > namespace A { > > namespace A { int oops; } > > int x; > > void foo() { /* A::x; error */ x; } > > } > > > prog2.cc: > > namespace A { > > int x; > > void foo() { A::x; /* no error */ } > > } > > > ./gdb prog1 > > ... > > (gdb) maint cplus namespace > > Definite namespaces: > > Possible namespaces: > > A::A > > A > > (gdb) file ./prog2 > > Load new symbol table from "./prog2"? (y or n) y > > Reading symbols from ./prog2...done. > > (gdb) maint cplus namespace > > Definite namespaces: > > Possible namespaces: > > A::A > > A > > > Oops! You've still got A::A as a namespace. > > > In addition there are memory concerns with this fake objfile. All > > in all, I don't think this use of fake objfiles is legitimate. I > > think you're going to have to tie a fake block to each objfile > > instead, which should be an acceptable compromise. Definite > > namespaces would go in the global block of any objfile where they > > are found, possible namespaces would go in a special block in any > > objfile in which they are inferred. > > lookup_possible_namespace_symbol will gain a loop over all objfiles. > > A few functions will have to take an objfile parameter. > > That sounds sensible: I guess I hadn't really realized how objfiles > work. I understand and agree with you about the possible namespace > symbol stuff, but let me double-check on what you want with definite > namespace symbols: should I stick those in each symtab where they're > found, or should I put them in a special symtab (one per objfile, of > course)? Either way is fine with me. I would prefer them in the normal global block, but if you've got a reason to do it the other way that's good too. I believe, with some minor massaging, that this will be easier. And it's fewer special cases. > > Yeah. There are at least three problems with stabs namespace tests > that I'm aware of: > > 1) Some of what I'm doing (e.g. this patch) requires modifying the > actual reader to get the new functionality; I've only done that > with DWARF 2. That's why the above new tests fail. > > 2) Some of the generic buildsym code depends on having access to > mangled names; GCC 3.x doesn't give us those when doing stabs > debugging. It always provides the mangled names for methods. Not for functions, I suppose. > Parts 1 and 2 will wait until somebody with the appropriate motivation > addresses them; we've talked about that before, of course. I assume > part 3 is trivial to fix, so I'll deal with that at some point when I > have a free moment. (I have, reluctantly, come to the conclusion that > I'll have to start tweaking the various demanglers' outputs. Sigh.) I'd still rather not do this. I have some ideas, but they're definitely long-term. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-24 19:02 ` Daniel Jacobowitz @ 2003-06-27 16:04 ` David Carlton 2003-06-27 21:58 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: David Carlton @ 2003-06-27 16:04 UTC (permalink / raw) To: gdb-patches; +Cc: Elena Zannoni, Jim Blandy On Tue, 24 Jun 2003 14:50:19 -0400, Daniel Jacobowitz <drow@mvista.com> said: > On Tue, Jun 24, 2003 at 11:31:36AM -0700, David Carlton wrote: >> On Sun, 22 Jun 2003 13:35:47 -0400, Daniel Jacobowitz <drow@mvista.com> said: >>> I'd really, really like to see that in the next release of GDB; we'll >>> see...] >> I don't think this is a good idea. First, looking through my mailbox, > I'll bow to your judgement on this. Right now it's our > second-most-often reported bug in C++, after the constructor > breakpoints thing. Yes. Unfortunately, if we do a hasty job at this, we'll have a new favorite bug in C++, namely people asking what all these "<incomplete type>" messages are about, and why they can no longer print out members of classes that they used to be able to. :-( (Incidentally, in regards to constructor breakpoints, it looks less likely than it did a couple of months ago that I'll have time to work on that. So if you need an outlet for your considerable energies, feel free to work on that one. :-) ) > However, if we do a limited form of inference - just > DW_AT_MIPS_linkage_name based - I think the risk is much smaller. > If we have time to play with it... You'd be surprised. (Or at least I was.) It turns out that it's not all that uncommon for type deduction to fail in ways that confuse lookup_transparent_type no end. Sigh. Anyways, don't worry: we really are making progress on this, and it really will be there for 6.1. >>> I think you're going to have to tie a fake block to each objfile >>> instead, which should be an acceptable compromise. Definite >>> namespaces would go in the global block of any objfile where they >>> are found, possible namespaces would go in a special block in any >>> objfile in which they are inferred. >>> lookup_possible_namespace_symbol will gain a loop over all >>> objfiles. A few functions will have to take an objfile parameter. >> That sounds sensible: I guess I hadn't really realized how objfiles >> work. I understand and agree with you about the possible namespace >> symbol stuff, but let me double-check on what you want with >> definite namespace symbols: should I stick those in each symtab >> where they're found, or should I put them in a special symtab (one >> per objfile, of course)? Either way is fine with me. > I would prefer them in the normal global block, but if you've got a > reason to do it the other way that's good too. I believe, with some > minor massaging, that this will be easier. And it's fewer special > cases. You're probably right; I'll treat them like normal symbols, then. I've looked at your code comments, and they all seem reasonable. I hope I'll have a revised version of the patch today; job transition issues will take up some of my time (I start full-time work at Kealia today, so I have to figure out what they want me to do other than hack GDB), but it's near the top of my priority list. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-27 16:04 ` David Carlton @ 2003-06-27 21:58 ` David Carlton 2003-06-27 22:32 ` David Carlton ` (3 more replies) 0 siblings, 4 replies; 23+ messages in thread From: David Carlton @ 2003-06-27 21:58 UTC (permalink / raw) To: gdb-patches; +Cc: Elena Zannoni, Jim Blandy, Daniel Jacobowitz On Fri, 27 Jun 2003 09:04:13 -0700, David Carlton <carlton@kealia.com> said: > I've looked at your code comments, and they all seem reasonable. I > hope I'll have a revised version of the patch today; job transition > issues will take up some of my time (I start full-time work at > Kealia today, so I have to figure out what they want me to do other > than hack GDB), but it's near the top of my priority list. Okay, here's the new version. Following Daniel's suggestion, it puts symbols associated to DW_TAG_namespace in the symtab where they are found, instead of in a special block, and creates one possible namespace block for each objfile. This fixes the problem Daniel found with the last version of my patch (which, incidentally, turns out also to show up under DWARF 2 with pr-1210.exp; the more tests the merrier). Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+, and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs. No new regressions (though the new tests in gdb.c++/namespace.exp fail under stabs+, as expected). How does this one look to y'all? David Carlton carlton@kealia.com 2003-06-27 David Carlton <carlton@kealia.com> * gdbtypes.h: Add TYPE_CODE_NAMESPACE. * gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE. (recursive_dump_type): Ditto. * printcmd.c (print_formatted): Ditto. * typeprint.c (print_type_scalar): Ditto. * c-typeprint.c (c_type_print_varspec_prefix): Ditto. (c_type_print_varspec_suffix, c_type_print_base): Ditto. * cp-support.h: Declare cp_check_possible_namespace_symbols, maint_cplus_cmd_list. * cp-support.c: Make maint_cplus_cmd_list extern. * cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h, command.h. (lookup_symbol_file): Look in possible namespace blocks when appropriate. (initialize_namespace_symtab): New. (get_possible_namespace_block, free_namespace_block) (check_possible_namespace_symbols) (check_possible_namespace_symbols_loop) (check_one_possible_namespace_symbol) (lookup_possible_namespace_symbol, maintenance_cplus_namespace) (_initialize_cp_namespace): Ditto. * block.h: Declare allocate_block. * block.c (allocate_block): New. * jv-lang.c (get_java_class_symtab): Allocate blocks via allocate_block. * symfile.h: Update declaration of add_psymbol_to_list. * symfile.c (add_psymbol_to_list): Return the partial symbol in question. * dwarf2read.c (dwarf2_build_psymtabs_hard): Do initial setting lowpc and highpc ourselves. Add argument to scan_partial_symbols_call. (scan_partial_symbols): Restructure into a recursive version, calling add_partial_namespace and add_partial_enumeration when appropriate. (add_partial_symbol): If necessary, scan mangled names for names of namespaces. (add_partial_namespace): New. (add_partial_enumeration, locate_pdi_sibling): Ditto. * objfiles.h (struct objfile): Add cp_namespace_symtab member. * objfiles.c (allocate_objfile): Set objfile->cp_namespace_symtab. * Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h, dictionary_h, command_h. 2003-06-27 David Carlton <carlton@kealia.com> * gdb.c++/namespace.exp: Add tests for namespace types. * gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'. (test_namespace): New. Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.410 diff -u -p -r1.410 Makefile.in --- Makefile.in 21 Jun 2003 23:14:43 -0000 1.410 +++ Makefile.in 27 Jun 2003 21:37:38 -0000 @@ -1642,7 +1642,8 @@ corelow.o: corelow.c $(defs_h) $(gdb_str cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(command_h) \ $(gdbcmd_h) $(ui_out_h) $(gdb_string_h) cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \ - $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) + $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) $(objfiles_h) \ + $(gdbtypes_h) $(dictionary_h) $(command_h) cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \ $(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \ $(objfiles_h) $(frame_h) $(block_h) Index: block.c =================================================================== RCS file: /cvs/src/src/gdb/block.c,v retrieving revision 1.7 diff -u -p -r1.7 block.c --- block.c 2 Jun 2003 18:36:33 -0000 1.7 +++ block.c 27 Jun 2003 21:37:40 -0000 @@ -268,3 +268,28 @@ block_global_block (const struct block * return block; } + +/* Allocate a block on OBSTACK, and initialize its elements to + zero/NULL. This is useful for creating "dummy" blocks that don't + correspond to actual source files. + + Warning: it sets the block's BLOCK_DICT to NULL, which isn't a + valid value. If you really don't want the block to have a + dictionary, then you should subsequently set its BLOCK_DICT to + dict_create_linear (obstack, NULL). */ + +struct block * +allocate_block (struct obstack *obstack) +{ + struct block *bl = obstack_alloc (obstack, sizeof (struct block)); + + BLOCK_START (bl) = 0; + BLOCK_END (bl) = 0; + BLOCK_FUNCTION (bl) = NULL; + BLOCK_SUPERBLOCK (bl) = NULL; + BLOCK_DICT (bl) = NULL; + BLOCK_NAMESPACE (bl) = NULL; + BLOCK_GCC_COMPILED (bl) = 0; + + return bl; +} Index: block.h =================================================================== RCS file: /cvs/src/src/gdb/block.h,v retrieving revision 1.8 diff -u -p -r1.8 block.h --- block.h 11 Jun 2003 23:29:46 -0000 1.8 +++ block.h 27 Jun 2003 21:37:40 -0000 @@ -171,4 +171,6 @@ extern const struct block *block_static_ extern const struct block *block_global_block (const struct block *block); +extern struct block *allocate_block (struct obstack *obstack); + #endif /* BLOCK_H */ Index: c-typeprint.c =================================================================== RCS file: /cvs/src/src/gdb/c-typeprint.c,v retrieving revision 1.26 diff -u -p -r1.26 c-typeprint.c --- c-typeprint.c 4 Jan 2003 21:54:54 -0000 1.26 +++ c-typeprint.c 27 Jun 2003 21:37:58 -0000 @@ -284,6 +284,7 @@ c_type_print_varspec_prefix (struct type case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types need no prefix. They are listed here so that gcc -Wall will reveal any types that haven't been handled. */ break; @@ -624,6 +625,7 @@ c_type_print_varspec_suffix (struct type case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types do not need a suffix. They are listed so that gcc -Wall will report types that may not have been considered. */ break; @@ -1180,6 +1182,11 @@ c_type_print_base (struct type *type, st fprintf_filtered (stream, "\n"); } } + break; + + case TYPE_CODE_NAMESPACE: + fputs_filtered ("namespace ", stream); + fputs_filtered (TYPE_TAG_NAME (type), stream); break; default: Index: cp-namespace.c =================================================================== RCS file: /cvs/src/src/gdb/cp-namespace.c,v retrieving revision 1.3 diff -u -p -r1.3 cp-namespace.c --- cp-namespace.c 13 Jun 2003 00:55:43 -0000 1.3 +++ cp-namespace.c 27 Jun 2003 21:38:02 -0000 @@ -27,6 +27,10 @@ #include "symfile.h" #include "gdb_assert.h" #include "block.h" +#include "objfiles.h" +#include "gdbtypes.h" +#include "dictionary.h" +#include "command.h" /* When set, the file that we're processing seems to have debugging info for C++ namespaces, so cp-namespace.c shouldn't try to guess @@ -70,6 +74,26 @@ static struct symbol *lookup_symbol_file struct symtab **symtab, int anonymous_namespace); +static void initialize_namespace_symtab (struct objfile *objfile); + +static struct block *get_possible_namespace_block (struct objfile *objfile); + +static void free_namespace_block (struct symtab *symtab); + +static int check_possible_namespace_symbols_loop (const char *name, + int len, + struct objfile *objfile); + +static int check_one_possible_namespace_symbol (const char *name, + int len, + struct objfile *objfile); + +static +struct symbol *lookup_possible_namespace_symbol (const char *name, + struct symtab **symtab); + +static void maintenance_cplus_namespace (char *args, int from_tty); + /* Set up support for dealing with C++ namespace info in the current symtab. */ @@ -453,13 +477,268 @@ lookup_symbol_file (const char *name, const struct block *global_block = block_global_block (block); if (global_block != NULL) - return lookup_symbol_aux_block (name, linkage_name, global_block, - domain, symtab); - else - return NULL; + sym = lookup_symbol_aux_block (name, linkage_name, global_block, + domain, symtab); + } + else + { + sym = lookup_symbol_global (name, linkage_name, domain, symtab); + } + + if (sym != NULL) + return sym; + + /* Now call "lookup_possible_namespace_symbol". Symbols in here + claim to be associated to namespaces, but this claim might be + incorrect: the names in question might actually correspond to + classes instead of namespaces. But if they correspond to + classes, then we should have found a match for them above. So if + we find them now, they should be genuine. */ + + /* FIXME: carlton/2003-06-12: This is a hack and should eventually + be deleted: see comments below. */ + + if (domain == VAR_DOMAIN) + { + sym = lookup_possible_namespace_symbol (name, symtab); + if (sym != NULL) + return sym; + } + + return NULL; +} + +/* Now come functions for dealing with symbols associated to + namespaces. (They're used to store the namespaces themselves, not + objects that live in the namespaces.) These symbols come in two + varieties: if we run into a DW_TAG_namespace DIE, then we know that + we have a namespace, so dwarf2read.c creates a symbol for it just + like normal. But, unfortunately, versions of GCC through at least + 3.3 don't generate those DIE's. Our solution is to try to guess + their existence by looking at demangled names. This might cause us + to misidentify classes as namespaces, however. So we put those + symbols in a special block (one per objfile), and we only search + that block as a last resort. */ + +/* FIXME: carlton/2003-06-12: Once versions of GCC that generate + DW_TAG_namespace have been out for a year or two, we should get rid + of all of this "possible namespace" nonsense. */ + +/* Allocate everything necessary the possible namespace block + associated to OBJFILE. */ + +static void +initialize_namespace_symtab (struct objfile *objfile) +{ + struct symtab *namespace_symtab; + struct blockvector *bv; + struct block *bl; + + namespace_symtab = allocate_symtab ("<<C++-namespaces>>", objfile); + namespace_symtab->language = language_cplus; + namespace_symtab->free_code = free_nothing; + namespace_symtab->dirname = NULL; + + bv = obstack_alloc (&objfile->symbol_obstack, + sizeof (struct blockvector) + + FIRST_LOCAL_BLOCK * sizeof (struct block *)); + BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1; + BLOCKVECTOR (namespace_symtab) = bv; + + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ + + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, + NULL); + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, + NULL); + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; + + /* Allocate the possible namespace block; we put it where the first + local block will live, though I don't think there's any need to + pretend that it's actually a local block (e.g. by setting + BLOCK_SUPERBLOCK appropriately). */ + + bl = allocate_block (&objfile->symbol_obstack); + BLOCK_DICT (bl) = dict_create_hashed_expandable (); + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; + + namespace_symtab->free_func = free_namespace_block; + + objfile->cp_namespace_symtab = namespace_symtab; +} + +/* Locate the possible namespace block associated to OBJFILE, + allocating it if necessary. */ + +static struct block * +get_possible_namespace_block (struct objfile *objfile) +{ + if (objfile->cp_namespace_symtab == NULL) + initialize_namespace_symtab (objfile); + + return BLOCKVECTOR_BLOCK (BLOCKVECTOR (objfile->cp_namespace_symtab), + FIRST_LOCAL_BLOCK); +} + +/* Free the dictionary associated to the possible namespace block. */ + +static void +free_namespace_block (struct symtab *symtab) +{ + struct block *possible_namespace_block; + + possible_namespace_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), + FIRST_LOCAL_BLOCK); + gdb_assert (possible_namespace_block != NULL); + dict_free (BLOCK_DICT (possible_namespace_block)); +} + +/* Ensure that there are symbols in the possible namespace block + associated to OBJFILE for all initial substrings of NAME that look + like namespaces or classes. NAME should end in a member variable: + it shouldn't consist solely of namespaces. */ + +void +cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile) +{ + check_possible_namespace_symbols_loop (name, + cp_find_first_component (name), + objfile); +} + +/* This is a helper loop for cp_check_possible_namespace_symbols; it + ensures that there are symbols in the possible namespace block + associated to OBJFILE for all namespaces that are initial + substrings of NAME of length at least LEN. It returns 1 if a + previous loop had already created the shortest such symbol and 0 + otherwise. + + This function assumes that if there is already a symbol associated + to a substring of NAME of a given length, then there are already + symbols associated to all substrings of NAME whose length is less + than that length. So if cp_check_possible_namespace_symbols has + been called once with argument "A::B::C::member", then that will + create symbols "A", "A::B", and "A::B::C". If it is then later + called with argument "A::B::D::member", then the new call will + generate a new symbol for "A::B::D", but once it sees that "A::B" + has already been created, it doesn't bother checking to see if "A" + has also been created. */ + +static int +check_possible_namespace_symbols_loop (const char *name, int len, + struct objfile *objfile) +{ + if (name[len] == ':') + { + int done; + int next_len = len + 2; + + next_len += cp_find_first_component (name + next_len); + done = check_possible_namespace_symbols_loop (name, next_len, + objfile); + + if (!done) + done = check_one_possible_namespace_symbol (name, len, objfile); + + return done; } else + return 0; +} + +/* Check to see if there's already a possible namespace symbol in + OBJFILE whose name is the initial substring of NAME of length LEN. + If not, create one and return 0; otherwise, return 1. */ + +static int +check_one_possible_namespace_symbol (const char *name, int len, + struct objfile *objfile) +{ + struct block *block = get_possible_namespace_block (objfile); + char *name_copy = obsavestring (name, len, &objfile->symbol_obstack); + struct symbol *sym = lookup_block_symbol (block, name_copy, NULL, + VAR_DOMAIN); + + if (sym == NULL) { - return lookup_symbol_global (name, linkage_name, domain, symtab); + struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + name_copy, objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_LANGUAGE (sym) = language_cplus; + SYMBOL_SET_NAMES (sym, name_copy, len, objfile); + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_TYPE (sym) = type; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + + dict_add_symbol (BLOCK_DICT (block), sym); + + return 0; } + else + { + obstack_free (&objfile->symbol_obstack, name_copy); + + return 1; + } +} + +/* Look for a symbol named NAME in all the possible namespace blocks. + If one is found, return it; if SYMTAB is non-NULL, set *SYMTAB to + equal the symtab where it was found. */ + +static struct symbol * +lookup_possible_namespace_symbol (const char *name, struct symtab **symtab) +{ + struct objfile *objfile; + + ALL_OBJFILES (objfile) + { + struct symbol *sym; + + sym = lookup_block_symbol (get_possible_namespace_block (objfile), + name, NULL, VAR_DOMAIN); + + if (sym != NULL) + { + if (symtab != NULL) + *symtab = objfile->cp_namespace_symtab; + + return sym; + } + } + + return NULL; +} + +/* Print out all the possible namespace symbols. */ + +static void +maintenance_cplus_namespace (char *args, int from_tty) +{ + struct objfile *objfile; + printf_unfiltered ("Possible namespaces:\n"); + ALL_OBJFILES (objfile) + { + struct dict_iterator iter; + struct symbol *sym; + + ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym) + { + printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); + } + } +} + +void +_initialize_cp_namespace (void) +{ + add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace, + "Print the list of possible C++ namespaces.", + &maint_cplus_cmd_list); } Index: cp-support.c =================================================================== RCS file: /cvs/src/src/gdb/cp-support.c,v retrieving revision 1.5 diff -u -p -r1.5 cp-support.c --- cp-support.c 12 Jun 2003 15:33:45 -0000 1.5 +++ cp-support.c 27 Jun 2003 21:38:07 -0000 @@ -45,7 +45,7 @@ static void overload_list_add_symbol (st /* The list of "maint cplus" commands. */ -static struct cmd_list_element *maint_cplus_cmd_list = NULL; +struct cmd_list_element *maint_cplus_cmd_list = NULL; /* The actual commands. */ Index: cp-support.h =================================================================== RCS file: /cvs/src/src/gdb/cp-support.h,v retrieving revision 1.6 diff -u -p -r1.6 cp-support.h --- cp-support.h 12 Jun 2003 15:33:45 -0000 1.6 +++ cp-support.h 27 Jun 2003 21:38:12 -0000 @@ -96,4 +96,11 @@ extern struct symbol *cp_lookup_symbol_n const domain_enum domain, struct symtab **symtab); +extern void cp_check_possible_namespace_symbols (const char *name, + struct objfile *objfile); + +/* The list of "maint cplus" commands. */ + +extern struct cmd_list_element *maint_cplus_cmd_list; + #endif /* CP_SUPPORT_H */ Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.97 diff -u -p -r1.97 dwarf2read.c --- dwarf2read.c 26 Jun 2003 21:20:39 -0000 1.97 +++ dwarf2read.c 27 Jun 2003 21:38:33 -0000 @@ -678,10 +678,30 @@ static void dwarf2_build_psymtabs_hard ( static char *scan_partial_symbols (char *, struct objfile *, CORE_ADDR *, CORE_ADDR *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); static void add_partial_symbol (struct partial_die_info *, struct objfile *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); + +static char *add_partial_namespace (struct partial_die_info *pdi, + char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *add_partial_enumeration (struct partial_die_info *enum_pdi, + char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *locate_pdi_sibling (struct partial_die_info *orig_pdi, + char *info_ptr, + bfd *abfd, + const struct comp_unit_head *cu_header); static void dwarf2_psymtab_to_symtab (struct partial_symtab *); @@ -1327,9 +1347,17 @@ dwarf2_build_psymtabs_hard (struct objfi If not, there's no more debug_info for this comp unit. */ if (comp_unit_die.has_children) { + lowpc = ((CORE_ADDR) -1); + highpc = ((CORE_ADDR) 0); + info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, - &cu_header); + &cu_header, NULL); + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + /* If the compilation unit didn't have an explicit address range, then use the information extracted from its child dies. */ if (! comp_unit_die.has_pc_info) @@ -1358,45 +1386,40 @@ dwarf2_build_psymtabs_hard (struct objfi do_cleanups (back_to); } -/* Read in all interesting dies to the end of the compilation unit. */ +/* Read in all interesting dies to the end of the compilation unit or + to the end of the current namespace. NAMESPACE is NULL if we + haven't yet encountered any DW_TAG_namespace entries; otherwise, + it's the name of the current namespace. In particular, it's the + empty string if we're currently in the global namespace but have + previously encountered a DW_TAG_namespace. */ static char * scan_partial_symbols (char *info_ptr, struct objfile *objfile, CORE_ADDR *lowpc, CORE_ADDR *highpc, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { bfd *abfd = objfile->obfd; struct partial_die_info pdi; - /* This function is called after we've read in the comp_unit_die in - order to read its children. We start the nesting level at 1 since - we have pushed 1 level down in order to read the comp unit's children. - The comp unit itself is at level 0, so we stop reading when we pop - back to that level. */ - - int nesting_level = 1; - - /* We only want to read in symbols corresponding to variables or - other similar objects that are global or static. Normally, these - are all children of the DW_TAG_compile_unit die, so are all at - level 1. But C++ namespaces give ries to DW_TAG_namespace dies - whose children are global objects. So we keep track of what - level we currently think of as referring to file scope; this - should always equal 1 plus the number of namespaces that we are - currently nested within. */ - - int file_scope_level = 1; - - *lowpc = ((CORE_ADDR) -1); - *highpc = ((CORE_ADDR) 0); + /* Now, march along the PDI's, descending into ones which have + interesting children but skipping the children of the other ones, + until we reach the end of the compilation unit. */ - while (nesting_level) + while (1) { + /* This flag tells whether or not info_ptr has gotten updated + inside the loop. */ + int info_ptr_updated = 0; + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); - /* Anonymous namespaces have no name but are interesting. */ + /* Anonymous namespaces have no name but have interesting + children, so we need to look at them. Ditto for anonymous + enums. */ - if (pdi.name != NULL || pdi.tag == DW_TAG_namespace) + if (pdi.name != NULL || pdi.tag == DW_TAG_namespace + || pdi.tag == DW_TAG_enumeration_type) { switch (pdi.tag) { @@ -1411,93 +1434,77 @@ scan_partial_symbols (char *info_ptr, st { *highpc = pdi.highpc; } - if ((pdi.is_external || nesting_level == file_scope_level) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } } break; case DW_TAG_variable: case DW_TAG_typedef: + case DW_TAG_union_type: case DW_TAG_class_type: case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - if ((pdi.is_external || nesting_level == file_scope_level) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } break; - case DW_TAG_enumerator: - /* File scope enumerators are added to the partial - symbol table. They're children of the enumeration - type die, so they occur at a level one higher than we - normally look for. */ - if (nesting_level == file_scope_level + 1) - add_partial_symbol (&pdi, objfile, cu_header); + case DW_TAG_enumeration_type: + if (!pdi.is_declaration) + { + info_ptr = add_partial_enumeration (&pdi, info_ptr, + objfile, cu_header, + namespace); + info_ptr_updated = 1; + } break; case DW_TAG_base_type: /* File scope base type definitions are added to the partial symbol table. */ - if (nesting_level == file_scope_level) - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); break; case DW_TAG_namespace: - /* FIXME: carlton/2002-10-16: we're not yet doing - anything useful with this, but for now make sure that - these tags at least don't cause us to miss any - important symbols. */ - if (pdi.has_children) - file_scope_level++; + /* We've hit a DW_TAG_namespace entry, so we know this + file has been compiled using a compiler that + generates them; update NAMESPACE to reflect that. */ + if (namespace == NULL) + namespace = ""; + info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, + lowpc, highpc, cu_header, + namespace); + info_ptr_updated = 1; + break; default: break; } } - /* If the die has a sibling, skip to the sibling. Do not skip - enumeration types, we want to record their enumerators. Do - not skip namespaces, we want to record symbols inside - them. */ - if (pdi.sibling - && pdi.tag != DW_TAG_enumeration_type - && pdi.tag != DW_TAG_namespace) - { - info_ptr = pdi.sibling; - } - else if (pdi.has_children) - { - /* Die has children, but either the optional DW_AT_sibling - attribute is missing or we want to look at them. */ - nesting_level++; - } - if (pdi.tag == 0) - { - nesting_level--; - /* If this is the end of a DW_TAG_namespace entry, then - decrease the file_scope_level, too. */ - if (nesting_level < file_scope_level) - { - file_scope_level--; - gdb_assert (nesting_level == file_scope_level); - } - } + break; + + /* If the die has a sibling, skip to the sibling, unless another + function has already updated info_ptr for us. */ + + /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether + or not we want to update this depends on enough stuff (not + only pdi.tag but also whether or not pdi.name is NULL) that + this seems like the easiest way to handle the issue. */ + + if (!info_ptr_updated) + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); } - /* If we didn't find a lowpc, set it to highpc to avoid complaints - from `maint check'. */ - if (*lowpc == ((CORE_ADDR) -1)) - *lowpc = *highpc; return info_ptr; } static void add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { CORE_ADDR addr = 0; + const struct partial_symbol *psym = NULL; switch (pdi->tag) { @@ -1506,19 +1513,21 @@ add_partial_symbol (struct partial_die_i { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->global_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } else { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_file_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->static_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } break; case DW_TAG_variable: @@ -1540,10 +1549,11 @@ add_partial_symbol (struct partial_die_i if (pdi->locdesc) addr = decode_locdesc (pdi->locdesc, objfile, cu_header); if (pdi->locdesc || pdi->has_type) - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->global_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } else { @@ -1553,10 +1563,11 @@ add_partial_symbol (struct partial_die_i addr = decode_locdesc (pdi->locdesc, objfile, cu_header); /*prim_record_minimal_symbol (pdi->name, addr + baseaddr, mst_file_data, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->static_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } break; case DW_TAG_typedef: @@ -1597,6 +1608,124 @@ add_partial_symbol (struct partial_die_i default: break; } + + /* Check to see if we should scan the name for possible namespace + info. Only do this if this is C++, if we don't have namespace + debugging info in the file, if the psym is of an appropriate type + (otherwise we'll have psym == NULL), and if we actually had a + mangled name to begin with. */ + + if (cu_language == language_cplus + && namespace == NULL + && psym != NULL + && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) + cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym), + objfile); +} + +/* Read a partial die corresponding to a namespace; also, add a symbol + corresponding to that namespace to the symbol table. NAMESPACE is + the name of the enclosing namespace. */ + +static char * +add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + /* Calculate the full name of the namespace that we just entered. */ + + const char *new_name = pdi->name; + char *full_name; + + if (new_name == NULL) + new_name = "(anonymous namespace)"; + full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1); + strcpy (full_name, namespace); + if (*namespace != '\0') + strcat (full_name, "::"); + strcat (full_name, new_name); + + /* FIXME: carlton/2003-06-27: Once we build qualified names for more + symbols than just namespaces, we should replace this by a call to + add_partial_symbol. */ + + add_psymbol_to_list (full_name, strlen (full_name), + VAR_DOMAIN, LOC_TYPEDEF, + &objfile->global_psymbols, + 0, 0, cu_language, objfile); + + /* Now scan partial symbols in that namespace. */ + + if (pdi->has_children) + info_ptr = scan_partial_symbols (info_ptr, objfile, + lowpc, highpc, + cu_header, full_name); + + return info_ptr; +} + +/* Read a partial die corresponding to an enumeration type. */ + +static char * +add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + bfd *abfd = objfile->obfd; + struct partial_die_info pdi; + + if (enum_pdi->name != NULL) + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); + + while (1) + { + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + if (pdi.tag == 0) + break; + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) + complaint (&symfile_complaints, "malformed enumerator DIE ignored"); + else + add_partial_symbol (&pdi, objfile, cu_header, namespace); + } + + return info_ptr; +} + +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE + after ORIG_PDI. */ + +static char * +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, + bfd *abfd, const struct comp_unit_head *cu_header) +{ + /* Do we know the sibling already? */ + + if (orig_pdi->sibling) + return orig_pdi->sibling; + + /* Are there any children to deal with? */ + + if (!orig_pdi->has_children) + return info_ptr; + + /* Okay, we don't know the sibling, but we have children that we + want to skip. So read children until we run into one without a + tag; return whatever follows it. */ + + while (1) + { + struct partial_die_info pdi; + + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + + if (pdi.tag == 0) + return info_ptr; + else + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); + } } /* Expand this partial symbol table into a full symbol table. */ @@ -3260,6 +3389,23 @@ read_namespace (struct die_info *die, st strlen (previous_namespace), strlen (processing_current_namespace)); + /* Add a symbol associated to this if we haven't seen the namespace + before. */ + + if (dwarf2_extension (die) == NULL) + { + struct type *type; + + /* FIXME: carlton/2003-06-27: Once GDB is more const-correct, + this cast will hopefully become unnecessary. */ + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + (char *) processing_current_namespace, + objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + new_symbol (die, type, objfile, cu_header); + } + if (die->has_children) { struct die_info *child_die = die->next; @@ -5113,7 +5259,11 @@ new_symbol (struct die_info *die, struct struct attribute *attr2 = NULL; CORE_ADDR addr = 0; - name = dwarf2_linkage_name (die); + if (die->tag != DW_TAG_namespace) + name = dwarf2_linkage_name (die); + else + name = TYPE_NAME (type); + if (name) { sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, @@ -5291,6 +5441,10 @@ new_symbol (struct die_info *die, struct dwarf2_const_value (attr, sym, objfile, cu_header); } add_symbol_to_list (sym, list_in_scope); + break; + case DW_TAG_namespace: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + add_symbol_to_list (sym, &global_symbols); break; default: /* Not a tag we recognize. Hopefully we aren't processing Index: gdbtypes.c =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.c,v retrieving revision 1.74 diff -u -p -r1.74 gdbtypes.c --- gdbtypes.c 23 Jun 2003 21:05:40 -0000 1.74 +++ gdbtypes.c 27 Jun 2003 21:38:38 -0000 @@ -1897,7 +1897,8 @@ init_type (enum type_code code, int leng if (name && strcmp (name, "char") == 0) TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; - if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION + || code == TYPE_CODE_NAMESPACE) { INIT_CPLUS_SPECIFIC (type); } @@ -3144,6 +3145,9 @@ recursive_dump_type (struct type *type, break; case TYPE_CODE_TEMPLATE_ARG: printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)"); + break; + case TYPE_CODE_NAMESPACE: + printf_filtered ("(TYPE_CODE_NAMESPACE)"); break; default: printf_filtered ("(UNKNOWN TYPE CODE)"); Index: gdbtypes.h =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.h,v retrieving revision 1.48 diff -u -p -r1.48 gdbtypes.h --- gdbtypes.h 23 Jun 2003 21:05:40 -0000 1.48 +++ gdbtypes.h 27 Jun 2003 21:38:50 -0000 @@ -134,8 +134,9 @@ enum type_code TYPE_CODE_TYPEDEF, TYPE_CODE_TEMPLATE, /* C++ template */ - TYPE_CODE_TEMPLATE_ARG /* C++ template arg */ + TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */ + TYPE_CODE_NAMESPACE, /* C++ namespace. */ }; /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an Index: jv-lang.c =================================================================== RCS file: /cvs/src/src/gdb/jv-lang.c,v retrieving revision 1.21 diff -u -p -r1.21 jv-lang.c --- jv-lang.c 11 Jun 2003 23:29:47 -0000 1.21 +++ jv-lang.c 27 Jun 2003 21:38:55 -0000 @@ -111,22 +111,13 @@ get_java_class_symtab (void) BLOCKVECTOR (class_symtab) = bv; /* Allocate dummy STATIC_BLOCK. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, NULL); - BLOCK_START (bl) = 0; - BLOCK_END (bl) = 0; - BLOCK_FUNCTION (bl) = NULL; - BLOCK_SUPERBLOCK (bl) = NULL; - BLOCK_NAMESPACE (bl) = NULL; - BLOCK_GCC_COMPILED (bl) = 0; BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; - /* Allocate GLOBAL_BLOCK. This has to be relocatable. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); - *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + /* Allocate GLOBAL_BLOCK. */ + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_hashed_expandable (); BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; class_symtab->free_func = free_class_block; Index: objfiles.c =================================================================== RCS file: /cvs/src/src/gdb/objfiles.c,v retrieving revision 1.33 diff -u -p -r1.33 objfiles.c --- objfiles.c 11 Jun 2003 23:29:47 -0000 1.33 +++ objfiles.c 27 Jun 2003 21:38:55 -0000 @@ -332,10 +332,14 @@ allocate_objfile (bfd *abfd, int flags) /* Initialize the section indexes for this objfile, so that we can later detect if they are used w/o being properly assigned to. */ - objfile->sect_index_text = -1; - objfile->sect_index_data = -1; - objfile->sect_index_bss = -1; - objfile->sect_index_rodata = -1; + objfile->sect_index_text = -1; + objfile->sect_index_data = -1; + objfile->sect_index_bss = -1; + objfile->sect_index_rodata = -1; + + /* We don't yet have a C++-specific namespace symtab. */ + + objfile->cp_namespace_symtab = NULL; /* Add this file onto the tail of the linked list of other such files. */ Index: objfiles.h =================================================================== RCS file: /cvs/src/src/gdb/objfiles.h,v retrieving revision 1.22 diff -u -p -r1.22 objfiles.h --- objfiles.h 24 Mar 2003 03:54:48 -0000 1.22 +++ objfiles.h 27 Jun 2003 21:39:07 -0000 @@ -28,6 +28,7 @@ struct bcache; struct htab; +struct symtab; /* This structure maintains information on a per-objfile basis about the "entry point" of the objfile, and the scope within which the entry point @@ -436,6 +437,13 @@ struct objfile /* Place to stash various statistics about this objfile */ OBJSTATS; + + /* A symtab that the C++ code uses to stash special symbols + associated to namespaces. */ + + /* FIXME/carlton-2003-06-27: Delete this in a few years once + "possible namespace symbols" go away. */ + struct symtab *cp_namespace_symtab; }; /* Defines for the objfile flag word. */ Index: printcmd.c =================================================================== RCS file: /cvs/src/src/gdb/printcmd.c,v retrieving revision 1.63 diff -u -p -r1.63 printcmd.c --- printcmd.c 9 Jun 2003 15:20:21 -0000 1.63 +++ printcmd.c 27 Jun 2003 21:39:09 -0000 @@ -315,7 +315,8 @@ print_formatted (struct value *val, regi || TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_CODE (type) == TYPE_CODE_STRING || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) /* If format is 0, use the 'natural' format for * that type of value. If the type is non-scalar, * we have to use language rules to print it as Index: symfile.c =================================================================== RCS file: /cvs/src/src/gdb/symfile.c,v retrieving revision 1.101 diff -u -p -r1.101 symfile.c --- symfile.c 27 Jun 2003 13:11:17 -0000 1.101 +++ symfile.c 27 Jun 2003 21:39:23 -0000 @@ -2631,9 +2631,10 @@ start_psymtab_common (struct objfile *ob } \f /* Add a symbol with a long value to a psymtab. - Since one arg is a struct, we pass in a ptr and deref it (sigh). */ + Since one arg is a struct, we pass in a ptr and deref it (sigh). + Return the partial symbol that has been added. */ -void +const struct partial_symbol * add_psymbol_to_list (char *name, int namelength, domain_enum domain, enum address_class class, struct psymbol_allocation_list *list, long val, /* Value as a long */ @@ -2676,6 +2677,8 @@ add_psymbol_to_list (char *name, int nam } *list->next++ = psym; OBJSTAT (objfile, n_psyms++); + + return psym; } /* Add a symbol with a long value to a psymtab. This differs from Index: symfile.h =================================================================== RCS file: /cvs/src/src/gdb/symfile.h,v retrieving revision 1.24 diff -u -p -r1.24 symfile.h --- symfile.h 11 Jun 2003 22:27:13 -0000 1.24 +++ symfile.h 27 Jun 2003 21:39:26 -0000 @@ -152,9 +152,12 @@ extern void extend_psymbol_list (struct /* #include "demangle.h" */ -extern void add_psymbol_to_list (char *, int, domain_enum, enum address_class, - struct psymbol_allocation_list *, long, - CORE_ADDR, enum language, struct objfile *); +extern const +struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum, + enum address_class, + struct psymbol_allocation_list *, + long, CORE_ADDR, + enum language, struct objfile *); extern void add_psymbol_with_dem_name_to_list (char *, int, char *, int, domain_enum, Index: typeprint.c =================================================================== RCS file: /cvs/src/src/gdb/typeprint.c,v retrieving revision 1.18 diff -u -p -r1.18 typeprint.c --- typeprint.c 8 Jun 2003 18:27:14 -0000 1.18 +++ typeprint.c 27 Jun 2003 21:39:28 -0000 @@ -307,6 +307,7 @@ print_type_scalar (struct type *type, LO case TYPE_CODE_MEMBER: case TYPE_CODE_METHOD: case TYPE_CODE_REF: + case TYPE_CODE_NAMESPACE: error ("internal error: unhandled type in print_type_scalar"); break; Index: testsuite/gdb.c++/maint.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/maint.exp,v retrieving revision 1.2 diff -u -p -r1.2 maint.exp --- testsuite/gdb.c++/maint.exp 23 Apr 2003 23:45:24 -0000 1.2 +++ testsuite/gdb.c++/maint.exp 27 Jun 2003 21:39:29 -0000 @@ -29,13 +29,19 @@ if $tracelevel then { # Test the help messages. proc test_help {} { - gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set first_component_help "Print the first class/namespace component of NAME" + set namespace_help "Print the list of possible C\\+\\+ namespaces" - gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." - gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}" - gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME." + gdb_test "help maintenance cplus" "${help_maint_cp}" + gdb_test "help maint cp" "${help_maint_cp}" + gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}" + + gdb_test "help maint cp first_component" "${first_component_help}." + gdb_test "help maint cp namespace" "${namespace_help}." } # This is used when NAME should contain only a single component. Be @@ -79,6 +85,12 @@ proc test_first_component {} { gdb_test "maint cp first_component foo::bar::baz" "foo" gdb_test "maint cp first_component C<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's not a lot we can do to test this. + + gdb_test "maint cp namespace" "Possible namespaces:" } gdb_exit Index: testsuite/gdb.c++/namespace.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.exp,v retrieving revision 1.13 diff -u -p -r1.13 namespace.exp --- testsuite/gdb.c++/namespace.exp 20 May 2003 03:56:29 -0000 1.13 +++ testsuite/gdb.c++/namespace.exp 27 Jun 2003 21:39:29 -0000 @@ -208,6 +208,8 @@ gdb_test "print cd" "\\$\[0-9\].* = 3" gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5" gdb_test "print shadow" "\\$\[0-9\].* = 13" gdb_test "print cOtherFile" "\\$\[0-9\].* = 316" +gdb_test "ptype C" "type = namespace C::C" +gdb_test "ptype E" "type = namespace C::D::E" # Some anonymous namespace tests. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-27 21:58 ` David Carlton @ 2003-06-27 22:32 ` David Carlton 2003-08-05 16:30 ` David Carlton ` (2 subsequent siblings) 3 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-06-27 22:32 UTC (permalink / raw) To: gdb-patches; +Cc: Elena Zannoni, Jim Blandy, Daniel Jacobowitz On Fri, 27 Jun 2003 14:58:50 -0700, David Carlton <carlton@kealia.com> said: > How does this one look to y'all? Whoops, the ChangeLog entry isn't quite right: the following lines should be added to the entry for dwarf2read.c. (new_symbol): Allow namespace syms. (read_namespace): Generate namespace syms. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-27 21:58 ` David Carlton 2003-06-27 22:32 ` David Carlton @ 2003-08-05 16:30 ` David Carlton 2003-08-05 17:54 ` Daniel Jacobowitz 2003-09-09 19:42 ` Elena Zannoni 3 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-08-05 16:30 UTC (permalink / raw) To: gdb-patches; +Cc: Elena Zannoni, Jim Blandy, Daniel Jacobowitz On Fri, 27 Jun 2003 14:58:50 -0700, David Carlton <carlton@kealia.com> said: > Okay, here's the new version. Following Daniel's suggestion, it puts > symbols associated to DW_TAG_namespace in the symtab where they are > found, instead of in a special block, and creates one possible > namespace block for each objfile. This fixes the problem Daniel found > with the last version of my patch (which, incidentally, turns out also > to show up under DWARF 2 with pr-1210.exp; the more tests the > merrier). > Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+, > and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs. > No new regressions (though the new tests in gdb.c++/namespace.exp fail > under stabs+, as expected). > How does this one look to y'all? Ping? David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-27 21:58 ` David Carlton 2003-06-27 22:32 ` David Carlton 2003-08-05 16:30 ` David Carlton @ 2003-08-05 17:54 ` Daniel Jacobowitz 2003-08-05 18:06 ` David Carlton 2003-08-31 19:29 ` Daniel Jacobowitz 2003-09-09 19:42 ` Elena Zannoni 3 siblings, 2 replies; 23+ messages in thread From: Daniel Jacobowitz @ 2003-08-05 17:54 UTC (permalink / raw) To: gdb-patches On Fri, Jun 27, 2003 at 02:58:50PM -0700, David Carlton wrote: > On Fri, 27 Jun 2003 09:04:13 -0700, David Carlton <carlton@kealia.com> said: > > > I've looked at your code comments, and they all seem reasonable. I > > hope I'll have a revised version of the patch today; job transition > > issues will take up some of my time (I start full-time work at > > Kealia today, so I have to figure out what they want me to do other > > than hack GDB), but it's near the top of my priority list. > > Okay, here's the new version. Following Daniel's suggestion, it puts > symbols associated to DW_TAG_namespace in the symtab where they are > found, instead of in a special block, and creates one possible > namespace block for each objfile. This fixes the problem Daniel found > with the last version of my patch (which, incidentally, turns out also > to show up under DWARF 2 with pr-1210.exp; the more tests the > merrier). > > Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+, > and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs. > No new regressions (though the new tests in gdb.c++/namespace.exp fail > under stabs+, as expected). > > How does this one look to y'all? Sorry 'bout the delay. This looks good to me; Elena? Minor comments: > +/* Allocate everything necessary the possible namespace block > + associated to OBJFILE. */ Grammar :) > + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ > + > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > + NULL); > + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > + NULL); > + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; > + > + /* Allocate the possible namespace block; we put it where the first > + local block will live, though I don't think there's any need to > + pretend that it's actually a local block (e.g. by setting > + BLOCK_SUPERBLOCK appropriately). */ > + > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_hashed_expandable (); > + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; Is there any particular reason not to use the global block? If so might want to comment what it is. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-08-05 17:54 ` Daniel Jacobowitz @ 2003-08-05 18:06 ` David Carlton 2003-08-05 18:08 ` Daniel Jacobowitz 2003-08-31 19:29 ` Daniel Jacobowitz 1 sibling, 1 reply; 23+ messages in thread From: David Carlton @ 2003-08-05 18:06 UTC (permalink / raw) To: gdb-patches On Tue, 5 Aug 2003 13:54:29 -0400, Daniel Jacobowitz <drow@mvista.com> said: > On Fri, Jun 27, 2003 at 02:58:50PM -0700, David Carlton wrote: >> + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ >> + >> + bl = allocate_block (&objfile->symbol_obstack); >> + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, >> + NULL); >> + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; >> + bl = allocate_block (&objfile->symbol_obstack); >> + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, >> + NULL); >> + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; >> + >> + /* Allocate the possible namespace block; we put it where the first >> + local block will live, though I don't think there's any need to >> + pretend that it's actually a local block (e.g. by setting >> + BLOCK_SUPERBLOCK appropriately). */ >> + >> + bl = allocate_block (&objfile->symbol_obstack); >> + BLOCK_DICT (bl) = dict_create_hashed_expandable (); >> + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; > Is there any particular reason not to use the global block? If so > might want to comment what it is. Yes: we never want these symbols to be found by a normal search of all symtabs' global blocks, because we don't trust these symbols. We only want them found as a last resort, once we've looked every place that symbols associated to classes should live. So that's why I stash them in a local block. I'll add a comment to that effect. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-08-05 18:06 ` David Carlton @ 2003-08-05 18:08 ` Daniel Jacobowitz 2003-08-05 18:18 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: Daniel Jacobowitz @ 2003-08-05 18:08 UTC (permalink / raw) To: gdb-patches On Tue, Aug 05, 2003 at 11:06:28AM -0700, David Carlton wrote: > On Tue, 5 Aug 2003 13:54:29 -0400, Daniel Jacobowitz <drow@mvista.com> said: > > On Fri, Jun 27, 2003 at 02:58:50PM -0700, David Carlton wrote: > > >> + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ > >> + > >> + bl = allocate_block (&objfile->symbol_obstack); > >> + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > >> + NULL); > >> + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; > >> + bl = allocate_block (&objfile->symbol_obstack); > >> + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > >> + NULL); > >> + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; > >> + > >> + /* Allocate the possible namespace block; we put it where the first > >> + local block will live, though I don't think there's any need to > >> + pretend that it's actually a local block (e.g. by setting > >> + BLOCK_SUPERBLOCK appropriately). */ > >> + > >> + bl = allocate_block (&objfile->symbol_obstack); > >> + BLOCK_DICT (bl) = dict_create_hashed_expandable (); > >> + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; > > > Is there any particular reason not to use the global block? If so > > might want to comment what it is. > > Yes: we never want these symbols to be found by a normal search of all > symtabs' global blocks, because we don't trust these symbols. We only > want them found as a last resort, once we've looked every place that > symbols associated to classes should live. So that's why I stash them > in a local block. I'll add a comment to that effect. OK. I would have thought that the fake symtab would never have been searched normally, though - I guess it gets chained into objfile->symtabs? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-08-05 18:08 ` Daniel Jacobowitz @ 2003-08-05 18:18 ` David Carlton 0 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-08-05 18:18 UTC (permalink / raw) To: gdb-patches On Tue, 5 Aug 2003 14:08:39 -0400, Daniel Jacobowitz <drow@mvista.com> said: > On Tue, Aug 05, 2003 at 11:06:28AM -0700, David Carlton wrote: >> On Tue, 5 Aug 2003 13:54:29 -0400, Daniel Jacobowitz <drow@mvista.com> said: >>> Is there any particular reason not to use the global block? If so >>> might want to comment what it is. >> Yes: we never want these symbols to be found by a normal search of >> all symtabs' global blocks, because we don't trust these symbols. >> We only want them found as a last resort, once we've looked every >> place that symbols associated to classes should live. So that's >> why I stash them in a local block. I'll add a comment to that >> effect. > OK. I would have thought that the fake symtab would never have been > searched normally, though - I guess it gets chained into > objfile-> symtabs? Yeah, allocate_symtab does that automatically. I'm a little tempted not to have a symtab there at all, instead just having a special block (or even a special dictionary) that isn't associated to a symtab. That, however, runs into the issue of what to do with the 'symtab' argument to lookup_symbol in that case; we could set it to NULL, but in that case GDB might crash if some silly user typed 'break NamespaceName'. Or something. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-08-05 17:54 ` Daniel Jacobowitz 2003-08-05 18:06 ` David Carlton @ 2003-08-31 19:29 ` Daniel Jacobowitz 2003-09-02 16:38 ` David Carlton 1 sibling, 1 reply; 23+ messages in thread From: Daniel Jacobowitz @ 2003-08-31 19:29 UTC (permalink / raw) To: gdb-patches; +Cc: carlton, ezannoni On Tue, Aug 05, 2003 at 01:54:29PM -0400, Daniel Jacobowitz wrote: > On Fri, Jun 27, 2003 at 02:58:50PM -0700, David Carlton wrote: > > On Fri, 27 Jun 2003 09:04:13 -0700, David Carlton <carlton@kealia.com> said: > > > > > I've looked at your code comments, and they all seem reasonable. I > > > hope I'll have a revised version of the patch today; job transition > > > issues will take up some of my time (I start full-time work at > > > Kealia today, so I have to figure out what they want me to do other > > > than hack GDB), but it's near the top of my priority list. > > > > Okay, here's the new version. Following Daniel's suggestion, it puts > > symbols associated to DW_TAG_namespace in the symtab where they are > > found, instead of in a special block, and creates one possible > > namespace block for each objfile. This fixes the problem Daniel found > > with the last version of my patch (which, incidentally, turns out also > > to show up under DWARF 2 with pr-1210.exp; the more tests the > > merrier). > > > > Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+, > > and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs. > > No new regressions (though the new tests in gdb.c++/namespace.exp fail > > under stabs+, as expected). > > > > How does this one look to y'all? > > Sorry 'bout the delay. This looks good to me; Elena? This patch needs a trivial update for the gdb.c++ -> gdb.cp rename, and IIRC one other merge update for the testsuite; and the comments we discussed downthread. Mind reposting it? Elena, could you look at this? I have some other C++ work which is blocked waiting for this patch. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-08-31 19:29 ` Daniel Jacobowitz @ 2003-09-02 16:38 ` David Carlton 0 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-09-02 16:38 UTC (permalink / raw) To: gdb-patches; +Cc: ezannoni, Jim Blandy, Andrew Cagney On Sun, 31 Aug 2003 15:29:50 -0400, Daniel Jacobowitz <drow@mvista.com> said: > This patch needs a trivial update for the gdb.c++ -> gdb.cp rename, > and IIRC one other merge update for the testsuite; and the comments > we discussed downthread. Mind reposting it? I'll see if I can find time to do that, though I'm a bit busy right now. But, frankly, I do mind reposting it (though I'm certainly not blaming you for this): the patch has been awaiting symtab review for two and a half months, and I shouldn't have to spend the time keeping it up to date while waiting for the symtab maintainers to get around to it. I had a lot of time to work on GDB through the end of June; I have much less time to work on GDB now. I'm still willing to spend the time trying to get my branch merged into the mainline sources, but I'd rather spend my limited GDB time doing things that are actually productive (generating new patches, responding to criticism of them, fixing bugs) instead of rehashing old patches. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-06-27 21:58 ` David Carlton ` (2 preceding siblings ...) 2003-08-05 17:54 ` Daniel Jacobowitz @ 2003-09-09 19:42 ` Elena Zannoni 2003-09-09 20:28 ` David Carlton 2003-09-11 23:28 ` [rfa] use allocate_block more David Carlton 3 siblings, 2 replies; 23+ messages in thread From: Elena Zannoni @ 2003-09-09 19:42 UTC (permalink / raw) To: David Carlton; +Cc: gdb-patches David Carlton writes: > On Fri, 27 Jun 2003 09:04:13 -0700, David Carlton <carlton@kealia.com> said: > > > I've looked at your code comments, and they all seem reasonable. I > > hope I'll have a revised version of the patch today; job transition > > issues will take up some of my time (I start full-time work at > > Kealia today, so I have to figure out what they want me to do other > > than hack GDB), but it's near the top of my priority list. > > Okay, here's the new version. Following Daniel's suggestion, it puts > symbols associated to DW_TAG_namespace in the symtab where they are > found, instead of in a special block, and creates one possible > namespace block for each objfile. This fixes the problem Daniel found > with the last version of my patch (which, incidentally, turns out also > to show up under DWARF 2 with pr-1210.exp; the more tests the > merrier). > > Tested with GCC 3.2, i686-pc-linux-gnu with both DWARF 2 and stabs+, > and with a version of GCC 3.2.3 that generates DW_TAG_namespace DIEs. > No new regressions (though the new tests in gdb.c++/namespace.exp fail > under stabs+, as expected). > > How does this one look to y'all? It looks ok, but there are a couple of things I'd like to see addressed, see below. elena > > David Carlton > carlton@kealia.com > > 2003-06-27 David Carlton <carlton@kealia.com> > > * gdbtypes.h: Add TYPE_CODE_NAMESPACE. > * gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE. > (recursive_dump_type): Ditto. > * printcmd.c (print_formatted): Ditto. > * typeprint.c (print_type_scalar): Ditto. > * c-typeprint.c (c_type_print_varspec_prefix): Ditto. > (c_type_print_varspec_suffix, c_type_print_base): Ditto. > * cp-support.h: Declare cp_check_possible_namespace_symbols, > maint_cplus_cmd_list. > * cp-support.c: Make maint_cplus_cmd_list extern. > * cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h, > command.h. > (lookup_symbol_file): Look in possible namespace blocks when > appropriate. > (initialize_namespace_symtab): New. > (get_possible_namespace_block, free_namespace_block) > (check_possible_namespace_symbols) > (check_possible_namespace_symbols_loop) > (check_one_possible_namespace_symbol) > (lookup_possible_namespace_symbol, maintenance_cplus_namespace) > (_initialize_cp_namespace): Ditto. > * block.h: Declare allocate_block. > * block.c (allocate_block): New. > * jv-lang.c (get_java_class_symtab): Allocate blocks via > allocate_block. > * symfile.h: Update declaration of add_psymbol_to_list. > * symfile.c (add_psymbol_to_list): Return the partial symbol in > question. > * dwarf2read.c (dwarf2_build_psymtabs_hard): Do initial setting > lowpc and highpc ourselves. Add argument to > scan_partial_symbols_call. > (scan_partial_symbols): Restructure into a recursive version, > calling add_partial_namespace and add_partial_enumeration when > appropriate. > (add_partial_symbol): If necessary, scan mangled names for names > of namespaces. > (add_partial_namespace): New. > (add_partial_enumeration, locate_pdi_sibling): Ditto. > * objfiles.h (struct objfile): Add cp_namespace_symtab member. > * objfiles.c (allocate_objfile): Set > objfile->cp_namespace_symtab. > * Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h, > dictionary_h, command_h. > > 2003-06-27 David Carlton <carlton@kealia.com> > > * gdb.c++/namespace.exp: Add tests for namespace types. > * gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'. > (test_namespace): New. > > Index: Makefile.in > =================================================================== > RCS file: /cvs/src/src/gdb/Makefile.in,v > retrieving revision 1.410 > diff -u -p -r1.410 Makefile.in > --- Makefile.in 21 Jun 2003 23:14:43 -0000 1.410 > +++ Makefile.in 27 Jun 2003 21:37:38 -0000 > @@ -1642,7 +1642,8 @@ corelow.o: corelow.c $(defs_h) $(gdb_str > cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(command_h) \ > $(gdbcmd_h) $(ui_out_h) $(gdb_string_h) > cp-namespace.o: cp-namespace.c $(defs_h) $(cp_support_h) $(gdb_obstack_h) \ > - $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) > + $(symtab_h) $(symfile_h) $(gdb_assert_h) $(block_h) $(objfiles_h) \ > + $(gdbtypes_h) $(dictionary_h) $(command_h) > cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \ > $(demangle_h) $(gdb_assert_h) $(gdbcmd_h) $(dictionary_h) \ > $(objfiles_h) $(frame_h) $(block_h) > Index: block.c > =================================================================== > RCS file: /cvs/src/src/gdb/block.c,v > retrieving revision 1.7 > diff -u -p -r1.7 block.c > --- block.c 2 Jun 2003 18:36:33 -0000 1.7 > +++ block.c 27 Jun 2003 21:37:40 -0000 > @@ -268,3 +268,28 @@ block_global_block (const struct block * > > return block; > } > + > +/* Allocate a block on OBSTACK, and initialize its elements to > + zero/NULL. This is useful for creating "dummy" blocks that don't > + correspond to actual source files. > + > + Warning: it sets the block's BLOCK_DICT to NULL, which isn't a > + valid value. If you really don't want the block to have a > + dictionary, then you should subsequently set its BLOCK_DICT to > + dict_create_linear (obstack, NULL). */ > + > +struct block * > +allocate_block (struct obstack *obstack) > +{ > + struct block *bl = obstack_alloc (obstack, sizeof (struct block)); > + > + BLOCK_START (bl) = 0; > + BLOCK_END (bl) = 0; > + BLOCK_FUNCTION (bl) = NULL; > + BLOCK_SUPERBLOCK (bl) = NULL; > + BLOCK_DICT (bl) = NULL; > + BLOCK_NAMESPACE (bl) = NULL; > + BLOCK_GCC_COMPILED (bl) = 0; > + > + return bl; > +} > Index: block.h > =================================================================== > RCS file: /cvs/src/src/gdb/block.h,v > retrieving revision 1.8 > diff -u -p -r1.8 block.h > --- block.h 11 Jun 2003 23:29:46 -0000 1.8 > +++ block.h 27 Jun 2003 21:37:40 -0000 > @@ -171,4 +171,6 @@ extern const struct block *block_static_ > > extern const struct block *block_global_block (const struct block *block); > > +extern struct block *allocate_block (struct obstack *obstack); > + > #endif /* BLOCK_H */ > Index: c-typeprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/c-typeprint.c,v > retrieving revision 1.26 > diff -u -p -r1.26 c-typeprint.c > --- c-typeprint.c 4 Jan 2003 21:54:54 -0000 1.26 > +++ c-typeprint.c 27 Jun 2003 21:37:58 -0000 > @@ -284,6 +284,7 @@ c_type_print_varspec_prefix (struct type > case TYPE_CODE_BITSTRING: > case TYPE_CODE_COMPLEX: > case TYPE_CODE_TEMPLATE: > + case TYPE_CODE_NAMESPACE: > /* These types need no prefix. They are listed here so that > gcc -Wall will reveal any types that haven't been handled. */ > break; > @@ -624,6 +625,7 @@ c_type_print_varspec_suffix (struct type > case TYPE_CODE_BITSTRING: > case TYPE_CODE_COMPLEX: > case TYPE_CODE_TEMPLATE: > + case TYPE_CODE_NAMESPACE: > /* These types do not need a suffix. They are listed so that > gcc -Wall will report types that may not have been considered. */ > break; > @@ -1180,6 +1182,11 @@ c_type_print_base (struct type *type, st > fprintf_filtered (stream, "\n"); > } > } > + break; > + > + case TYPE_CODE_NAMESPACE: > + fputs_filtered ("namespace ", stream); > + fputs_filtered (TYPE_TAG_NAME (type), stream); > break; > > default: > Index: cp-namespace.c > =================================================================== > RCS file: /cvs/src/src/gdb/cp-namespace.c,v > retrieving revision 1.3 > diff -u -p -r1.3 cp-namespace.c > --- cp-namespace.c 13 Jun 2003 00:55:43 -0000 1.3 > +++ cp-namespace.c 27 Jun 2003 21:38:02 -0000 > @@ -27,6 +27,10 @@ > #include "symfile.h" > #include "gdb_assert.h" > #include "block.h" > +#include "objfiles.h" > +#include "gdbtypes.h" > +#include "dictionary.h" > +#include "command.h" > > /* When set, the file that we're processing seems to have debugging > info for C++ namespaces, so cp-namespace.c shouldn't try to guess > @@ -70,6 +74,26 @@ static struct symbol *lookup_symbol_file > struct symtab **symtab, > int anonymous_namespace); > > +static void initialize_namespace_symtab (struct objfile *objfile); > + > +static struct block *get_possible_namespace_block (struct objfile *objfile); > + > +static void free_namespace_block (struct symtab *symtab); > + > +static int check_possible_namespace_symbols_loop (const char *name, > + int len, > + struct objfile *objfile); > + > +static int check_one_possible_namespace_symbol (const char *name, > + int len, > + struct objfile *objfile); > + > +static > +struct symbol *lookup_possible_namespace_symbol (const char *name, > + struct symtab **symtab); > + > +static void maintenance_cplus_namespace (char *args, int from_tty); > + > /* Set up support for dealing with C++ namespace info in the current > symtab. */ > > @@ -453,13 +477,268 @@ lookup_symbol_file (const char *name, > const struct block *global_block = block_global_block (block); > > if (global_block != NULL) > - return lookup_symbol_aux_block (name, linkage_name, global_block, > - domain, symtab); > - else > - return NULL; > + sym = lookup_symbol_aux_block (name, linkage_name, global_block, > + domain, symtab); > + } > + else > + { > + sym = lookup_symbol_global (name, linkage_name, domain, symtab); > + } > + > + if (sym != NULL) > + return sym; > + > + /* Now call "lookup_possible_namespace_symbol". Symbols in here > + claim to be associated to namespaces, but this claim might be > + incorrect: the names in question might actually correspond to > + classes instead of namespaces. But if they correspond to > + classes, then we should have found a match for them above. So if > + we find them now, they should be genuine. */ > + > + /* FIXME: carlton/2003-06-12: This is a hack and should eventually > + be deleted: see comments below. */ > + > + if (domain == VAR_DOMAIN) > + { > + sym = lookup_possible_namespace_symbol (name, symtab); > + if (sym != NULL) > + return sym; > + } > + > + return NULL; > +} > + > +/* Now come functions for dealing with symbols associated to > + namespaces. (They're used to store the namespaces themselves, not > + objects that live in the namespaces.) These symbols come in two > + varieties: if we run into a DW_TAG_namespace DIE, then we know that > + we have a namespace, so dwarf2read.c creates a symbol for it just > + like normal. But, unfortunately, versions of GCC through at least > + 3.3 don't generate those DIE's. Our solution is to try to guess > + their existence by looking at demangled names. This might cause us > + to misidentify classes as namespaces, however. So we put those > + symbols in a special block (one per objfile), and we only search > + that block as a last resort. */ > + > +/* FIXME: carlton/2003-06-12: Once versions of GCC that generate > + DW_TAG_namespace have been out for a year or two, we should get rid > + of all of this "possible namespace" nonsense. */ > + > +/* Allocate everything necessary the possible namespace block > + associated to OBJFILE. */ > + > +static void > +initialize_namespace_symtab (struct objfile *objfile) > +{ > + struct symtab *namespace_symtab; > + struct blockvector *bv; > + struct block *bl; > + > + namespace_symtab = allocate_symtab ("<<C++-namespaces>>", objfile); > + namespace_symtab->language = language_cplus; > + namespace_symtab->free_code = free_nothing; > + namespace_symtab->dirname = NULL; > + > + bv = obstack_alloc (&objfile->symbol_obstack, > + sizeof (struct blockvector) > + + FIRST_LOCAL_BLOCK * sizeof (struct block *)); > + BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1; > + BLOCKVECTOR (namespace_symtab) = bv; > + > + /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ > + > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > + NULL); > + BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > + NULL); > + BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; > + > + /* Allocate the possible namespace block; we put it where the first > + local block will live, though I don't think there's any need to > + pretend that it's actually a local block (e.g. by setting > + BLOCK_SUPERBLOCK appropriately). */ > + > + bl = allocate_block (&objfile->symbol_obstack); > + BLOCK_DICT (bl) = dict_create_hashed_expandable (); > + BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; > + > + namespace_symtab->free_func = free_namespace_block; > + > + objfile->cp_namespace_symtab = namespace_symtab; > +} > + > +/* Locate the possible namespace block associated to OBJFILE, > + allocating it if necessary. */ > + > +static struct block * > +get_possible_namespace_block (struct objfile *objfile) > +{ > + if (objfile->cp_namespace_symtab == NULL) > + initialize_namespace_symtab (objfile); > + > + return BLOCKVECTOR_BLOCK (BLOCKVECTOR (objfile->cp_namespace_symtab), > + FIRST_LOCAL_BLOCK); > +} > + > +/* Free the dictionary associated to the possible namespace block. */ > + > +static void > +free_namespace_block (struct symtab *symtab) > +{ > + struct block *possible_namespace_block; > + > + possible_namespace_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), > + FIRST_LOCAL_BLOCK); > + gdb_assert (possible_namespace_block != NULL); > + dict_free (BLOCK_DICT (possible_namespace_block)); > +} > + > +/* Ensure that there are symbols in the possible namespace block > + associated to OBJFILE for all initial substrings of NAME that look > + like namespaces or classes. NAME should end in a member variable: > + it shouldn't consist solely of namespaces. */ > + > +void > +cp_check_possible_namespace_symbols (const char *name, struct objfile *objfile) > +{ > + check_possible_namespace_symbols_loop (name, > + cp_find_first_component (name), > + objfile); > +} > + > +/* This is a helper loop for cp_check_possible_namespace_symbols; it > + ensures that there are symbols in the possible namespace block > + associated to OBJFILE for all namespaces that are initial > + substrings of NAME of length at least LEN. It returns 1 if a > + previous loop had already created the shortest such symbol and 0 > + otherwise. > + > + This function assumes that if there is already a symbol associated > + to a substring of NAME of a given length, then there are already > + symbols associated to all substrings of NAME whose length is less > + than that length. So if cp_check_possible_namespace_symbols has > + been called once with argument "A::B::C::member", then that will > + create symbols "A", "A::B", and "A::B::C". If it is then later > + called with argument "A::B::D::member", then the new call will > + generate a new symbol for "A::B::D", but once it sees that "A::B" > + has already been created, it doesn't bother checking to see if "A" > + has also been created. */ > + > +static int > +check_possible_namespace_symbols_loop (const char *name, int len, > + struct objfile *objfile) > +{ > + if (name[len] == ':') > + { > + int done; > + int next_len = len + 2; > + > + next_len += cp_find_first_component (name + next_len); > + done = check_possible_namespace_symbols_loop (name, next_len, > + objfile); > + > + if (!done) > + done = check_one_possible_namespace_symbol (name, len, objfile); > + > + return done; > } > else > + return 0; > +} > + > +/* Check to see if there's already a possible namespace symbol in > + OBJFILE whose name is the initial substring of NAME of length LEN. > + If not, create one and return 0; otherwise, return 1. */ > + > +static int > +check_one_possible_namespace_symbol (const char *name, int len, > + struct objfile *objfile) > +{ > + struct block *block = get_possible_namespace_block (objfile); > + char *name_copy = obsavestring (name, len, &objfile->symbol_obstack); > + struct symbol *sym = lookup_block_symbol (block, name_copy, NULL, > + VAR_DOMAIN); > + > + if (sym == NULL) > { > - return lookup_symbol_global (name, linkage_name, domain, symtab); > + struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0, > + name_copy, objfile); > + TYPE_TAG_NAME (type) = TYPE_NAME (type); > + > + sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); > + memset (sym, 0, sizeof (struct symbol)); > + SYMBOL_LANGUAGE (sym) = language_cplus; > + SYMBOL_SET_NAMES (sym, name_copy, len, objfile); > + SYMBOL_CLASS (sym) = LOC_TYPEDEF; > + SYMBOL_TYPE (sym) = type; > + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; > + > + dict_add_symbol (BLOCK_DICT (block), sym); > + > + return 0; > } > + else > + { > + obstack_free (&objfile->symbol_obstack, name_copy); > + > + return 1; > + } > +} > + > +/* Look for a symbol named NAME in all the possible namespace blocks. > + If one is found, return it; if SYMTAB is non-NULL, set *SYMTAB to > + equal the symtab where it was found. */ > + > +static struct symbol * > +lookup_possible_namespace_symbol (const char *name, struct symtab **symtab) > +{ > + struct objfile *objfile; > + > + ALL_OBJFILES (objfile) > + { > + struct symbol *sym; > + > + sym = lookup_block_symbol (get_possible_namespace_block (objfile), > + name, NULL, VAR_DOMAIN); > + > + if (sym != NULL) > + { > + if (symtab != NULL) > + *symtab = objfile->cp_namespace_symtab; > + > + return sym; > + } > + } > + > + return NULL; > +} > + > +/* Print out all the possible namespace symbols. */ > + > +static void > +maintenance_cplus_namespace (char *args, int from_tty) > +{ > + struct objfile *objfile; > + printf_unfiltered ("Possible namespaces:\n"); > + ALL_OBJFILES (objfile) > + { > + struct dict_iterator iter; > + struct symbol *sym; > + > + ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), iter, sym) > + { > + printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); > + } > + } > +} > + > +void > +_initialize_cp_namespace (void) > +{ > + add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace, > + "Print the list of possible C++ namespaces.", > + &maint_cplus_cmd_list); > } > Index: cp-support.c > =================================================================== > RCS file: /cvs/src/src/gdb/cp-support.c,v > retrieving revision 1.5 > diff -u -p -r1.5 cp-support.c > --- cp-support.c 12 Jun 2003 15:33:45 -0000 1.5 > +++ cp-support.c 27 Jun 2003 21:38:07 -0000 > @@ -45,7 +45,7 @@ static void overload_list_add_symbol (st > > /* The list of "maint cplus" commands. */ > > -static struct cmd_list_element *maint_cplus_cmd_list = NULL; > +struct cmd_list_element *maint_cplus_cmd_list = NULL; > > /* The actual commands. */ > > Index: cp-support.h > =================================================================== > RCS file: /cvs/src/src/gdb/cp-support.h,v > retrieving revision 1.6 > diff -u -p -r1.6 cp-support.h > --- cp-support.h 12 Jun 2003 15:33:45 -0000 1.6 > +++ cp-support.h 27 Jun 2003 21:38:12 -0000 > @@ -96,4 +96,11 @@ extern struct symbol *cp_lookup_symbol_n > const domain_enum domain, > struct symtab **symtab); > > +extern void cp_check_possible_namespace_symbols (const char *name, > + struct objfile *objfile); > + > +/* The list of "maint cplus" commands. */ > + > +extern struct cmd_list_element *maint_cplus_cmd_list; > + > #endif /* CP_SUPPORT_H */ > Index: dwarf2read.c > =================================================================== > RCS file: /cvs/src/src/gdb/dwarf2read.c,v > retrieving revision 1.97 > diff -u -p -r1.97 dwarf2read.c > --- dwarf2read.c 26 Jun 2003 21:20:39 -0000 1.97 > +++ dwarf2read.c 27 Jun 2003 21:38:33 -0000 > @@ -678,10 +678,30 @@ static void dwarf2_build_psymtabs_hard ( > > static char *scan_partial_symbols (char *, struct objfile *, > CORE_ADDR *, CORE_ADDR *, > - const struct comp_unit_head *); > + const struct comp_unit_head *, > + const char *namespace); > > static void add_partial_symbol (struct partial_die_info *, struct objfile *, > - const struct comp_unit_head *); > + const struct comp_unit_head *, > + const char *namespace); > + > +static char *add_partial_namespace (struct partial_die_info *pdi, > + char *info_ptr, > + struct objfile *objfile, > + CORE_ADDR *lowpc, CORE_ADDR *highpc, > + const struct comp_unit_head *cu_header, > + const char *namespace); > + > +static char *add_partial_enumeration (struct partial_die_info *enum_pdi, > + char *info_ptr, > + struct objfile *objfile, > + const struct comp_unit_head *cu_header, > + const char *namespace); > + > +static char *locate_pdi_sibling (struct partial_die_info *orig_pdi, > + char *info_ptr, > + bfd *abfd, > + const struct comp_unit_head *cu_header); > > static void dwarf2_psymtab_to_symtab (struct partial_symtab *); > > @@ -1327,9 +1347,17 @@ dwarf2_build_psymtabs_hard (struct objfi > If not, there's no more debug_info for this comp unit. */ > if (comp_unit_die.has_children) > { > + lowpc = ((CORE_ADDR) -1); > + highpc = ((CORE_ADDR) 0); > + > info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, > - &cu_header); > + &cu_header, NULL); > > + /* If we didn't find a lowpc, set it to highpc to avoid > + complaints from `maint check'. */ > + if (lowpc == ((CORE_ADDR) -1)) > + lowpc = highpc; > + > /* If the compilation unit didn't have an explicit address range, > then use the information extracted from its child dies. */ > if (! comp_unit_die.has_pc_info) > @@ -1358,45 +1386,40 @@ dwarf2_build_psymtabs_hard (struct objfi > do_cleanups (back_to); > } > > -/* Read in all interesting dies to the end of the compilation unit. */ > +/* Read in all interesting dies to the end of the compilation unit or > + to the end of the current namespace. NAMESPACE is NULL if we > + haven't yet encountered any DW_TAG_namespace entries; otherwise, > + it's the name of the current namespace. In particular, it's the > + empty string if we're currently in the global namespace but have > + previously encountered a DW_TAG_namespace. */ > > static char * > scan_partial_symbols (char *info_ptr, struct objfile *objfile, > CORE_ADDR *lowpc, CORE_ADDR *highpc, > - const struct comp_unit_head *cu_header) > + const struct comp_unit_head *cu_header, > + const char *namespace) > { > bfd *abfd = objfile->obfd; > struct partial_die_info pdi; > > - /* This function is called after we've read in the comp_unit_die in > - order to read its children. We start the nesting level at 1 since > - we have pushed 1 level down in order to read the comp unit's children. > - The comp unit itself is at level 0, so we stop reading when we pop > - back to that level. */ > - > - int nesting_level = 1; > - > - /* We only want to read in symbols corresponding to variables or > - other similar objects that are global or static. Normally, these > - are all children of the DW_TAG_compile_unit die, so are all at > - level 1. But C++ namespaces give ries to DW_TAG_namespace dies > - whose children are global objects. So we keep track of what > - level we currently think of as referring to file scope; this > - should always equal 1 plus the number of namespaces that we are > - currently nested within. */ > - > - int file_scope_level = 1; > - > - *lowpc = ((CORE_ADDR) -1); > - *highpc = ((CORE_ADDR) 0); > + /* Now, march along the PDI's, descending into ones which have > + interesting children but skipping the children of the other ones, > + until we reach the end of the compilation unit. */ > > - while (nesting_level) > + while (1) > { > + /* This flag tells whether or not info_ptr has gotten updated > + inside the loop. */ > + int info_ptr_updated = 0; > + > info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); > > - /* Anonymous namespaces have no name but are interesting. */ > + /* Anonymous namespaces have no name but have interesting > + children, so we need to look at them. Ditto for anonymous > + enums. */ > > - if (pdi.name != NULL || pdi.tag == DW_TAG_namespace) > + if (pdi.name != NULL || pdi.tag == DW_TAG_namespace > + || pdi.tag == DW_TAG_enumeration_type) > { > switch (pdi.tag) > { > @@ -1411,93 +1434,77 @@ scan_partial_symbols (char *info_ptr, st > { > *highpc = pdi.highpc; > } > - if ((pdi.is_external || nesting_level == file_scope_level) > - && !pdi.is_declaration) > + if (!pdi.is_declaration) > { > - add_partial_symbol (&pdi, objfile, cu_header); > + add_partial_symbol (&pdi, objfile, cu_header, namespace); > } > } > break; > case DW_TAG_variable: > case DW_TAG_typedef: > + case DW_TAG_union_type: > case DW_TAG_class_type: > case DW_TAG_structure_type: > - case DW_TAG_union_type: > - case DW_TAG_enumeration_type: > - if ((pdi.is_external || nesting_level == file_scope_level) > - && !pdi.is_declaration) > + if (!pdi.is_declaration) > { > - add_partial_symbol (&pdi, objfile, cu_header); > + add_partial_symbol (&pdi, objfile, cu_header, namespace); > } > break; > - case DW_TAG_enumerator: > - /* File scope enumerators are added to the partial > - symbol table. They're children of the enumeration > - type die, so they occur at a level one higher than we > - normally look for. */ > - if (nesting_level == file_scope_level + 1) > - add_partial_symbol (&pdi, objfile, cu_header); > + case DW_TAG_enumeration_type: > + if (!pdi.is_declaration) > + { > + info_ptr = add_partial_enumeration (&pdi, info_ptr, > + objfile, cu_header, > + namespace); > + info_ptr_updated = 1; > + } > break; > case DW_TAG_base_type: > /* File scope base type definitions are added to the partial > symbol table. */ > - if (nesting_level == file_scope_level) > - add_partial_symbol (&pdi, objfile, cu_header); > + add_partial_symbol (&pdi, objfile, cu_header, namespace); > break; > case DW_TAG_namespace: > - /* FIXME: carlton/2002-10-16: we're not yet doing > - anything useful with this, but for now make sure that > - these tags at least don't cause us to miss any > - important symbols. */ > - if (pdi.has_children) > - file_scope_level++; > + /* We've hit a DW_TAG_namespace entry, so we know this > + file has been compiled using a compiler that > + generates them; update NAMESPACE to reflect that. */ > + if (namespace == NULL) > + namespace = ""; > + info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, > + lowpc, highpc, cu_header, > + namespace); > + info_ptr_updated = 1; > + break; > default: > break; > } > } > > - /* If the die has a sibling, skip to the sibling. Do not skip > - enumeration types, we want to record their enumerators. Do > - not skip namespaces, we want to record symbols inside > - them. */ > - if (pdi.sibling > - && pdi.tag != DW_TAG_enumeration_type > - && pdi.tag != DW_TAG_namespace) > - { > - info_ptr = pdi.sibling; > - } > - else if (pdi.has_children) > - { > - /* Die has children, but either the optional DW_AT_sibling > - attribute is missing or we want to look at them. */ > - nesting_level++; > - } > - > if (pdi.tag == 0) > - { > - nesting_level--; > - /* If this is the end of a DW_TAG_namespace entry, then > - decrease the file_scope_level, too. */ > - if (nesting_level < file_scope_level) > - { > - file_scope_level--; > - gdb_assert (nesting_level == file_scope_level); > - } > - } > + break; > + > + /* If the die has a sibling, skip to the sibling, unless another > + function has already updated info_ptr for us. */ > + > + /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether > + or not we want to update this depends on enough stuff (not > + only pdi.tag but also whether or not pdi.name is NULL) that > + this seems like the easiest way to handle the issue. */ > + > + if (!info_ptr_updated) > + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); > } > > - /* If we didn't find a lowpc, set it to highpc to avoid complaints > - from `maint check'. */ > - if (*lowpc == ((CORE_ADDR) -1)) > - *lowpc = *highpc; > return info_ptr; > } Ok, but, could you check in the algorithm change (the nested_level stuff) for scan_partial_symbols w/o any namespace changes? So that we can do a cvs -D if something goes wrong? I have decided that it is best to have a change per 24hours period to a file, after spending a couple of days tracking down some other breakage in symfiles, a few weeks back. Then the rest of the changes. > > static void > add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, > - const struct comp_unit_head *cu_header) > + const struct comp_unit_head *cu_header, > + const char *namespace) > { > CORE_ADDR addr = 0; > + const struct partial_symbol *psym = NULL; > > switch (pdi->tag) > { > @@ -1506,19 +1513,21 @@ add_partial_symbol (struct partial_die_i > { > /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, > mst_text, objfile); */ > - add_psymbol_to_list (pdi->name, strlen (pdi->name), > - VAR_DOMAIN, LOC_BLOCK, > - &objfile->global_psymbols, > - 0, pdi->lowpc + baseaddr, cu_language, objfile); > + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), > + VAR_DOMAIN, LOC_BLOCK, > + &objfile->global_psymbols, > + 0, pdi->lowpc + baseaddr, > + cu_language, objfile); > } > else > { > /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, > mst_file_text, objfile); */ > - add_psymbol_to_list (pdi->name, strlen (pdi->name), > - VAR_DOMAIN, LOC_BLOCK, > - &objfile->static_psymbols, > - 0, pdi->lowpc + baseaddr, cu_language, objfile); > + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), > + VAR_DOMAIN, LOC_BLOCK, > + &objfile->static_psymbols, > + 0, pdi->lowpc + baseaddr, > + cu_language, objfile); > } > break; > case DW_TAG_variable: > @@ -1540,10 +1549,11 @@ add_partial_symbol (struct partial_die_i > if (pdi->locdesc) > addr = decode_locdesc (pdi->locdesc, objfile, cu_header); > if (pdi->locdesc || pdi->has_type) > - add_psymbol_to_list (pdi->name, strlen (pdi->name), > - VAR_DOMAIN, LOC_STATIC, > - &objfile->global_psymbols, > - 0, addr + baseaddr, cu_language, objfile); > + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), > + VAR_DOMAIN, LOC_STATIC, > + &objfile->global_psymbols, > + 0, addr + baseaddr, > + cu_language, objfile); > } > else > { > @@ -1553,10 +1563,11 @@ add_partial_symbol (struct partial_die_i > addr = decode_locdesc (pdi->locdesc, objfile, cu_header); > /*prim_record_minimal_symbol (pdi->name, addr + baseaddr, > mst_file_data, objfile); */ > - add_psymbol_to_list (pdi->name, strlen (pdi->name), > - VAR_DOMAIN, LOC_STATIC, > - &objfile->static_psymbols, > - 0, addr + baseaddr, cu_language, objfile); > + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), > + VAR_DOMAIN, LOC_STATIC, > + &objfile->static_psymbols, > + 0, addr + baseaddr, > + cu_language, objfile); > } > break; > case DW_TAG_typedef: > @@ -1597,6 +1608,124 @@ add_partial_symbol (struct partial_die_i > default: > break; > } > + > + /* Check to see if we should scan the name for possible namespace > + info. Only do this if this is C++, if we don't have namespace > + debugging info in the file, if the psym is of an appropriate type > + (otherwise we'll have psym == NULL), and if we actually had a > + mangled name to begin with. */ > + > + if (cu_language == language_cplus > + && namespace == NULL > + && psym != NULL > + && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) > + cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym), > + objfile); > +} > + I don't like this too much. I.e. changing add_psymbol_to_list to return a value so you can get a hold of the psym. After all, add_psymbol_to_list doesn't change any of the fields of the psymbol, and cp_check_possible_namespace_symbols uses 2 fields that you already have around. Would it be possible to do w/o using psym at all? You might have to set a local variable to the function. > +/* Read a partial die corresponding to a namespace; also, add a symbol > + corresponding to that namespace to the symbol table. NAMESPACE is > + the name of the enclosing namespace. */ > + > +static char * > +add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, > + struct objfile *objfile, > + CORE_ADDR *lowpc, CORE_ADDR *highpc, > + const struct comp_unit_head *cu_header, > + const char *namespace) > +{ > + /* Calculate the full name of the namespace that we just entered. */ > + > + const char *new_name = pdi->name; > + char *full_name; > + > + if (new_name == NULL) > + new_name = "(anonymous namespace)"; > + full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1); > + strcpy (full_name, namespace); > + if (*namespace != '\0') > + strcat (full_name, "::"); > + strcat (full_name, new_name); > + > + /* FIXME: carlton/2003-06-27: Once we build qualified names for more > + symbols than just namespaces, we should replace this by a call to > + add_partial_symbol. */ > + > + add_psymbol_to_list (full_name, strlen (full_name), > + VAR_DOMAIN, LOC_TYPEDEF, > + &objfile->global_psymbols, > + 0, 0, cu_language, objfile); > + > + /* Now scan partial symbols in that namespace. */ > + > + if (pdi->has_children) > + info_ptr = scan_partial_symbols (info_ptr, objfile, > + lowpc, highpc, > + cu_header, full_name); > + > + return info_ptr; > +} > + > +/* Read a partial die corresponding to an enumeration type. */ > + > +static char * > +add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, > + struct objfile *objfile, > + const struct comp_unit_head *cu_header, > + const char *namespace) > +{ > + bfd *abfd = objfile->obfd; > + struct partial_die_info pdi; > + > + if (enum_pdi->name != NULL) > + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); > + > + while (1) > + { > + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); > + if (pdi.tag == 0) > + break; > + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) > + complaint (&symfile_complaints, "malformed enumerator DIE ignored"); > + else > + add_partial_symbol (&pdi, objfile, cu_header, namespace); > + } > + > + return info_ptr; > +} > + Any enumeration related tests that fail before and pass after this change? > +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE > + after ORIG_PDI. */ > + > +static char * > +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, > + bfd *abfd, const struct comp_unit_head *cu_header) > +{ > + /* Do we know the sibling already? */ > + > + if (orig_pdi->sibling) > + return orig_pdi->sibling; > + > + /* Are there any children to deal with? */ > + > + if (!orig_pdi->has_children) > + return info_ptr; > + > + /* Okay, we don't know the sibling, but we have children that we > + want to skip. So read children until we run into one without a > + tag; return whatever follows it. */ > + > + while (1) > + { > + struct partial_die_info pdi; > + > + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); > + > + if (pdi.tag == 0) > + return info_ptr; > + else > + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); > + } > } > > /* Expand this partial symbol table into a full symbol table. */ > @@ -3260,6 +3389,23 @@ read_namespace (struct die_info *die, st > strlen (previous_namespace), > strlen (processing_current_namespace)); > > + /* Add a symbol associated to this if we haven't seen the namespace > + before. */ > + > + if (dwarf2_extension (die) == NULL) Could you use this function in the check before this, in read_namespace (not in this patch, but already in the file)? > + { > + struct type *type; > + > + /* FIXME: carlton/2003-06-27: Once GDB is more const-correct, > + this cast will hopefully become unnecessary. */ > + type = init_type (TYPE_CODE_NAMESPACE, 0, 0, > + (char *) processing_current_namespace, > + objfile); > + TYPE_TAG_NAME (type) = TYPE_NAME (type); > + > + new_symbol (die, type, objfile, cu_header); > + } > + > if (die->has_children) > { > struct die_info *child_die = die->next; > @@ -5113,7 +5259,11 @@ new_symbol (struct die_info *die, struct > struct attribute *attr2 = NULL; > CORE_ADDR addr = 0; > > - name = dwarf2_linkage_name (die); > + if (die->tag != DW_TAG_namespace) > + name = dwarf2_linkage_name (die); > + else > + name = TYPE_NAME (type); > + > if (name) > { > sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack, > @@ -5291,6 +5441,10 @@ new_symbol (struct die_info *die, struct > dwarf2_const_value (attr, sym, objfile, cu_header); > } > add_symbol_to_list (sym, list_in_scope); > + break; > + case DW_TAG_namespace: > + SYMBOL_CLASS (sym) = LOC_TYPEDEF; > + add_symbol_to_list (sym, &global_symbols); > break; > default: > /* Not a tag we recognize. Hopefully we aren't processing > Index: gdbtypes.c > =================================================================== > RCS file: /cvs/src/src/gdb/gdbtypes.c,v > retrieving revision 1.74 > diff -u -p -r1.74 gdbtypes.c > --- gdbtypes.c 23 Jun 2003 21:05:40 -0000 1.74 > +++ gdbtypes.c 27 Jun 2003 21:38:38 -0000 > @@ -1897,7 +1897,8 @@ init_type (enum type_code code, int leng > if (name && strcmp (name, "char") == 0) > TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; > > - if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) > + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION > + || code == TYPE_CODE_NAMESPACE) > { > INIT_CPLUS_SPECIFIC (type); > } > @@ -3144,6 +3145,9 @@ recursive_dump_type (struct type *type, > break; > case TYPE_CODE_TEMPLATE_ARG: > printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)"); > + break; > + case TYPE_CODE_NAMESPACE: > + printf_filtered ("(TYPE_CODE_NAMESPACE)"); > break; > default: > printf_filtered ("(UNKNOWN TYPE CODE)"); > Index: gdbtypes.h > =================================================================== > RCS file: /cvs/src/src/gdb/gdbtypes.h,v > retrieving revision 1.48 > diff -u -p -r1.48 gdbtypes.h > --- gdbtypes.h 23 Jun 2003 21:05:40 -0000 1.48 > +++ gdbtypes.h 27 Jun 2003 21:38:50 -0000 > @@ -134,8 +134,9 @@ enum type_code > > TYPE_CODE_TYPEDEF, > TYPE_CODE_TEMPLATE, /* C++ template */ > - TYPE_CODE_TEMPLATE_ARG /* C++ template arg */ > + TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */ > > + TYPE_CODE_NAMESPACE, /* C++ namespace. */ > }; > > /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an > Index: jv-lang.c > =================================================================== > RCS file: /cvs/src/src/gdb/jv-lang.c,v > retrieving revision 1.21 > diff -u -p -r1.21 jv-lang.c > --- jv-lang.c 11 Jun 2003 23:29:47 -0000 1.21 > +++ jv-lang.c 27 Jun 2003 21:38:55 -0000 > @@ -111,22 +111,13 @@ get_java_class_symtab (void) > BLOCKVECTOR (class_symtab) = bv; > > /* Allocate dummy STATIC_BLOCK. */ > - bl = (struct block *) > - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); > + bl = allocate_block (&objfile->symbol_obstack); > BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, > NULL); > - BLOCK_START (bl) = 0; > - BLOCK_END (bl) = 0; > - BLOCK_FUNCTION (bl) = NULL; > - BLOCK_SUPERBLOCK (bl) = NULL; > - BLOCK_NAMESPACE (bl) = NULL; > - BLOCK_GCC_COMPILED (bl) = 0; > BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; > > - /* Allocate GLOBAL_BLOCK. This has to be relocatable. */ > - bl = (struct block *) > - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); > - *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); > + /* Allocate GLOBAL_BLOCK. */ > + bl = allocate_block (&objfile->symbol_obstack); > BLOCK_DICT (bl) = dict_create_hashed_expandable (); > BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; > class_symtab->free_func = free_class_block; I think it would make sense, in a next pass, to have all the creation of blocks go through the new function. > Index: objfiles.c > =================================================================== > RCS file: /cvs/src/src/gdb/objfiles.c,v > retrieving revision 1.33 > diff -u -p -r1.33 objfiles.c > --- objfiles.c 11 Jun 2003 23:29:47 -0000 1.33 > +++ objfiles.c 27 Jun 2003 21:38:55 -0000 > @@ -332,10 +332,14 @@ allocate_objfile (bfd *abfd, int flags) > /* Initialize the section indexes for this objfile, so that we can > later detect if they are used w/o being properly assigned to. */ > > - objfile->sect_index_text = -1; > - objfile->sect_index_data = -1; > - objfile->sect_index_bss = -1; > - objfile->sect_index_rodata = -1; > + objfile->sect_index_text = -1; > + objfile->sect_index_data = -1; > + objfile->sect_index_bss = -1; > + objfile->sect_index_rodata = -1; > + > + /* We don't yet have a C++-specific namespace symtab. */ > + > + objfile->cp_namespace_symtab = NULL; > > /* Add this file onto the tail of the linked list of other such files. */ > > Index: objfiles.h > =================================================================== > RCS file: /cvs/src/src/gdb/objfiles.h,v > retrieving revision 1.22 > diff -u -p -r1.22 objfiles.h > --- objfiles.h 24 Mar 2003 03:54:48 -0000 1.22 > +++ objfiles.h 27 Jun 2003 21:39:07 -0000 > @@ -28,6 +28,7 @@ > > struct bcache; > struct htab; > +struct symtab; > > /* This structure maintains information on a per-objfile basis about the > "entry point" of the objfile, and the scope within which the entry point > @@ -436,6 +437,13 @@ struct objfile > > /* Place to stash various statistics about this objfile */ > OBJSTATS; > + > + /* A symtab that the C++ code uses to stash special symbols > + associated to namespaces. */ > + > + /* FIXME/carlton-2003-06-27: Delete this in a few years once > + "possible namespace symbols" go away. */ > + struct symtab *cp_namespace_symtab; > }; > > /* Defines for the objfile flag word. */ > Index: printcmd.c > =================================================================== > RCS file: /cvs/src/src/gdb/printcmd.c,v > retrieving revision 1.63 > diff -u -p -r1.63 printcmd.c > --- printcmd.c 9 Jun 2003 15:20:21 -0000 1.63 > +++ printcmd.c 27 Jun 2003 21:39:09 -0000 > @@ -315,7 +315,8 @@ print_formatted (struct value *val, regi > || TYPE_CODE (type) == TYPE_CODE_ARRAY > || TYPE_CODE (type) == TYPE_CODE_STRING > || TYPE_CODE (type) == TYPE_CODE_STRUCT > - || TYPE_CODE (type) == TYPE_CODE_UNION) > + || TYPE_CODE (type) == TYPE_CODE_UNION > + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) > /* If format is 0, use the 'natural' format for > * that type of value. If the type is non-scalar, > * we have to use language rules to print it as > Index: symfile.c > =================================================================== > RCS file: /cvs/src/src/gdb/symfile.c,v > retrieving revision 1.101 > diff -u -p -r1.101 symfile.c > --- symfile.c 27 Jun 2003 13:11:17 -0000 1.101 > +++ symfile.c 27 Jun 2003 21:39:23 -0000 > @@ -2631,9 +2631,10 @@ start_psymtab_common (struct objfile *ob > } > \f > /* Add a symbol with a long value to a psymtab. > - Since one arg is a struct, we pass in a ptr and deref it (sigh). */ > + Since one arg is a struct, we pass in a ptr and deref it (sigh). > + Return the partial symbol that has been added. */ > > -void > +const struct partial_symbol * > add_psymbol_to_list (char *name, int namelength, domain_enum domain, > enum address_class class, > struct psymbol_allocation_list *list, long val, /* Value as a long */ > @@ -2676,6 +2677,8 @@ add_psymbol_to_list (char *name, int nam > } > *list->next++ = psym; > OBJSTAT (objfile, n_psyms++); > + > + return psym; > } > > /* Add a symbol with a long value to a psymtab. This differs from See the comments about the dwarf2read.c changes, to see if we can avoid doing this. > Index: symfile.h > =================================================================== > RCS file: /cvs/src/src/gdb/symfile.h,v > retrieving revision 1.24 > diff -u -p -r1.24 symfile.h > --- symfile.h 11 Jun 2003 22:27:13 -0000 1.24 > +++ symfile.h 27 Jun 2003 21:39:26 -0000 > @@ -152,9 +152,12 @@ extern void extend_psymbol_list (struct > > /* #include "demangle.h" */ > > -extern void add_psymbol_to_list (char *, int, domain_enum, enum address_class, > - struct psymbol_allocation_list *, long, > - CORE_ADDR, enum language, struct objfile *); > +extern const > +struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum, > + enum address_class, > + struct psymbol_allocation_list *, > + long, CORE_ADDR, > + enum language, struct objfile *); > > extern void add_psymbol_with_dem_name_to_list (char *, int, char *, int, > domain_enum, Ditto. > Index: typeprint.c > =================================================================== > RCS file: /cvs/src/src/gdb/typeprint.c,v > retrieving revision 1.18 > diff -u -p -r1.18 typeprint.c > --- typeprint.c 8 Jun 2003 18:27:14 -0000 1.18 > +++ typeprint.c 27 Jun 2003 21:39:28 -0000 > @@ -307,6 +307,7 @@ print_type_scalar (struct type *type, LO > case TYPE_CODE_MEMBER: > case TYPE_CODE_METHOD: > case TYPE_CODE_REF: > + case TYPE_CODE_NAMESPACE: > error ("internal error: unhandled type in print_type_scalar"); > break; > > Index: testsuite/gdb.c++/maint.exp > =================================================================== > RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/maint.exp,v > retrieving revision 1.2 > diff -u -p -r1.2 maint.exp > --- testsuite/gdb.c++/maint.exp 23 Apr 2003 23:45:24 -0000 1.2 > +++ testsuite/gdb.c++/maint.exp 27 Jun 2003 21:39:29 -0000 > @@ -29,13 +29,19 @@ if $tracelevel then { > # Test the help messages. > > proc test_help {} { > - gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." > + set first_component_help "Print the first class/namespace component of NAME" > + set namespace_help "Print the list of possible C\\+\\+ namespaces" > > - gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." > + set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." > > - gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." > + set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}" > > - gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME." > + gdb_test "help maintenance cplus" "${help_maint_cp}" > + gdb_test "help maint cp" "${help_maint_cp}" > + gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}" > + > + gdb_test "help maint cp first_component" "${first_component_help}." > + gdb_test "help maint cp namespace" "${namespace_help}." > } > > # This is used when NAME should contain only a single component. Be > @@ -79,6 +85,12 @@ proc test_first_component {} { > gdb_test "maint cp first_component foo::bar::baz" "foo" > gdb_test "maint cp first_component C<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's not a lot we can do to test this. > + > + gdb_test "maint cp namespace" "Possible namespaces:" > } > > gdb_exit > Index: testsuite/gdb.c++/namespace.exp > =================================================================== > RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.exp,v > retrieving revision 1.13 > diff -u -p -r1.13 namespace.exp > --- testsuite/gdb.c++/namespace.exp 20 May 2003 03:56:29 -0000 1.13 > +++ testsuite/gdb.c++/namespace.exp 27 Jun 2003 21:39:29 -0000 > @@ -208,6 +208,8 @@ gdb_test "print cd" "\\$\[0-9\].* = 3" > gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5" > gdb_test "print shadow" "\\$\[0-9\].* = 13" > gdb_test "print cOtherFile" "\\$\[0-9\].* = 316" > +gdb_test "ptype C" "type = namespace C::C" > +gdb_test "ptype E" "type = namespace C::D::E" > > # Some anonymous namespace tests. > ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-09-09 19:42 ` Elena Zannoni @ 2003-09-09 20:28 ` David Carlton 2003-09-09 22:17 ` Elena Zannoni 2003-09-11 23:28 ` [rfa] use allocate_block more David Carlton 1 sibling, 1 reply; 23+ messages in thread From: David Carlton @ 2003-09-09 20:28 UTC (permalink / raw) To: Elena Zannoni; +Cc: gdb-patches On Tue, 9 Sep 2003 15:51:37 -0400, Elena Zannoni <ezannoni@redhat.com> said: > David Carlton writes: > Ok, but, could you check in the algorithm change (the nested_level > stuff) for scan_partial_symbols w/o any namespace changes? So that > we can do a cvs -D if something goes wrong? I have decided that it > is best to have a change per 24hours period to a file, after > spending a couple of days tracking down some other breakage in > symfiles, a few weeks back. Then the rest of the changes. That should be fine. >> + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), >> + VAR_DOMAIN, LOC_STATIC, >> + &objfile->static_psymbols, >> + 0, addr + baseaddr, >> + cu_language, objfile); > I don't like this too much. I.e. changing add_psymbol_to_list to > return a value so you can get a hold of the psym. After all, > add_psymbol_to_list doesn't change any of the fields of the psymbol, > and cp_check_possible_namespace_symbols uses 2 fields that you > already have around. No, add_psymbol_to_list does change the fields: it calls SYMBOL_SET_NAMES to set the demangled name, which I need in cp_check_possible_namespace_symbols. So having add_psymbol_to_list return the psymbol seems the best solution; I suppose I could break out the demangled-name-caching code that SYMBOL_SET_NAMES uses into a separate function, but it doesn't seem worth it here. >> +static char * >> +add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, >> + struct objfile *objfile, >> + const struct comp_unit_head *cu_header, >> + const char *namespace) >> +{ >> + bfd *abfd = objfile->obfd; >> + struct partial_die_info pdi; >> + >> + if (enum_pdi->name != NULL) >> + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); >> + >> + while (1) >> + { >> + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); >> + if (pdi.tag == 0) >> + break; >> + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) >> + complaint (&symfile_complaints, "malformed enumerator DIE ignored"); >> + else >> + add_partial_symbol (&pdi, objfile, cu_header, namespace); >> + } >> + >> + return info_ptr; >> +} >> + > Any enumeration related tests that fail before and pass after this > change? Nope. I don't think it should change GDB's behavior on well-formed debug info. >> + /* Add a symbol associated to this if we haven't seen the namespace >> + before. */ >> + >> + if (dwarf2_extension (die) == NULL) > Could you use this function in the check before this, in > read_namespace (not in this patch, but already in the file)? I think so; I don't see why the using directive bit couldn't be moved into this block. > I think it would make sense, in a next pass, to have all the creation > of blocks go through the new function. That would be my instinct as well. I can't remember why I didn't do that in this patch, but I don't think I had a good reason for why it wouldn't work. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-09-09 20:28 ` David Carlton @ 2003-09-09 22:17 ` Elena Zannoni 2003-09-09 23:25 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: Elena Zannoni @ 2003-09-09 22:17 UTC (permalink / raw) To: David Carlton; +Cc: Elena Zannoni, gdb-patches David Carlton writes: > On Tue, 9 Sep 2003 15:51:37 -0400, Elena Zannoni <ezannoni@redhat.com> said: > > David Carlton writes: > > >> + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), > >> + VAR_DOMAIN, LOC_STATIC, > >> + &objfile->static_psymbols, > >> + 0, addr + baseaddr, > >> + cu_language, objfile); > > > I don't like this too much. I.e. changing add_psymbol_to_list to > > return a value so you can get a hold of the psym. After all, > > add_psymbol_to_list doesn't change any of the fields of the psymbol, > > and cp_check_possible_namespace_symbols uses 2 fields that you > > already have around. > > No, add_psymbol_to_list does change the fields: it calls > SYMBOL_SET_NAMES to set the demangled name, which I need in > cp_check_possible_namespace_symbols. So having add_psymbol_to_list > return the psymbol seems the best solution; I suppose I could break > out the demangled-name-caching code that SYMBOL_SET_NAMES uses into a > separate function, but it doesn't seem worth it here. > Oh, right. I really don't like it. Only these few callers of add_psymbol_to_list use its return value. But you are right, that function does quite a bit. Sigh. I don't see any alternative, then. Ok on the rest. elena ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-09-09 22:17 ` Elena Zannoni @ 2003-09-09 23:25 ` David Carlton 2003-09-11 19:52 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: David Carlton @ 2003-09-09 23:25 UTC (permalink / raw) To: Elena Zannoni; +Cc: gdb-patches On Tue, 9 Sep 2003 17:44:59 -0400, Elena Zannoni <ezannoni@redhat.com> said: > Oh, right. I really don't like it. Only these few callers of > add_psymbol_to_list use its return value. But you are right, that > function does quite a bit. Sigh. I don't see any alternative, then. Yeah, me neither. I'll add a comment about who is using the return value, though. > Ok on the rest. Great. Then I've just committed the following, which is the scan_partial_symbols reorganization. I'll commit the rest no earlier than tomorrow afternoon (but quite possibly later, depending on when I have time to tweak it in response to yours and Daniel's request). David Carlton carlton@kealia.com 2003-09-09 David Carlton <carlton@kealia.com> * dwarf2read.c (dwarf2_build_psymtabs_hard): Move lowpc and highpc initialization here out of scan_partial_symbols. (scan_partial_symbols): Restructure into a recursive version, calling add_partial_namespace and add_partial_enumeration when appropriate. (add_partial_namespace): New. (add_partial_enumeration, locate_pdi_sibling): Ditto. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.100 diff -u -p -r1.100 dwarf2read.c --- dwarf2read.c 26 Aug 2003 05:28:38 -0000 1.100 +++ dwarf2read.c 9 Sep 2003 23:20:08 -0000 @@ -677,6 +677,22 @@ static char *scan_partial_symbols (char static void add_partial_symbol (struct partial_die_info *, struct objfile *, const struct comp_unit_head *); +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); + +static char *add_partial_enumeration (struct partial_die_info *enum_pdi, + char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header); + +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 *); static void psymtab_to_symtab_1 (struct partial_symtab *); @@ -1321,9 +1337,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); + /* 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) @@ -1352,7 +1376,8 @@ 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. */ static char * scan_partial_symbols (char *info_ptr, struct objfile *objfile, @@ -1362,35 +1387,24 @@ scan_partial_symbols (char *info_ptr, st 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 (1) + { + /* This flag tells whether or not info_ptr has gotten updated + inside the loop. */ + int info_ptr_updated = 0; - while (nesting_level) - { 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) { @@ -1405,8 +1419,7 @@ 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); } @@ -1414,76 +1427,52 @@ scan_partial_symbols (char *info_ptr, st 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); } 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); + 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); 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++; + info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, + lowpc, highpc, cu_header); + 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; } @@ -1590,6 +1579,85 @@ add_partial_symbol (struct partial_die_i break; default: break; + } +} + +/* 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. */ + +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) +{ + if (pdi->has_children) + info_ptr = scan_partial_symbols (info_ptr, objfile, + lowpc, highpc, + cu_header); + + 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) +{ + bfd *abfd = objfile->obfd; + struct partial_die_info pdi; + + if (enum_pdi->name != NULL) + add_partial_symbol (enum_pdi, objfile, cu_header); + + while (1) + { + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + if (pdi.tag == 0) + break; + if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL) + complaint (&symfile_complaints, "malformed enumerator DIE ignored"); + else + add_partial_symbol (&pdi, objfile, cu_header); + } + + return info_ptr; +} + +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE + after ORIG_PDI. */ + +static char * +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, + bfd *abfd, const struct comp_unit_head *cu_header) +{ + /* Do we know the sibling already? */ + + if (orig_pdi->sibling) + return orig_pdi->sibling; + + /* Are there any children to deal with? */ + + if (!orig_pdi->has_children) + return info_ptr; + + /* Okay, we don't know the sibling, but we have children that we + want to skip. So read children until we run into one without a + tag; return whatever follows it. */ + + while (1) + { + struct partial_die_info pdi; + + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + + if (pdi.tag == 0) + return info_ptr; + else + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); } } ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-09-09 23:25 ` David Carlton @ 2003-09-11 19:52 ` David Carlton 2003-09-17 20:41 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: David Carlton @ 2003-09-11 19:52 UTC (permalink / raw) To: Elena Zannoni; +Cc: gdb-patches On Tue, 09 Sep 2003 16:25:41 -0700, David Carlton <carlton@kealia.com> said: > I'll commit the rest no earlier than tomorrow afternoon (but quite > possibly later, depending on when I have time to tweak it in > response to yours and Daniel's request). I've just committed the rest. Patch below; the only differences from what I posted before are minor tweaks based on your and Daniel's requests. David Carlton carlton@kealia.com 2003-09-11 David Carlton <carlton@kealia.com> * gdbtypes.h: Add TYPE_CODE_NAMESPACE. * gdbtypes.c (init_type): Handle TYPE_CODE_NAMESPACE. (recursive_dump_type): Ditto. * printcmd.c (print_formatted): Ditto. * typeprint.c (print_type_scalar): Ditto. * c-typeprint.c (c_type_print_varspec_prefix): Ditto. (c_type_print_varspec_suffix, c_type_print_base): Ditto. * cp-support.h: Declare cp_check_possible_namespace_symbols, maint_cplus_cmd_list. * cp-support.c: Make maint_cplus_cmd_list extern. * cp-namespace.c: Include objfiles.h, gdbtypes.h, dictionary.h, command.h. (lookup_symbol_file): Look in possible namespace blocks when appropriate. (initialize_namespace_symtab): New. (get_possible_namespace_block, free_namespace_block) (check_possible_namespace_symbols) (check_possible_namespace_symbols_loop) (check_one_possible_namespace_symbol) (lookup_possible_namespace_symbol, maintenance_cplus_namespace) (_initialize_cp_namespace): Ditto. * block.h: Declare allocate_block. * block.c (allocate_block): New. * jv-lang.c (get_java_class_symtab): Allocate blocks via allocate_block. * symfile.h: Update declaration of add_psymbol_to_list. * symfile.c (add_psymbol_to_list): Return the partial symbol in question. * dwarf2read.c (dwarf2_build_psymtabs_hard): Add argument to scan_partial_symbols_call. (scan_partial_symbols): Add NAMESPACE argument; update calls to helper functions. (add_partial_symbol): If necessary, scan mangled names for names of namespaces. (add_partial_namespace): Add NAMESPACE argument; generate partial symbols associated to namespaces. (add_partial_enumeration): Add NAMESPACE argument. (new_symbol): Allow namespace syms. (read_namespace): Generate namespace syms. * objfiles.h: Add opaque declaration of struct symtab. (struct objfile): Add cp_namespace_symtab member. * objfiles.c (allocate_objfile): Set objfile->cp_namespace_symtab. * Makefile.in (cp-namespace.o): Depend on objfiles_h, gdbtypes_h, dictionary_h, command_h. 2003-09-11 David Carlton <carlton@kealia.com> * gdb.c++/namespace.exp: Add tests for namespace types. * gdb.c++/maint.exp (test_help): Test 'help maint cp namespace'. (test_namespace): New. Index: Makefile.in =================================================================== RCS file: /cvs/src/src/gdb/Makefile.in,v retrieving revision 1.442 diff -u -p -r1.442 Makefile.in --- Makefile.in 11 Sep 2003 02:00:50 -0000 1.442 +++ Makefile.in 11 Sep 2003 19:37:45 -0000 @@ -1657,7 +1657,8 @@ core-sol2.o: core-sol2.c $(defs_h) $(gdb 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: 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 11 Sep 2003 19:37:45 -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 11 Sep 2003 19:37:45 -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 11 Sep 2003 19:37:45 -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 11 Sep 2003 19:37:45 -0000 @@ -27,6 +27,10 @@ #include "symfile.h" #include "gdb_assert.h" #include "block.h" +#include "objfiles.h" +#include "gdbtypes.h" +#include "dictionary.h" +#include "command.h" /* When set, the file that we're processing seems to have debugging info for C++ namespaces, so cp-namespace.c shouldn't try to guess @@ -70,6 +74,26 @@ static struct symbol *lookup_symbol_file struct symtab **symtab, int anonymous_namespace); +static void initialize_namespace_symtab (struct objfile *objfile); + +static struct block *get_possible_namespace_block (struct objfile *objfile); + +static void free_namespace_block (struct symtab *symtab); + +static int check_possible_namespace_symbols_loop (const char *name, + int len, + struct objfile *objfile); + +static int check_one_possible_namespace_symbol (const char *name, + int len, + struct objfile *objfile); + +static +struct symbol *lookup_possible_namespace_symbol (const char *name, + struct symtab **symtab); + +static void maintenance_cplus_namespace (char *args, int from_tty); + /* Set up support for dealing with C++ namespace info in the current symtab. */ @@ -453,13 +477,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: cp-support.c =================================================================== RCS file: /cvs/src/src/gdb/cp-support.c,v retrieving revision 1.7 diff -u -p -r1.7 cp-support.c --- cp-support.c 30 Jun 2003 16:23:29 -0000 1.7 +++ cp-support.c 11 Sep 2003 19:37:45 -0000 @@ -55,7 +55,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 11 Sep 2003 19:37:45 -0000 @@ -96,4 +96,11 @@ extern struct symbol *cp_lookup_symbol_n const domain_enum domain, struct symtab **symtab); +extern void cp_check_possible_namespace_symbols (const char *name, + struct objfile *objfile); + +/* The list of "maint cplus" commands. */ + +extern struct cmd_list_element *maint_cplus_cmd_list; + #endif /* CP_SUPPORT_H */ Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.101 diff -u -p -r1.101 dwarf2read.c --- dwarf2read.c 9 Sep 2003 23:23:05 -0000 1.101 +++ dwarf2read.c 11 Sep 2003 19:37:45 -0000 @@ -672,21 +672,25 @@ 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 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 objfi 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 objfi } /* 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, st } 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, st 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, st 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_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: @@ -1523,10 +1543,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 { @@ -1536,10 +1557,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: @@ -1580,22 +1602,60 @@ add_partial_symbol (struct partial_die_i default: break; } -} -/* 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. */ + /* 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; 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_di 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_ 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, st 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 (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 && dwarf_attr (die, DW_AT_extension) == NULL) - cp_add_using_directive (processing_current_namespace, - strlen (previous_namespace), - strlen (processing_current_namespace)); + 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 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, @@ -5331,6 +5411,10 @@ new_symbol (struct die_info *die, struct dwarf2_const_value (attr, sym, objfile, cu_header); } add_symbol_to_list (sym, list_in_scope); + break; + case DW_TAG_namespace: + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + add_symbol_to_list (sym, &global_symbols); break; default: /* Not a tag we recognize. Hopefully we aren't processing Index: gdbtypes.c =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.c,v retrieving revision 1.74 diff -u -p -r1.74 gdbtypes.c --- gdbtypes.c 23 Jun 2003 21:05:40 -0000 1.74 +++ gdbtypes.c 11 Sep 2003 19:37:46 -0000 @@ -1897,7 +1897,8 @@ init_type (enum type_code code, int leng if (name && strcmp (name, "char") == 0) TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; - if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION + || code == TYPE_CODE_NAMESPACE) { INIT_CPLUS_SPECIFIC (type); } @@ -3144,6 +3145,9 @@ recursive_dump_type (struct type *type, break; case TYPE_CODE_TEMPLATE_ARG: printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)"); + break; + case TYPE_CODE_NAMESPACE: + printf_filtered ("(TYPE_CODE_NAMESPACE)"); break; default: printf_filtered ("(UNKNOWN TYPE CODE)"); Index: gdbtypes.h =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.h,v retrieving revision 1.50 diff -u -p -r1.50 gdbtypes.h --- gdbtypes.h 22 Aug 2003 05:05:56 -0000 1.50 +++ gdbtypes.h 11 Sep 2003 19:37:46 -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.22 diff -u -p -r1.22 jv-lang.c --- jv-lang.c 9 Sep 2003 08:05:42 -0000 1.22 +++ jv-lang.c 11 Sep 2003 19:37:46 -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: objfiles.c =================================================================== RCS file: /cvs/src/src/gdb/objfiles.c,v retrieving revision 1.34 diff -u -p -r1.34 objfiles.c --- objfiles.c 21 Aug 2003 22:35:33 -0000 1.34 +++ objfiles.c 11 Sep 2003 19:37:47 -0000 @@ -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: objfiles.h =================================================================== RCS file: /cvs/src/src/gdb/objfiles.h,v retrieving revision 1.23 diff -u -p -r1.23 objfiles.h --- objfiles.h 21 Aug 2003 22:35:33 -0000 1.23 +++ objfiles.h 11 Sep 2003 19:37:47 -0000 @@ -28,6 +28,7 @@ struct bcache; struct htab; +struct symtab; /* This structure maintains information on a per-objfile basis about the "entry point" of the objfile, and the scope within which the entry point @@ -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: printcmd.c =================================================================== RCS file: /cvs/src/src/gdb/printcmd.c,v retrieving revision 1.65 diff -u -p -r1.65 printcmd.c --- printcmd.c 4 Aug 2003 17:08:22 -0000 1.65 +++ printcmd.c 11 Sep 2003 19:37:47 -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.104 diff -u -p -r1.104 symfile.c --- symfile.c 11 Sep 2003 19:20:07 -0000 1.104 +++ symfile.c 11 Sep 2003 19:37:48 -0000 @@ -2632,9 +2632,21 @@ start_psymtab_common (struct objfile *ob } \f /* Add a symbol with a long value to a psymtab. - Since one arg is a struct, we pass in a ptr and deref it (sigh). */ + Since one arg is a struct, we pass in a ptr and deref it (sigh). + Return the partial symbol that has been added. */ -void +/* 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 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 11 Sep 2003 19:37:48 -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 11 Sep 2003 19:37:48 -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.cp/maint.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/maint.exp,v retrieving revision 1.1 diff -u -p -r1.1 maint.exp --- testsuite/gdb.cp/maint.exp 23 Aug 2003 03:55:59 -0000 1.1 +++ testsuite/gdb.cp/maint.exp 11 Sep 2003 19:37:48 -0000 @@ -29,13 +29,19 @@ if $tracelevel then { # Test the help messages. proc test_help {} { - gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set first_component_help "Print the first class/namespace component of NAME" + set namespace_help "Print the list of possible C\\+\\+ namespaces" - gdb_test "help maint cp" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set multiple_help_body "List of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- ${first_component_help}\r\nmaintenance cplus namespace -- ${namespace_help}\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." - gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" followed by maintenance cplus subcommand name for full documentation.\r\nCommand name abbreviations are allowed if unambiguous." + set help_maint_cp "C\\+\\+ maintenance commands.\r\n\r\n${multiple_help_body}" - gdb_test "help maint cp first_component" "Print the first class/namespace component of NAME." + gdb_test "help maintenance cplus" "${help_maint_cp}" + gdb_test "help maint cp" "${help_maint_cp}" + gdb_test "maint cp" "\"maintenance cplus\" must be followed by the name of a command.\r\n${multiple_help_body}" + + gdb_test "help maint cp first_component" "${first_component_help}." + gdb_test "help maint cp namespace" "${namespace_help}." } # This is used when NAME should contain only a single component. Be @@ -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: testsuite/gdb.cp/namespace.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/namespace.exp,v retrieving revision 1.1 diff -u -p -r1.1 namespace.exp --- testsuite/gdb.cp/namespace.exp 23 Aug 2003 03:55:59 -0000 1.1 +++ testsuite/gdb.cp/namespace.exp 11 Sep 2003 19:37:49 -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. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] generate symbols associated to namespaces 2003-09-11 19:52 ` David Carlton @ 2003-09-17 20:41 ` David Carlton 0 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-09-17 20:41 UTC (permalink / raw) To: gdb-patches On Thu, 11 Sep 2003 12:52:23 -0700, David Carlton <carlton@kealia.com> said: > 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. These should refer to gdb.cp; I've modified the ChangeLog accordingly. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
* [rfa] use allocate_block more 2003-09-09 19:42 ` Elena Zannoni 2003-09-09 20:28 ` David Carlton @ 2003-09-11 23:28 ` David Carlton 2003-09-11 23:33 ` Elena Zannoni 1 sibling, 1 reply; 23+ messages in thread From: David Carlton @ 2003-09-11 23:28 UTC (permalink / raw) To: Elena Zannoni; +Cc: gdb-patches On Tue, 9 Sep 2003 15:51:37 -0400, Elena Zannoni <ezannoni@redhat.com> said: > I think it would make sense, in a next pass, to have all the creation > of blocks go through the new function. Well, I was planning to do that; here's what I came up with instead. The problem is that mdebugread.c currently doesn't allocate blocks on an obstack at all! That should presumably be fixed ("rm mdebugread.c" would be my preferred method), but I didn't feel like doing that right now; I'd rather leave it up to somebody with access to a machine using mdebugread. Tested on i686-pc-linux-gnu, GCC 3.2, DWARF 2; no new regressions. OK to commit? David Carlton carlton@kealia.com 2003-09-11 David Carlton <carlton@kealia.com> * buildsym.c (finish_block): Use allocate_block to allocate the block. * mdebugread.c (new_block): Add FIXME. Index: buildsym.c =================================================================== RCS file: /cvs/src/src/gdb/buildsym.c,v retrieving revision 1.33 diff -u -p -r1.33 buildsym.c --- buildsym.c 11 Jun 2003 23:29:46 -0000 1.33 +++ buildsym.c 11 Sep 2003 22:58:08 -0000 @@ -231,19 +231,15 @@ finish_block (struct symbol *symbol, str register struct pending_block *pblock; struct pending_block *opblock; - /* Initialize the block's dictionary. */ + block = allocate_block (&objfile->symbol_obstack); if (symbol) { - block = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); BLOCK_DICT (block) = dict_create_linear (&objfile->symbol_obstack, *listhead); } else { - block = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); BLOCK_DICT (block) = dict_create_hashed (&objfile->symbol_obstack, *listhead); } Index: mdebugread.c =================================================================== RCS file: /cvs/src/src/gdb/mdebugread.c,v retrieving revision 1.47 diff -u -p -r1.47 mdebugread.c --- mdebugread.c 11 Jun 2003 23:29:47 -0000 1.47 +++ mdebugread.c 11 Sep 2003 22:58:14 -0000 @@ -4696,6 +4696,9 @@ new_bvect (int nblocks) static struct block * new_block (enum block_type type) { + /* FIXME: carlton/2003-09-11: This should use allocate_block to + allocate the block. Which, in turn, suggests that the block + should be allocated on an obstack. */ struct block *retval = xzalloc (sizeof (struct block)); if (type == FUNCTION_BLOCK) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] use allocate_block more 2003-09-11 23:28 ` [rfa] use allocate_block more David Carlton @ 2003-09-11 23:33 ` Elena Zannoni 2003-09-11 23:44 ` David Carlton 0 siblings, 1 reply; 23+ messages in thread From: Elena Zannoni @ 2003-09-11 23:33 UTC (permalink / raw) To: David Carlton; +Cc: Elena Zannoni, gdb-patches David Carlton writes: > On Tue, 9 Sep 2003 15:51:37 -0400, Elena Zannoni <ezannoni@redhat.com> said: > > > I think it would make sense, in a next pass, to have all the creation > > of blocks go through the new function. > > Well, I was planning to do that; here's what I came up with instead. > The problem is that mdebugread.c currently doesn't allocate blocks on > an obstack at all! That should presumably be fixed ("rm mdebugread.c" > would be my preferred method), but I didn't feel like doing that > right now; I'd rather leave it up to somebody with access to a machine > using mdebugread. > > Tested on i686-pc-linux-gnu, GCC 3.2, DWARF 2; no new regressions. OK > to commit? Yep. elena > > David Carlton > carlton@kealia.com > > 2003-09-11 David Carlton <carlton@kealia.com> > > * buildsym.c (finish_block): Use allocate_block to allocate the > block. > * mdebugread.c (new_block): Add FIXME. > > Index: buildsym.c > =================================================================== > RCS file: /cvs/src/src/gdb/buildsym.c,v > retrieving revision 1.33 > diff -u -p -r1.33 buildsym.c > --- buildsym.c 11 Jun 2003 23:29:46 -0000 1.33 > +++ buildsym.c 11 Sep 2003 22:58:08 -0000 > @@ -231,19 +231,15 @@ finish_block (struct symbol *symbol, str > register struct pending_block *pblock; > struct pending_block *opblock; > > - /* Initialize the block's dictionary. */ > + block = allocate_block (&objfile->symbol_obstack); > > if (symbol) > { > - block = (struct block *) > - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); > BLOCK_DICT (block) = dict_create_linear (&objfile->symbol_obstack, > *listhead); > } > else > { > - block = (struct block *) > - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); > BLOCK_DICT (block) = dict_create_hashed (&objfile->symbol_obstack, > *listhead); > } > Index: mdebugread.c > =================================================================== > RCS file: /cvs/src/src/gdb/mdebugread.c,v > retrieving revision 1.47 > diff -u -p -r1.47 mdebugread.c > --- mdebugread.c 11 Jun 2003 23:29:47 -0000 1.47 > +++ mdebugread.c 11 Sep 2003 22:58:14 -0000 > @@ -4696,6 +4696,9 @@ new_bvect (int nblocks) > static struct block * > new_block (enum block_type type) > { > + /* FIXME: carlton/2003-09-11: This should use allocate_block to > + allocate the block. Which, in turn, suggests that the block > + should be allocated on an obstack. */ > struct block *retval = xzalloc (sizeof (struct block)); > > if (type == FUNCTION_BLOCK) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [rfa] use allocate_block more 2003-09-11 23:33 ` Elena Zannoni @ 2003-09-11 23:44 ` David Carlton 0 siblings, 0 replies; 23+ messages in thread From: David Carlton @ 2003-09-11 23:44 UTC (permalink / raw) To: Elena Zannoni; +Cc: gdb-patches On Thu, 11 Sep 2003 19:42:29 -0400, Elena Zannoni <ezannoni@redhat.com> said: > David Carlton writes: >> Tested on i686-pc-linux-gnu, GCC 3.2, DWARF 2; no new regressions. OK >> to commit? > Yep. Thanks, committed. David Carlton carlton@kealia.com ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2003-09-17 20:41 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2003-06-16 20:22 [rfa] generate symbols associated to namespaces David Carlton 2003-06-22 17:42 ` Daniel Jacobowitz 2003-06-24 19:00 ` David Carlton 2003-06-24 19:02 ` Daniel Jacobowitz 2003-06-27 16:04 ` David Carlton 2003-06-27 21:58 ` David Carlton 2003-06-27 22:32 ` David Carlton 2003-08-05 16:30 ` David Carlton 2003-08-05 17:54 ` Daniel Jacobowitz 2003-08-05 18:06 ` David Carlton 2003-08-05 18:08 ` Daniel Jacobowitz 2003-08-05 18:18 ` David Carlton 2003-08-31 19:29 ` Daniel Jacobowitz 2003-09-02 16:38 ` David Carlton 2003-09-09 19:42 ` Elena Zannoni 2003-09-09 20:28 ` David Carlton 2003-09-09 22:17 ` Elena Zannoni 2003-09-09 23:25 ` David Carlton 2003-09-11 19:52 ` David Carlton 2003-09-17 20:41 ` David Carlton 2003-09-11 23:28 ` [rfa] use allocate_block more David Carlton 2003-09-11 23:33 ` Elena Zannoni 2003-09-11 23:44 ` David Carlton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox