From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2834 invoked by alias); 16 Jun 2003 20:22:24 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 2547 invoked from network); 16 Jun 2003 20:22:18 -0000 Received: from unknown (HELO x1-6-00-09-6b-90-05-28) (12.234.118.28) by sources.redhat.com with SMTP; 16 Jun 2003 20:22:18 -0000 Received: from x1-6-00-09-6b-90-05-28 (coconut.kealia.com [127.0.0.1]) by x1-6-00-09-6b-90-05-28 (8.12.8/8.12.8) with ESMTP id h5GKLfj4031744; Mon, 16 Jun 2003 13:21:41 -0700 Received: (from carlton@localhost) by x1-6-00-09-6b-90-05-28 (8.12.8/8.12.8/Submit) id h5GKLa97031742; Mon, 16 Jun 2003 13:21:36 -0700 X-Authentication-Warning: x1-6-00-09-6b-90-05-28: carlton set sender to carlton@kealia.com using -f To: gdb-patches@sources.redhat.com Cc: Elena Zannoni , Daniel Jacobowitz , Jim Blandy Subject: [rfa] generate symbols associated to namespaces From: David Carlton Date: Mon, 16 Jun 2003 20:22:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-06/txt/msg00546.txt.bz2 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 * 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 * 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 ("", 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, "<>"); } + + return namespace_objfile; +} + +/* Check to see if there's already a namespace symbol whose name is + NAME. If there isn't one, allocate one and add it to the namespace + symtab. */ + +void +cp_check_namespace_symbol (const char *name) +{ + check_namespace_symbol_block (name, strlen (name), + get_namespace_block ()); +} + +/* A helper function used by cp_check_namespace_symbol and + check_one_possible_namespace_symbol. Looks to see if there is a + symbol whose name is the initial substring of NAME of length LEN in + block BLOCK; if not, adds it. Return 1 if the symbol was already + in there, 0 otherwise. */ + +static int +check_namespace_symbol_block (const char *name, int len, + struct block *block) +{ + struct objfile *objfile = get_namespace_objfile (); + char *name_copy = obsavestring (name, len, &objfile->symbol_obstack); + struct symbol *sym = lookup_block_symbol (block, name_copy, NULL, + VAR_DOMAIN); + + if (sym == NULL) + { + struct type *type = init_type (TYPE_CODE_NAMESPACE, 0, 0, + name_copy, objfile); + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + sym = obstack_alloc (&objfile->symbol_obstack, sizeof (struct symbol)); + memset (sym, 0, sizeof (struct symbol)); + SYMBOL_LANGUAGE (sym) = language_cplus; + SYMBOL_SET_NAMES (sym, name_copy, len, objfile); + SYMBOL_CLASS (sym) = LOC_TYPEDEF; + SYMBOL_TYPE (sym) = type; + SYMBOL_DOMAIN (sym) = VAR_DOMAIN; + + dict_add_symbol (BLOCK_DICT (block), sym); + + return 0; + } + else + { + obstack_free (&objfile->symbol_obstack, name_copy); + + return 1; + } +} + +/* Look for a symbol in namespace_block named NAME. */ + +static struct symbol * +lookup_namespace_symbol (const char *name) +{ + return lookup_block_symbol (get_namespace_block (), name, NULL, + VAR_DOMAIN); +} + +/* Ensure that there are symbols in possible_namespace_block for all + initial substrings of NAME that look like namespaces or classes. + NAME should end in a member variable: it shouldn't consist solely + of namespaces. */ + +void +cp_check_possible_namespace_symbols (const char *name) +{ + check_possible_namespace_symbols_loop (name, + cp_find_first_component (name)); +} + +/* This is a helper loop for cp_check_possible_namespace_symbols; it + ensures that there are namespace symbols for all namespaces that + are initial substrings of NAME of length at least LEN. It returns + 1 if a previous loop had already created the shortest such symbol + and 0 otherwise. + + This function assumes that if there is already a symbol associated + to a substring of NAME of a given length, then there are already + symbols associated to all substrings of NAME whose length is less + than that length. So if cp_check_possible_namespace_symbols has + been called once with argument "A::B::C::member", then that will + create symbols "A", "A::B", and "A::B::C". If it is then later + called with argument "A::B::D::member", then the new call will + generate a new symbol for "A::B::D", but once it sees that "A::B" + has already been created, it doesn't bother checking to see if "A" + has also been created. */ + +static int +check_possible_namespace_symbols_loop (const char *name, int len) +{ + if (name[len] == ':') + { + int done; + int next_len = len + 2; + + next_len += cp_find_first_component (name + next_len); + done = check_possible_namespace_symbols_loop (name, next_len); + + if (!done) + { + done = check_one_possible_namespace_symbol (name, len); + } + + return done; + } + else + return 0; +} + +/* Check to see if there's already a possible namespace symbol whose + name is the initial substring of NAME of length LEN. If not, + create one and return 0; otherwise, return 1. */ + +static int +check_one_possible_namespace_symbol (const char *name, int len) +{ + return check_namespace_symbol_block (name, len, + get_possible_namespace_block ()); +} + +/* Look for a symbol in possible_namespace_block named NAME. */ + +static struct symbol * +lookup_possible_namespace_symbol (const char *name) +{ + return lookup_block_symbol (get_possible_namespace_block (), + name, NULL, VAR_DOMAIN); +} + +static void +maintenance_cplus_namespace (char *args, int from_tty) +{ + const struct block *namespace_block = get_namespace_block (); + const struct block *possible_namespace_block + = get_possible_namespace_block (); + struct dict_iterator iter; + struct symbol *sym; + + printf_unfiltered ("Definite namespaces:\n"); + ALL_BLOCK_SYMBOLS (namespace_block, iter, sym) + { + printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); + } + printf_unfiltered ("Possible namespaces:\n"); + ALL_BLOCK_SYMBOLS (possible_namespace_block, iter, sym) + { + printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); + } +} + +void +_initialize_cp_namespace (void) +{ + add_cmd ("namespace", class_maintenance, maintenance_cplus_namespace, + "Print the list of current known C++ namespaces.", + &maint_cplus_cmd_list); } Index: cp-support.c =================================================================== RCS file: /cvs/src/src/gdb/cp-support.c,v retrieving revision 1.5 diff -u -p -r1.5 cp-support.c --- cp-support.c 12 Jun 2003 15:33:45 -0000 1.5 +++ cp-support.c 16 Jun 2003 19:55:44 -0000 @@ -45,7 +45,7 @@ static void overload_list_add_symbol (st /* The list of "maint cplus" commands. */ -static struct cmd_list_element *maint_cplus_cmd_list = NULL; +struct cmd_list_element *maint_cplus_cmd_list = NULL; /* The actual commands. */ Index: cp-support.h =================================================================== RCS file: /cvs/src/src/gdb/cp-support.h,v retrieving revision 1.6 diff -u -p -r1.6 cp-support.h --- cp-support.h 12 Jun 2003 15:33:45 -0000 1.6 +++ cp-support.h 16 Jun 2003 19:55:44 -0000 @@ -96,4 +96,12 @@ extern struct symbol *cp_lookup_symbol_n const domain_enum domain, struct symtab **symtab); +extern void cp_check_namespace_symbol (const char *name); + +extern void cp_check_possible_namespace_symbols (const char *name); + +/* The list of "maint cplus" commands. */ + +extern struct cmd_list_element *maint_cplus_cmd_list; + #endif /* CP_SUPPORT_H */ Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.96 diff -u -p -r1.96 dwarf2read.c --- dwarf2read.c 11 Jun 2003 22:27:11 -0000 1.96 +++ dwarf2read.c 16 Jun 2003 19:55:52 -0000 @@ -678,10 +678,30 @@ static void dwarf2_build_psymtabs_hard ( static char *scan_partial_symbols (char *, struct objfile *, CORE_ADDR *, CORE_ADDR *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); static void add_partial_symbol (struct partial_die_info *, struct objfile *, - const struct comp_unit_head *); + const struct comp_unit_head *, + const char *namespace); + +static char *add_partial_namespace (struct partial_die_info *pdi, + char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *add_partial_enumeration (struct partial_die_info *enum_pdi, + char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace); + +static char *locate_pdi_sibling (struct partial_die_info *orig_pdi, + char *info_ptr, + bfd *abfd, + const struct comp_unit_head *cu_header); static void dwarf2_psymtab_to_symtab (struct partial_symtab *); @@ -1323,9 +1343,17 @@ dwarf2_build_psymtabs_hard (struct objfi If not, there's no more debug_info for this comp unit. */ if (comp_unit_die.has_children) { + lowpc = ((CORE_ADDR) -1); + highpc = ((CORE_ADDR) 0); + info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc, - &cu_header); + &cu_header, NULL); + /* If we didn't find a lowpc, set it to highpc to avoid + complaints from `maint check'. */ + if (lowpc == ((CORE_ADDR) -1)) + lowpc = highpc; + /* If the compilation unit didn't have an explicit address range, then use the information extracted from its child dies. */ if (! comp_unit_die.has_pc_info) @@ -1354,45 +1382,40 @@ dwarf2_build_psymtabs_hard (struct objfi do_cleanups (back_to); } -/* Read in all interesting dies to the end of the compilation unit. */ +/* Read in all interesting dies to the end of the compilation unit or + to the end of the current namespace. NAMESPACE is NULL if we + haven't yet encountered any DW_TAG_namespace entries; otherwise, + it's the name of the current namespace. In particular, it's the + empty string if we're currently in the global namespace but have + previously encountered a DW_TAG_namespace. */ static char * scan_partial_symbols (char *info_ptr, struct objfile *objfile, CORE_ADDR *lowpc, CORE_ADDR *highpc, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { bfd *abfd = objfile->obfd; struct partial_die_info pdi; - /* This function is called after we've read in the comp_unit_die in - order to read its children. We start the nesting level at 1 since - we have pushed 1 level down in order to read the comp unit's children. - The comp unit itself is at level 0, so we stop reading when we pop - back to that level. */ - - int nesting_level = 1; - - /* We only want to read in symbols corresponding to variables or - other similar objects that are global or static. Normally, these - are all children of the DW_TAG_compile_unit die, so are all at - level 1. But C++ namespaces give ries to DW_TAG_namespace dies - whose children are global objects. So we keep track of what - level we currently think of as referring to file scope; this - should always equal 1 plus the number of namespaces that we are - currently nested within. */ - - int file_scope_level = 1; - - *lowpc = ((CORE_ADDR) -1); - *highpc = ((CORE_ADDR) 0); + /* Now, march along the PDI's, descending into ones which have + interesting children but skipping the children of the other ones, + until we reach the end of the compilation unit. */ - while (nesting_level) + while (1) { + /* This flag tells whether or not info_ptr has gotten updated + inside the loop. */ + int info_ptr_updated = 0; + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); - /* Anonymous namespaces have no name but are interesting. */ + /* Anonymous namespaces have no name but have interesting + children, so we need to look at them. Ditto for anonymous + enums. */ - if (pdi.name != NULL || pdi.tag == DW_TAG_namespace) + if (pdi.name != NULL || pdi.tag == DW_TAG_namespace + || pdi.tag == DW_TAG_enumeration_type) { switch (pdi.tag) { @@ -1407,93 +1430,77 @@ scan_partial_symbols (char *info_ptr, st { *highpc = pdi.highpc; } - if ((pdi.is_external || nesting_level == file_scope_level) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } } break; case DW_TAG_variable: case DW_TAG_typedef: + case DW_TAG_union_type: case DW_TAG_class_type: case DW_TAG_structure_type: - case DW_TAG_union_type: - case DW_TAG_enumeration_type: - if ((pdi.is_external || nesting_level == file_scope_level) - && !pdi.is_declaration) + if (!pdi.is_declaration) { - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); } break; - case DW_TAG_enumerator: - /* File scope enumerators are added to the partial - symbol table. They're children of the enumeration - type die, so they occur at a level one higher than we - normally look for. */ - if (nesting_level == file_scope_level + 1) - add_partial_symbol (&pdi, objfile, cu_header); + case DW_TAG_enumeration_type: + if (!pdi.is_declaration) + { + info_ptr = add_partial_enumeration (&pdi, info_ptr, + objfile, cu_header, + namespace); + info_ptr_updated = 1; + } break; case DW_TAG_base_type: /* File scope base type definitions are added to the partial symbol table. */ - if (nesting_level == file_scope_level) - add_partial_symbol (&pdi, objfile, cu_header); + add_partial_symbol (&pdi, objfile, cu_header, namespace); break; case DW_TAG_namespace: - /* FIXME: carlton/2002-10-16: we're not yet doing - anything useful with this, but for now make sure that - these tags at least don't cause us to miss any - important symbols. */ - if (pdi.has_children) - file_scope_level++; + /* We've hit a DW_TAG_namespace entry, so we know this + file has been compiled using a compiler that + generates them; update NAMESPACE to reflect that. */ + if (namespace == NULL) + namespace = ""; + info_ptr = add_partial_namespace (&pdi, info_ptr, objfile, + lowpc, highpc, cu_header, + namespace); + info_ptr_updated = 1; + break; default: break; } } - /* If the die has a sibling, skip to the sibling. Do not skip - enumeration types, we want to record their enumerators. Do - not skip namespaces, we want to record symbols inside - them. */ - if (pdi.sibling - && pdi.tag != DW_TAG_enumeration_type - && pdi.tag != DW_TAG_namespace) - { - info_ptr = pdi.sibling; - } - else if (pdi.has_children) - { - /* Die has children, but either the optional DW_AT_sibling - attribute is missing or we want to look at them. */ - nesting_level++; - } - if (pdi.tag == 0) - { - nesting_level--; - /* If this is the end of a DW_TAG_namespace entry, then - decrease the file_scope_level, too. */ - if (nesting_level < file_scope_level) - { - file_scope_level--; - gdb_assert (nesting_level == file_scope_level); - } - } + break; + + /* If the die has a sibling, skip to the sibling, unless another + function has already updated info_ptr for us. */ + + /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether + or not we want to update this depends on enough stuff (not + only pdi.tag but also whether or not pdi.name is NULL) that + this seems like the easiest way to handle the issue. */ + + if (!info_ptr_updated) + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); } - /* If we didn't find a lowpc, set it to highpc to avoid complaints - from `maint check'. */ - if (*lowpc == ((CORE_ADDR) -1)) - *lowpc = *highpc; return info_ptr; } static void add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + const char *namespace) { CORE_ADDR addr = 0; + const struct partial_symbol *psym = NULL; switch (pdi->tag) { @@ -1502,19 +1509,21 @@ add_partial_symbol (struct partial_die_i { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->global_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->global_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } else { /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr, mst_file_text, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_BLOCK, - &objfile->static_psymbols, - 0, pdi->lowpc + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_BLOCK, + &objfile->static_psymbols, + 0, pdi->lowpc + baseaddr, + cu_language, objfile); } break; case DW_TAG_variable: @@ -1536,10 +1545,11 @@ add_partial_symbol (struct partial_die_i if (pdi->locdesc) addr = decode_locdesc (pdi->locdesc, objfile, cu_header); if (pdi->locdesc || pdi->has_type) - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->global_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->global_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } else { @@ -1549,10 +1559,11 @@ add_partial_symbol (struct partial_die_i addr = decode_locdesc (pdi->locdesc, objfile, cu_header); /*prim_record_minimal_symbol (pdi->name, addr + baseaddr, mst_file_data, objfile); */ - add_psymbol_to_list (pdi->name, strlen (pdi->name), - VAR_DOMAIN, LOC_STATIC, - &objfile->static_psymbols, - 0, addr + baseaddr, cu_language, objfile); + psym = add_psymbol_to_list (pdi->name, strlen (pdi->name), + VAR_DOMAIN, LOC_STATIC, + &objfile->static_psymbols, + 0, addr + baseaddr, + cu_language, objfile); } break; case DW_TAG_typedef: @@ -1592,6 +1603,117 @@ add_partial_symbol (struct partial_die_i break; default: break; + } + + /* Check to see if we should scan the name for possible namespace + info. Only do this if this is C++, if we don't have namespace + debugging info in the file, if the psym is of an appropriate type + (otherwise we'll have psym == NULL), and if we actually had a + mangled name to begin with. */ + + if (cu_language == language_cplus + && namespace == NULL + && psym != NULL + && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL) + cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym)); +} + +/* Read a partial die corresponding to a namespace; also, add a symbol + corresponding to that namespace to the symbol table. NAMESPACE is + the name of the enclosing namespace. */ + +static char * +add_partial_namespace (struct partial_die_info *pdi, char *info_ptr, + struct objfile *objfile, + CORE_ADDR *lowpc, CORE_ADDR *highpc, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + /* Calculate the full name of the namespace that we just entered. */ + + const char *new_name = pdi->name; + char *full_name; + + if (new_name == NULL) + new_name = "(anonymous namespace)"; + full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1); + strcpy (full_name, namespace); + if (*namespace != '\0') + strcat (full_name, "::"); + strcat (full_name, new_name); + + /* Make sure that there's a symbol associated to that namespace. */ + + cp_check_namespace_symbol (full_name); + + /* Now scan partial symbols in that namespace. */ + + if (pdi->has_children) + info_ptr = scan_partial_symbols (info_ptr, objfile, + lowpc, highpc, + cu_header, full_name); + + return info_ptr; +} + +/* Read a partial die corresponding to an enumeration type. */ + +static char * +add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr, + struct objfile *objfile, + const struct comp_unit_head *cu_header, + const char *namespace) +{ + bfd *abfd = objfile->obfd; + struct partial_die_info pdi; + + if (enum_pdi->name != NULL) + add_partial_symbol (enum_pdi, objfile, cu_header, namespace); + + while (1) + { + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + if (pdi.tag == 0) + break; + gdb_assert (pdi.tag == DW_TAG_enumerator); + gdb_assert (pdi.name != NULL); + add_partial_symbol (&pdi, objfile, cu_header, namespace); + } + + return info_ptr; +} + +/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next PDI + after ORIG_PDI. */ + +static char * +locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr, + bfd *abfd, const struct comp_unit_head *cu_header) +{ + /* Do we know the sibling already? */ + + if (orig_pdi->sibling) + return orig_pdi->sibling; + + /* Are there any children to deal with? */ + + if (!orig_pdi->has_children) + return info_ptr; + + /* Okay, we don't know the sibling, but we have children that we + want to skip. So read children until we run into one without a + tag; return whatever follows it. */ + + while (1) + { + struct partial_die_info pdi; + + info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header); + + if (pdi.tag == 0) + return info_ptr; + else + info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header); } } Index: gdbtypes.c =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.c,v retrieving revision 1.73 diff -u -p -r1.73 gdbtypes.c --- gdbtypes.c 8 Jun 2003 18:27:13 -0000 1.73 +++ gdbtypes.c 16 Jun 2003 19:55:56 -0000 @@ -1896,7 +1896,8 @@ init_type (enum type_code code, int leng if (name && strcmp (name, "char") == 0) TYPE_FLAGS (type) |= TYPE_FLAG_NOSIGN; - if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) + if (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION + || code == TYPE_CODE_NAMESPACE) { INIT_CPLUS_SPECIFIC (type); } @@ -3143,6 +3144,9 @@ recursive_dump_type (struct type *type, break; case TYPE_CODE_TEMPLATE_ARG: printf_filtered ("(TYPE_CODE_TEMPLATE_ARG)"); + break; + case TYPE_CODE_NAMESPACE: + printf_filtered ("(TYPE_CODE_NAMESPACE)"); break; default: printf_filtered ("(UNKNOWN TYPE CODE)"); Index: gdbtypes.h =================================================================== RCS file: /cvs/src/src/gdb/gdbtypes.h,v retrieving revision 1.47 diff -u -p -r1.47 gdbtypes.h --- gdbtypes.h 14 May 2003 17:43:17 -0000 1.47 +++ gdbtypes.h 16 Jun 2003 19:55:57 -0000 @@ -134,8 +134,9 @@ enum type_code TYPE_CODE_TYPEDEF, TYPE_CODE_TEMPLATE, /* C++ template */ - TYPE_CODE_TEMPLATE_ARG /* C++ template arg */ + TYPE_CODE_TEMPLATE_ARG, /* C++ template arg */ + TYPE_CODE_NAMESPACE, /* C++ namespace. */ }; /* For now allow source to use TYPE_CODE_CLASS for C++ classes, as an Index: jv-lang.c =================================================================== RCS file: /cvs/src/src/gdb/jv-lang.c,v retrieving revision 1.21 diff -u -p -r1.21 jv-lang.c --- jv-lang.c 11 Jun 2003 23:29:47 -0000 1.21 +++ jv-lang.c 16 Jun 2003 19:55:59 -0000 @@ -111,22 +111,13 @@ get_java_class_symtab (void) BLOCKVECTOR (class_symtab) = bv; /* Allocate dummy STATIC_BLOCK. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack, NULL); - BLOCK_START (bl) = 0; - BLOCK_END (bl) = 0; - BLOCK_FUNCTION (bl) = NULL; - BLOCK_SUPERBLOCK (bl) = NULL; - BLOCK_NAMESPACE (bl) = NULL; - BLOCK_GCC_COMPILED (bl) = 0; BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; - /* Allocate GLOBAL_BLOCK. This has to be relocatable. */ - bl = (struct block *) - obstack_alloc (&objfile->symbol_obstack, sizeof (struct block)); - *bl = *BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); + /* Allocate GLOBAL_BLOCK. */ + bl = allocate_block (&objfile->symbol_obstack); BLOCK_DICT (bl) = dict_create_hashed_expandable (); BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; class_symtab->free_func = free_class_block; Index: printcmd.c =================================================================== RCS file: /cvs/src/src/gdb/printcmd.c,v retrieving revision 1.63 diff -u -p -r1.63 printcmd.c --- printcmd.c 9 Jun 2003 15:20:21 -0000 1.63 +++ printcmd.c 16 Jun 2003 19:56:01 -0000 @@ -315,7 +315,8 @@ print_formatted (struct value *val, regi || TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_CODE (type) == TYPE_CODE_STRING || TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION) + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_NAMESPACE) /* If format is 0, use the 'natural' format for * that type of value. If the type is non-scalar, * we have to use language rules to print it as Index: symfile.c =================================================================== RCS file: /cvs/src/src/gdb/symfile.c,v retrieving revision 1.98 diff -u -p -r1.98 symfile.c --- symfile.c 11 Jun 2003 22:27:13 -0000 1.98 +++ symfile.c 16 Jun 2003 19:56:05 -0000 @@ -2635,9 +2635,10 @@ start_psymtab_common (struct objfile *ob } /* Add a symbol with a long value to a psymtab. - Since one arg is a struct, we pass in a ptr and deref it (sigh). */ + Since one arg is a struct, we pass in a ptr and deref it (sigh). + Return the partial symbol that has been added. */ -void +const struct partial_symbol * add_psymbol_to_list (char *name, int namelength, domain_enum domain, enum address_class class, struct psymbol_allocation_list *list, long val, /* Value as a long */ @@ -2680,6 +2681,8 @@ add_psymbol_to_list (char *name, int nam } *list->next++ = psym; OBJSTAT (objfile, n_psyms++); + + return psym; } /* Add a symbol with a long value to a psymtab. This differs from Index: symfile.h =================================================================== RCS file: /cvs/src/src/gdb/symfile.h,v retrieving revision 1.24 diff -u -p -r1.24 symfile.h --- symfile.h 11 Jun 2003 22:27:13 -0000 1.24 +++ symfile.h 16 Jun 2003 19:56:05 -0000 @@ -152,9 +152,12 @@ extern void extend_psymbol_list (struct /* #include "demangle.h" */ -extern void add_psymbol_to_list (char *, int, domain_enum, enum address_class, - struct psymbol_allocation_list *, long, - CORE_ADDR, enum language, struct objfile *); +extern const +struct partial_symbol *add_psymbol_to_list (char *, int, domain_enum, + enum address_class, + struct psymbol_allocation_list *, + long, CORE_ADDR, + enum language, struct objfile *); extern void add_psymbol_with_dem_name_to_list (char *, int, char *, int, domain_enum, Index: typeprint.c =================================================================== RCS file: /cvs/src/src/gdb/typeprint.c,v retrieving revision 1.18 diff -u -p -r1.18 typeprint.c --- typeprint.c 8 Jun 2003 18:27:14 -0000 1.18 +++ typeprint.c 16 Jun 2003 19:56:06 -0000 @@ -307,6 +307,7 @@ print_type_scalar (struct type *type, LO case TYPE_CODE_MEMBER: case TYPE_CODE_METHOD: case TYPE_CODE_REF: + case TYPE_CODE_NAMESPACE: error ("internal error: unhandled type in print_type_scalar"); break; Index: testsuite/gdb.c++/maint.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/maint.exp,v retrieving revision 1.2 diff -u -p -r1.2 maint.exp --- testsuite/gdb.c++/maint.exp 23 Apr 2003 23:45:24 -0000 1.2 +++ testsuite/gdb.c++/maint.exp 16 Jun 2003 19:56:21 -0000 @@ -29,13 +29,19 @@ if $tracelevel then { # Test the help messages. proc test_help {} { - gdb_test "help maintenance cplus" "C\\+\\+ maintenance commands.\r\n\r\nList of maintenance cplus subcommands:\r\n\r\nmaintenance cplus first_component -- Print the first class/namespace component of NAME\r\n\r\nType \"help maintenance cplus\" 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::bar" "C" gdb_test "maint cp first_component C > >::bar" "C > >" +} + +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.*"