diff options
author | David Carlton <carlton@bactrian.org> | 2002-10-22 19:59:37 +0000 |
---|---|---|
committer | David Carlton <carlton@bactrian.org> | 2002-10-22 19:59:37 +0000 |
commit | 2d185a21dfe1493b6f24b73faa4be4b1608f718f (patch) | |
tree | fd6414a8ad3efa921ae4b064458ce50d164c92f4 | |
parent | 58fabab07992522e0e08e42d1c25d119ad78e9b4 (diff) | |
download | binutils-2d185a21dfe1493b6f24b73faa4be4b1608f718f.zip binutils-2d185a21dfe1493b6f24b73faa4be4b1608f718f.tar.gz binutils-2d185a21dfe1493b6f24b73faa4be4b1608f718f.tar.bz2 |
2002-10-22 David Carlton <carlton@math.stanford.edu>
* Makefile.in (buildsym.o): Depend on $(gdb_assert_h) and
$(cp_support_h).
(cp-support.o): Fix dependencies and add $(gdb_obstack_h) and
$(gdb_assert_h).
(symtab.o): Depend on $(cp_support_h).
* symtab.h: Add opaque declaration for struct using_direct_node.
(struct block): Add member 'language_specific'.
(BLOCK_USING): New macro.
* symtab.c: #include "cp-support.h"
(lookup_symbol_aux): Call lookup_symbol_aux_nonlocal and
lookup_symbol_aux_using when appropriate.
(lookup_symbol_aux_nonlocal): New function.
(lookup_symbol_aux_using): New function.
(lookup_symbol_aux_using_loop): New function.
* symfile.h: Add opaque declaration for struct obstack.
Declare obsavestring to take a const char *.
* symfile.c (obsavestring): Make first argument a const char *.
* jv-lang.c (get_java_class_symtab): Initialize BLOCK_USING.
* dwarf2read.c: New variable current_namespace.
(scan_partial_symbols): Handle DW_TAG_namespace.
(psymtab_to_symtab_1): Initialize current_namespace.
(process_die): Handle DW_TAG_namespace,
DW_TAG_imported_declaration, DW_TAG_imported_module.
(read_namespace): New function.
(dwarf2_name): New function.
(dwarf2_extension): New function.
(dwarf_tag_name): Add DWARF 3 names.
(dwarf_attr_name): Ditto.
(dwarf_type_encoding_name): Ditto.
* cp-support.h: Opaque declaration for struct obstack.
(struct using_direct): New struct.
(struct using_direct_node): New struct.
Add declarations for cp_add_using_obstack, cp_add_using_xmalloc,
cp_copy_usings, cp_free_usings, cp_find_first_component.
* cp-support.c: #include "gdb_obstack.h", "gdb_assert.h".
Comment on demangled name pitfalls.
(cp_add_using_obstack): New function.
(cp_add_using_xmalloc): New function.
(cp_copy_usings): New function.
(cp_free_usings): New function.
(cp_find_first_component): New function.
* buildsym.h: Declare processing_has_namespace_info.
Declare add_using_directive.
* buildsym.c: #include "gdb_assert.h", "cp-support.h".
Change comment after #include "symfile.h".
New variable using_list.
(add_symbol_to_list): Scan for anonymous namespaces when
appropriate.
(scan_for_anonymous_namespaces): New function.
(add_using_directive): New function.
(start_symtab): Initialize processing_has_namespace_info,
using_list.
(end_symtab): Copy using_list into block.
(copy_usings_to_obstack): New function.
(finish_block): Set BLOCK_USING in general case and in C++
function case.
2002-10-22 David Carlton <carlton@math.stanford.edu>
* gdb.c++/namespace.exp: Add tests involving namespaces
starting from C.
* gdb.c++/namespace.cc: Add namespaces with names starting
from C and their contents.
-rw-r--r-- | gdb/ChangeLog.cplus | 59 | ||||
-rw-r--r-- | gdb/Makefile.in | 7 | ||||
-rw-r--r-- | gdb/buildsym.c | 158 | ||||
-rw-r--r-- | gdb/buildsym.h | 9 | ||||
-rw-r--r-- | gdb/cp-support.c | 201 | ||||
-rw-r--r-- | gdb/cp-support.h | 63 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 211 | ||||
-rw-r--r-- | gdb/jv-lang.c | 1 | ||||
-rw-r--r-- | gdb/symfile.c | 6 | ||||
-rw-r--r-- | gdb/symfile.h | 6 | ||||
-rw-r--r-- | gdb/symtab.c | 210 | ||||
-rw-r--r-- | gdb/symtab.h | 19 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog.cplus | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.c++/namespace.cc | 150 | ||||
-rw-r--r-- | gdb/testsuite/gdb.c++/namespace.exp | 68 |
15 files changed, 1135 insertions, 39 deletions
diff --git a/gdb/ChangeLog.cplus b/gdb/ChangeLog.cplus index d764cd3..07bf6d2 100644 --- a/gdb/ChangeLog.cplus +++ b/gdb/ChangeLog.cplus @@ -1,3 +1,62 @@ +2002-10-22 David Carlton <carlton@math.stanford.edu> + + * Makefile.in (buildsym.o): Depend on $(gdb_assert_h) and + $(cp_support_h). + (cp-support.o): Fix dependencies and add $(gdb_obstack_h) and + $(gdb_assert_h). + (symtab.o): Depend on $(cp_support_h). + * symtab.h: Add opaque declaration for struct using_direct_node. + (struct block): Add member 'language_specific'. + (BLOCK_USING): New macro. + * symtab.c: #include "cp-support.h" + (lookup_symbol_aux): Call lookup_symbol_aux_nonlocal and + lookup_symbol_aux_using when appropriate. + (lookup_symbol_aux_nonlocal): New function. + (lookup_symbol_aux_using): New function. + (lookup_symbol_aux_using_loop): New function. + * symfile.h: Add opaque declaration for struct obstack. + Declare obsavestring to take a const char *. + * symfile.c (obsavestring): Make first argument a const char *. + * jv-lang.c (get_java_class_symtab): Initialize BLOCK_USING. + * dwarf2read.c: New variable current_namespace. + (scan_partial_symbols): Handle DW_TAG_namespace. + (psymtab_to_symtab_1): Initialize current_namespace. + (process_die): Handle DW_TAG_namespace, + DW_TAG_imported_declaration, DW_TAG_imported_module. + (read_namespace): New function. + (dwarf2_name): New function. + (dwarf2_extension): New function. + (dwarf_tag_name): Add DWARF 3 names. + (dwarf_attr_name): Ditto. + (dwarf_type_encoding_name): Ditto. + * cp-support.h: Opaque declaration for struct obstack. + (struct using_direct): New struct. + (struct using_direct_node): New struct. + Add declarations for cp_add_using_obstack, cp_add_using_xmalloc, + cp_copy_usings, cp_free_usings, cp_find_first_component. + * cp-support.c: #include "gdb_obstack.h", "gdb_assert.h". + Comment on demangled name pitfalls. + (cp_add_using_obstack): New function. + (cp_add_using_xmalloc): New function. + (cp_copy_usings): New function. + (cp_free_usings): New function. + (cp_find_first_component): New function. + * buildsym.h: Declare processing_has_namespace_info. + Declare add_using_directive. + * buildsym.c: #include "gdb_assert.h", "cp-support.h". + Change comment after #include "symfile.h". + New variable using_list. + (add_symbol_to_list): Scan for anonymous namespaces when + appropriate. + (scan_for_anonymous_namespaces): New function. + (add_using_directive): New function. + (start_symtab): Initialize processing_has_namespace_info, + using_list. + (end_symtab): Copy using_list into block. + (copy_usings_to_obstack): New function. + (finish_block): Set BLOCK_USING in general case and in C++ + function case. + 2002-10-11 David Carlton <carlton@math.stanford.edu> * symtab.c (lookup_symbol_aux): Move chunks of code into separate diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 95330c0..0888207 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1541,7 +1541,7 @@ buildsym.o: buildsym.c $(defs_h) $(bfd_h) $(gdb_obstack_h) $(symtab_h) \ $(symfile_h) $(objfiles_h) $(gdbtypes_h) $(complaints_h) \ $(gdb_string_h) $(expression_h) $(language_h) $(bcache_h) \ $(filenames_h) $(macrotab_h) $(demangle_h) $(buildsym_h) \ - $(stabsread_h) + $(stabsread_h) $(gdb_assert_h) $(cp_support_h) builtin-regs.o: builtin-regs.c $(defs_h) $(builtin_regs_h) $(gdbtypes_h) \ $(gdb_string_h) $(gdb_assert_h) c-lang.o: c-lang.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ @@ -1586,7 +1586,8 @@ corelow.o: corelow.c $(defs_h) $(gdb_string_h) $(frame_h) $(inferior_h) \ $(symtab_h) $(command_h) $(bfd_h) $(target_h) $(gdbcore_h) \ $(gdbthread_h) $(regcache_h) $(symfile_h) cp-abi.o: cp-abi.c $(defs_h) $(value_h) $(cp_abi_h) $(gdb_string_h) -cp-support.o: cp-support.c $(defs_h) $(cp_support_h) +cp-support.o: cp-support.c $(defs_h) $(cp_support_h) $(gdb_string_h) \ + $(demangle_h) $(gdb_obstack_h) $(gdb_assert_h) cp-valprint.o: cp-valprint.c $(defs_h) $(gdb_obstack_h) $(symtab_h) \ $(gdbtypes_h) $(expression_h) $(value_h) $(command_h) $(gdbcmd_h) \ $(demangle_h) $(annotate_h) $(gdb_string_h) $(c_lang_h) $(target_h) \ @@ -2202,7 +2203,7 @@ symtab.o: symtab.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(gdbcore_h) \ $(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \ $(language_h) $(demangle_h) $(inferior_h) $(linespec_h) \ $(filenames_h) $(gdb_obstack_h) $(gdb_string_h) $(gdb_stat_h) \ - $(cp_abi_h) $(source_h) + $(cp_abi_h) $(source_h) $(cp_support_h) target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \ $(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \ $(gdb_wait_h) $(dcache_h) $(regcache_h) diff --git a/gdb/buildsym.c b/gdb/buildsym.c index 9d9b4f7..7bbc0e6 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -30,7 +30,7 @@ #include "bfd.h" #include "gdb_obstack.h" #include "symtab.h" -#include "symfile.h" /* Needed for "struct complaint" */ +#include "symfile.h" /* Needed for "struct complaint", obsavestring */ #include "objfiles.h" #include "gdbtypes.h" #include "complaints.h" @@ -41,6 +41,8 @@ #include "filenames.h" /* For DOSish file names */ #include "macrotab.h" #include "demangle.h" /* Needed by SYMBOL_INIT_DEMANGLED_NAME. */ +#include "gdb_assert.h" +#include "cp-support.h" /* Ask buildsym.h to define the vars it normally declares `extern'. */ #define EXTERN /**/ @@ -60,8 +62,21 @@ static struct pending *free_pendings; otherwise empty symtab from being tossed. */ static int have_line_numbers; + +/* List of using directives that are active in the current file. */ + +static struct using_direct_node *using_list; + static int compare_line_numbers (const void *ln1p, const void *ln2p); + +static void scan_for_anonymous_namespaces (struct symbol *symbol); + +static struct using_direct_node *copy_usings_to_obstack (struct + using_direct_node + *usings, + struct obstack + *obstack); /* Initial sizes of data structures. These are realloc'd larger if @@ -105,7 +120,10 @@ add_free_pendings (struct pending *list) } } -/* Add a symbol to one of the lists of symbols. */ +/* Add a symbol to one of the lists of symbols. While we're at it, if + we're in the C++ case and don't have full namespace debugging info, + check to see if it references an anonymous namespace; if so, add an + appropriate using directive. */ void add_symbol_to_list (struct symbol *symbol, struct pending **listhead) @@ -136,6 +154,49 @@ add_symbol_to_list (struct symbol *symbol, struct pending **listhead) } (*listhead)->symbol[(*listhead)->nsyms++] = symbol; + + /* Check to see if we might need to look for a mention of anonymous + namespaces. */ + + if (SYMBOL_LANGUAGE (symbol) == language_cplus + && !processing_has_namespace_info + && SYMBOL_CPLUS_DEMANGLED_NAME (symbol) != NULL) + scan_for_anonymous_namespaces (symbol); +} + +/* Check to see if a symbol is contained within an anonymous + namespace; if so, add an appropriate using directive. */ + +/* Optimize away strlen ("(anonymous namespace)"). */ + +#define ANONYMOUS_NAMESPACE_LEN 21 + +static void +scan_for_anonymous_namespaces (struct symbol *symbol) +{ + const char *name = SYMBOL_CPLUS_DEMANGLED_NAME (symbol); + const char *beginning, *end; + + /* FIXME: carlton/2002-10-14: Should we do some sort of fast search + first to see if the substring "(anonymous namespace)" occurs in + name at all? */ + + for (beginning = name, end = cp_find_first_component (name); + *end == ':'; + /* The "+ 2" is for the "::"-. */ + beginning = end + 2, end = cp_find_first_component (beginning)) + { + if ((end - beginning) == ANONYMOUS_NAMESPACE_LEN + && strncmp (beginning, "(anonymous namespace)", + ANONYMOUS_NAMESPACE_LEN) == 0) + /* We've found a component of the name that's an anonymous + namespace. So add symbols in it to the namespace given by + the previous component if there is one, or to the global + namespace if there isn't. */ + add_using_directive (name, + beginning == name ? 0 : beginning - name - 2, + end - name); + } } /* Find a symbol named NAME on a LIST. NAME need not be @@ -163,6 +224,35 @@ find_symbol_in_list (struct pending *list, char *name, int length) return (NULL); } +/* This adds a using directive to using_list. NAME is the start of a + string that should contain the namespaces we want to add as initial + substrings, OUTER_LENGTH is the end of the outer namespace, and + INNER_LENGTH is the end of the inner namespace. If the using + directive in question has already been added, don't add it + twice. */ + +void +add_using_directive (const char *name, unsigned int outer_length, + unsigned int inner_length) +{ + struct using_direct_node *current; + struct using_direct_node *new_node; + struct using_direct *new; + + gdb_assert (outer_length < inner_length); + + /* Has it already been added? */ + + for (current = using_list; current; current = current->next) + if (current->current->outer_length == outer_length + && current->current->inner_length == inner_length + && (strncmp (current->current->name, name, inner_length) == 0)) + return; + + using_list = cp_add_using_xmalloc (name, outer_length, inner_length, + using_list); +} + /* At end of reading syms, or in case of quit, really free as many `struct pending's as we can easily find. */ @@ -294,6 +384,7 @@ finish_block (struct symbol *symbol, struct pending **listhead, BLOCK_END (block) = end; /* Superblock filled in when containing block is made */ BLOCK_SUPERBLOCK (block) = NULL; + BLOCK_USING (block) = NULL; BLOCK_GCC_COMPILED (block) = processing_gcc_compilation; @@ -382,6 +473,34 @@ finish_block (struct symbol *symbol, struct pending **listhead, } } } + + /* If we're in the C++ case, make sure that we add 'using' + directives for all of the namespaces in which this function + lives. Also, make sure that the name was originally mangled: + if not, there certainly isn't any namespace information to + worry about! (Also, if not, the gdb_assert will fail.) */ + if (SYMBOL_LANGUAGE (symbol) == language_cplus + && SYMBOL_CPLUS_DEMANGLED_NAME (symbol) != NULL) + { + const char *name = SYMBOL_CPLUS_DEMANGLED_NAME (symbol); + const char *next; + + for (next = cp_find_first_component (name); + *next == ':'; + /* The '+ 2' is to skip the '::'. */ + next = cp_find_first_component (next + 2)) + { + BLOCK_USING (block) + = cp_add_using_obstack (name, 0, next - name, + BLOCK_USING (block), + &objfile->symbol_obstack); + } + + /* FIMXE: carlton/2002-10-09: Until I understand the + possible pitfalls of demangled names a lot better, I want + to make sure I'm not running into surprises. */ + gdb_assert (*next == '\0'); + } } else { @@ -807,6 +926,8 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr) global_symbols = NULL; within_function = 0; have_line_numbers = 0; + processing_has_namespace_info = 0; + using_list = NULL; /* Context stack is initially empty. Allocate first one with room for 10 levels; reuse it forever afterward. */ @@ -940,6 +1061,13 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) finish_block (0, &global_symbols, 0, last_source_start_addr, end_addr, objfile); blockvector = make_blockvector (objfile); + if (using_list != NULL) + { + BLOCK_USING (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK)) + = copy_usings_to_obstack (using_list, + &objfile->symbol_obstack); + using_list = NULL; + } } #ifndef PROCESS_LINENUMBER_HOOK @@ -1070,6 +1198,32 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) return symtab; } +/* This reallocates USINGS using OBSTACK and xfree's USINGS. It + returns the reallocated version of USINGS. */ + +static struct using_direct_node * +copy_usings_to_obstack (struct using_direct_node *usings, + struct obstack *obstack) +{ + if (usings == NULL) + return NULL; + else + { + struct using_direct_node *new_node + = cp_add_using_obstack (usings->current->name, + usings->current->outer_length, + usings->current->inner_length, + copy_usings_to_obstack (usings->next, + obstack), + obstack); + + xfree (usings->current); + xfree (usings); + + return new_node; + } +} + /* Push a context block. Args are an identifying nesting level (checkable when you pop it), and the starting PC address of this context. */ diff --git a/gdb/buildsym.h b/gdb/buildsym.h index 8a252cb..3b8c16f 100644 --- a/gdb/buildsym.h +++ b/gdb/buildsym.h @@ -93,6 +93,12 @@ EXTERN unsigned char processing_acc_compilation; EXTERN unsigned char processing_hp_compilation; +/* When set, the file that we're processing seems to have debugging + info for C++ namespaces, so buildsym.c shouldn't try to guess + namespace info itself. */ + +EXTERN unsigned char processing_has_namespace_info; + /* Count symbols as they are processed, for error messages. */ EXTERN unsigned int symnum; @@ -240,6 +246,9 @@ extern void add_symbol_to_list (struct symbol *symbol, extern struct symbol *find_symbol_in_list (struct pending *list, char *name, int length); +extern void add_using_directive (const char *name, unsigned int outer_length, + unsigned int inner_length); + extern void finish_block (struct symbol *symbol, struct pending **listhead, struct pending_block *old_blocks, diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 46363a8..a13967f 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -24,6 +24,36 @@ #include "cp-support.h" #include "gdb_string.h" #include "demangle.h" +#include "gdb_obstack.h" +#include "gdb_assert.h" + +/* Here are some random pieces of trivia to keep in mind while trying + to take apart demangled names: + + - Names can contain function arguments or templates, so the process + has to be, to some extent recursive: maybe keep track of your + depth based on encountering <> and (). + + - Parentheses don't just have to happen at the end of a name: they + can occur even if the name in question isn't a function, because + a template argument might be a type that's a function. + + - Conversely, even if you're trying to deal with a function, its + demangled name might not end with ')': it could be a const (or + volatile, I suppose) class method, in which case it ends with + "const". + + - Parentheses are also used in anonymous namespaces: a variable + 'foo' in an anonymous namespace gets demangled as "(anonymous + namespace)::foo". + + - And operator names can contain parentheses or angle brackets. + Fortunately, I _think_ that operator names can only occur in a + fairly restrictive set of locations (in particular, they have be + at depth 0, don't they?). */ + +/* FIXME: carlton/2002-10-09: Do all the functions here handle all the + above considerations correctly? */ /* Find the last component of the demangled C++ name NAME. NAME must be a method name including arguments, in order to correctly @@ -139,3 +169,174 @@ method_name_from_physname (const char *physname) xfree (demangled_name); return ret; } + +/* This allocates a new using_direct structure initialized to contain + NAME, OUTER_LENGTH, and INNER_LENGTH, and puts it at the beginning + of the linked list given by NEXT. It returns the resulting struct + using_direct_node. All memory is allocated using OBSTACK. */ + +struct using_direct_node * +cp_add_using_obstack (const char *name, + unsigned short outer_length, + unsigned short inner_length, + struct using_direct_node *next, + struct obstack *obstack) +{ + struct using_direct *current + = obstack_alloc (obstack, sizeof (struct using_direct)); + struct using_direct_node *retval + = obstack_alloc (obstack, sizeof (struct using_direct_node)); + + gdb_assert (outer_length < inner_length); + + current->name = name; + current->outer_length = outer_length; + current->inner_length = inner_length; + retval->current = current; + retval->next = next; + + return retval; +} + +/* Same as cp_add_using, except that it uses xmalloc instead of + obstacks. */ + +struct using_direct_node * +cp_add_using_xmalloc (const char *name, + unsigned short outer_length, + unsigned short inner_length, + struct using_direct_node *next) +{ + struct using_direct *current = xmalloc (sizeof (struct using_direct)); + struct using_direct_node *retval + = xmalloc (sizeof (struct using_direct_node)); + + gdb_assert (outer_length < inner_length); + + current->name = name; + current->outer_length = outer_length; + current->inner_length = inner_length; + retval->current = current; + retval->next = next; + + return retval; +} + +/* This copies the using_direct_nodes in TOCOPY, using xmalloc, and + sticks them onto a list ending in TAIL. (It doesn't copy the + using_directs, just the using_direct_nodes.) */ + +struct using_direct_node * +cp_copy_usings (struct using_direct_node *tocopy, + struct using_direct_node *tail) +{ + struct using_direct_node *new_node; + + if (tocopy == NULL) + return tail; + + new_node = xmalloc (sizeof (struct using_direct_node)); + new_node->current = tocopy->current; + new_node->next = cp_copy_usings (tocopy->next, tail); + + return new_node; +} + +/* This xfree's all the using_direct_nodes in USING (but not their + using_directs!) */ +void +cp_free_usings (struct using_direct_node *using) +{ + struct using_direct_node *next; + + if (using != NULL) + { + for (next = using->next; next; + using = next, next = next->next) + xfree (using); + + xfree (using); + } +} + + +/* This returns the first component of NAME, which should be the + demangled name of a C++ variable/function/method/etc. + Specifically, it returns a pointer to the first colon forming the + boundary of the first component: so, given 'A::foo' or 'A::B::foo' + it returns a pointer to the first :, and given 'foo', it returns a + pointer to the trailing '\0'. */ + +/* Well, that's what it should do when called externally, but to make + the recursion easier, it also stops if it reaches an unexpected ')' + or '>'. */ + +/* Let's optimize away calls to strlen("operator"). */ + +#define LENGTH_OF_OPERATOR 8 + +const char * +cp_find_first_component (const char *name) +{ + /* Names like 'operator<<' screw up the recursion, so let's + special-case them. I _hope_ they can only occur at the start of + a component. */ + + if (strncmp (name, "operator", LENGTH_OF_OPERATOR) == 0) + { + name += LENGTH_OF_OPERATOR; + switch (*name) + { + case '<': + if (name[1] == '<') + name += 2; + else + name += 1; + break; + case '>': + case '-': + if (name[1] == '>') + name +=2; + else + name += 1; + break; + case '(': + name += 2; + break; + default: + name += 1; + break; + } + } + + for (;; ++name) + { + switch (*name) + { + case '<': + /* Template; eat it up. The calls to cp_first_component + should only return (I hope!) when they reach the '>' + terminating the component or a '::' between two + components. (Hence the '+ 2'.) */ + for (name = cp_find_first_component (name + 1); + *name != '>'; + name = cp_find_first_component (name + 2)) + gdb_assert (*name == ':'); + break; + case '(': + /* Similar comment as to '<'. */ + for (name = cp_find_first_component (name + 1); + *name != ')'; + name = cp_find_first_component (name + 2)) + gdb_assert (*name == ':'); + break; + case '>': + case ')': + case '\0': + case ':': + return name; + default: + break; + } + } +} diff --git a/gdb/cp-support.h b/gdb/cp-support.h index a7d333f..bb89c6f 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -20,6 +20,69 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* Opaque declarations. */ + +struct obstack; + extern char *class_name_from_physname (const char *physname); extern char *method_name_from_physname (const char *physname); + +extern const char *cp_find_first_component (const char *name); + +/* This is a struct to store data from "using directives" and similar + language constructs. NAME is a pointer to a string; its initial + substrings of length OUTER_LENGTH and INNER_LENGTH should both be + fully-qualified namespace names. (And OUTER_LENGTH should be + strictly less than INNER_LENGTH). The meaning is that names in the + inner namespace should be imported into outer. + + For example, if it is used to represent the directive "using + namespace std;" then NAME should start with "std", INNER_LENGTH + should be 0, and OUTER_LENGTH should be "3". For a more + complicated example, if there is an anonymous namespace with a + named namespace A, then NAME should start with "A::(anonymous + namespace)", INNER_LENGTH should be 1, and OUTER_LENGTH should be + strlen ("A::(anonymous namespace)"). */ + +/* FIXME: carlton/2002-10-07: That anonymous namespace example isn't + that great, since it really depends not only on what the + demangler's output is but also on the fact that the demangler's + output doesn't depend on the name of the file in question. Which, + alas, it doesn't, but should, leaving us with no way to distinguish + between anonymous namespaces in different files. Sigh... */ + +struct using_direct +{ + const char *name; + unsigned short outer_length; + unsigned short inner_length; +}; + +/* This is a struct for a linked list of using_direct's. */ + +struct using_direct_node +{ + struct using_direct *current; + struct using_direct_node *next; +}; + +extern struct +using_direct_node *cp_add_using_obstack (const char *name, + unsigned short outer_length, + unsigned short inner_length, + struct using_direct_node *next, + struct obstack *obstack); + +extern +struct using_direct_node *cp_add_using_xmalloc (const char *name, + unsigned short outer_length, + unsigned short inner_length, + struct using_direct_node + *next); + +extern +struct using_direct_node *cp_copy_usings (struct using_direct_node *tocopy, + struct using_direct_node *tail); + +extern void cp_free_usings (struct using_direct_node *using); diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index b62b028..84a8bbb 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -367,6 +367,13 @@ static struct partial_die_info zeroed_partial_die; in buildsym.c. */ static struct pending **list_in_scope = &file_symbols; +/* If we're debugging C++ code, this string should contain the name of + the current namespace. Other people shouldn't have to copy it when + referring to it, so don't free its previous contents when setting + this to a new value. */ + +static const char *current_namespace; + /* FIXME: decode_locdesc sets these variables to describe the location to the caller. These ought to be a structure or something. If none of the flags are set, the object lives at the address returned @@ -816,6 +823,9 @@ static void read_structure_scope (struct die_info *, struct objfile *, static void read_common_block (struct die_info *, struct objfile *, const struct comp_unit_head *); +static void read_namespace (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header); + static void read_enumeration (struct die_info *, struct objfile *, const struct comp_unit_head *); @@ -859,6 +869,10 @@ static void process_die (struct die_info *, struct objfile *, static char *dwarf2_linkage_name (struct die_info *); +static char *dwarf2_name (struct die_info *); + +static struct die_info *dwarf2_extension (struct die_info *die); + static char *dwarf_tag_name (unsigned int); static char *dwarf_attr_name (unsigned int); @@ -1301,6 +1315,11 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, int nesting_level = 1; + /* What level do we consider to be file scope? This is normally 1, + but can get pushed up by DW_TAG_namespace entries. */ + + int file_scope_level = 1; + *lowpc = ((CORE_ADDR) -1); *highpc = ((CORE_ADDR) 0); @@ -1323,7 +1342,7 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, { *highpc = pdi.highpc; } - if ((pdi.is_external || nesting_level == 1) + if ((pdi.is_external || nesting_level == file_scope_level) && !pdi.is_declaration) { add_partial_symbol (&pdi, objfile, cu_header); @@ -1336,7 +1355,7 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, case DW_TAG_structure_type: case DW_TAG_union_type: case DW_TAG_enumeration_type: - if ((pdi.is_external || nesting_level == 1) + if ((pdi.is_external || nesting_level == file_scope_level) && !pdi.is_declaration) { add_partial_symbol (&pdi, objfile, cu_header); @@ -1345,37 +1364,51 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile, case DW_TAG_enumerator: /* File scope enumerators are added to the partial symbol table. */ - if (nesting_level == 2) + if (nesting_level == file_scope_level + 1) add_partial_symbol (&pdi, objfile, cu_header); break; case DW_TAG_base_type: /* File scope base type definitions are added to the partial symbol table. */ - if (nesting_level == 1) + if (nesting_level == file_scope_level) 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++; default: break; } } - /* If the die has a sibling, skip to the sibling. - Do not skip enumeration types, we want to record their - enumerators. */ - if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type) + /* 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 the optional DW_AT_sibling attribute - is missing. */ + /* 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--; } } @@ -1550,6 +1583,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) cu_header_offset = offset; info_ptr = dwarf_info_buffer + offset; + /* We're in the global namespace. */ + current_namespace = ""; + obstack_init (&dwarf2_tmp_obstack); back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL); @@ -1675,6 +1711,21 @@ process_die (struct die_info *die, struct objfile *objfile, break; case DW_TAG_common_inclusion: break; + case DW_TAG_namespace: + processing_has_namespace_info = 1; + read_namespace (die, objfile, cu_header); + break; + case DW_TAG_imported_declaration: + case DW_TAG_imported_module: + /* FIXME: carlton/2002-10-16: Eventually, we should use the + information contained in these. DW_TAG_imported_declaration + dies shouldn't have children; DW_TAG_imported_module dies + shouldn't in the C++ case, but conceivably could in the + Fortran case, so we'll have to replace this gdb_assert if + Fortran compilers start generating that info. */ + processing_has_namespace_info = 1; + gdb_assert (!die->has_children); + break; default: new_symbol (die, NULL, objfile, cu_header); break; @@ -2890,6 +2941,66 @@ read_common_block (struct die_info *die, struct objfile *objfile, } } +/* Read a C++ namespace. */ + +/* FIXME: carlton/2002-10-16: For now, we don't actually do anything + useful with the namespace data: we just process its children. */ + +static void +read_namespace (struct die_info *die, struct objfile *objfile, + const struct comp_unit_head *cu_header) +{ + const char *previous_namespace = current_namespace; + const char *name = NULL; + int is_anonymous; + struct die_info *current_die; + + /* Loop through the extensions until we find a name. */ + + for (current_die = die; current_die != NULL; + current_die = dwarf2_extension (die)) + { + name = dwarf2_name (die); + if (name != NULL) + break; + } + + /* Is it an anonymous namespace? */ + + is_anonymous = (name == NULL); + if (is_anonymous) + name = "(anonymous namespace)"; + + /* Now build the name of the current namespace. */ + + current_namespace = obconcat (&objfile->symbol_obstack, + previous_namespace, + previous_namespace[0] == '\0' ? "" : "::", + name); + + /* If it's an anonymous namespace that we're seeing for the first + time, add a using directive. */ + + if (is_anonymous && dwarf_attr (die, DW_AT_extension) == NULL) + add_using_directive (current_namespace, + strlen (previous_namespace), + strlen (current_namespace)); + + + if (die->has_children) + { + struct die_info *child_die = die->next; + + while (child_die && child_die->tag) + { + process_die (child_die, objfile, cu_header); + child_die = sibling_die (child_die); + } + } + + current_namespace = previous_namespace; +} + /* Extract all information from a DW_TAG_pointer_type DIE and add to the user defined type vector. */ @@ -5326,6 +5437,43 @@ dwarf2_linkage_name (struct die_info *die) return NULL; } +/* Get name of a die, return NULL if not found. */ + +static char * +dwarf2_name (struct die_info *die) +{ + struct attribute *attr; + + attr = dwarf_attr (die, DW_AT_name); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); + return NULL; +} + +/* Return the die that this die in an extension of, or NULL if there + is none. */ + +static struct die_info * +dwarf2_extension (struct die_info *die) +{ + struct attribute *attr; + struct die_info *extension_die; + unsigned int ref; + + attr = dwarf_attr (die, DW_AT_extension); + if (attr == NULL) + return NULL; + + ref = dwarf2_get_ref_die_offset (attr); + extension_die = follow_die_ref (ref); + if (!extension_die) + { + error ("Dwarf Error: Cannot find referent at offset %d.", ref); + } + + return extension_die; +} + /* Convert a DIE tag into its string name. */ static char * @@ -5429,6 +5577,22 @@ dwarf_tag_name (register unsigned tag) return "DW_TAG_variable"; case DW_TAG_volatile_type: return "DW_TAG_volatile_type"; + case DW_TAG_dwarf_procedure: + return "DW_TAG_dwarf_procedure"; + case DW_TAG_restrict_type: + return "DW_TAG_restrict_type"; + case DW_TAG_interface_type: + return "DW_TAG_interface_type"; + case DW_TAG_namespace: + return "DW_TAG_namespace"; + case DW_TAG_imported_module: + return "DW_TAG_imported_module"; + case DW_TAG_unspecified_type: + return "DW_TAG_unspecified_type"; + case DW_TAG_partial_unit: + return "DW_TAG_partial_unit"; + case DW_TAG_imported_unit: + return "DW_TAG_imported_unit"; case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop"; case DW_TAG_format_label: @@ -5573,7 +5737,30 @@ dwarf_attr_name (register unsigned attr) return "DW_AT_virtuality"; case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location"; - + case DW_AT_allocated: + return "DW_AT_allocated"; + case DW_AT_associated: + return "DW_AT_associated"; + case DW_AT_data_location: + return "DW_AT_data_location"; + case DW_AT_stride: + return "DW_AT_stride"; + case DW_AT_entry_pc: + return "DW_AT_entry_pc"; + case DW_AT_use_UTF8: + return "DW_AT_use_UTF8"; + case DW_AT_extension: + return "DW_AT_extension"; + case DW_AT_ranges: + return "DW_AT_ranges"; + case DW_AT_trampoline: + return "DW_AT_trampoline"; + case DW_AT_call_column: + return "DW_AT_call_column"; + case DW_AT_call_file: + return "DW_AT_call_file"; + case DW_AT_call_line: + return "DW_AT_call_line"; #ifdef MIPS case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; @@ -6010,6 +6197,8 @@ dwarf_type_encoding_name (register unsigned enc) return "DW_ATE_unsigned"; case DW_ATE_unsigned_char: return "DW_ATE_unsigned_char"; + case DW_ATE_imaginary_float: + return "DW_ATE_imaginary_float"; default: return "DW_ATE_<unknown>"; } diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c index 3afdebd..03bf565 100644 --- a/gdb/jv-lang.c +++ b/gdb/jv-lang.c @@ -111,6 +111,7 @@ get_java_class_symtab (void) BLOCK_END (bl) = 0; BLOCK_FUNCTION (bl) = NULL; BLOCK_SUPERBLOCK (bl) = NULL; + BLOCK_USING (bl) = NULL; BLOCK_GCC_COMPILED (bl) = 0; BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; diff --git a/gdb/symfile.c b/gdb/symfile.c index 66bbf71..ae0578d 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -299,16 +299,16 @@ sort_symtab_syms (register struct symtab *s) may be part of a larger string and we are only saving a substring. */ char * -obsavestring (char *ptr, int size, struct obstack *obstackp) +obsavestring (const char *ptr, int size, struct obstack *obstackp) { register char *p = (char *) obstack_alloc (obstackp, size + 1); /* Open-coded memcpy--saves function call time. These strings are usually short. FIXME: Is this really still true with a compiler that can inline memcpy? */ { - register char *p1 = ptr; + register const char *p1 = ptr; register char *p2 = p; - char *end = ptr + size; + const char *end = ptr + size; while (p1 != end) *p2++ = *p1++; } diff --git a/gdb/symfile.h b/gdb/symfile.h index 39eb308..62dfcef 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -25,6 +25,10 @@ /* This file requires that you first include "bfd.h". */ +/* Opaque declarations. */ + +struct obstack; + /* Partial symbols are stored in the psymbol_cache and pointers to them are kept in a dynamically grown array that is obtained from malloc and grown as necessary via realloc. Each objfile typically has two of these, @@ -208,7 +212,7 @@ extern void sort_symtab_syms (struct symtab *); (and add a null character at the end in the copy). Returns the address of the copy. */ -extern char *obsavestring (char *, int, struct obstack *); +extern char *obsavestring (const char *, int, struct obstack *); /* Concatenate strings S1, S2 and S3; return the new string. Space is found in the symbol_obstack. */ diff --git a/gdb/symtab.c b/gdb/symtab.c index 9227fe7..8e76be8 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -49,6 +49,7 @@ #include "gdb_stat.h" #include <ctype.h> #include "cp-abi.h" +#include "cp-support.h" /* Prototype for one function in parser-defs.h, instead of including that entire file. */ @@ -95,6 +96,13 @@ static struct symbol *lookup_symbol_aux_local (const char *name, struct symtab **symtab); static +struct symbol *lookup_symbol_aux_nonlocal (int block_index, + const char *name, + const char *mangled_name, + const namespace_enum namespace, + struct symtab **symtab); + +static struct symbol *lookup_symbol_aux_symtabs (int block_index, const char *name, const char *mangled_name, @@ -107,6 +115,23 @@ struct symbol *lookup_symbol_aux_psymtabs (int block_index, const char *mangled_name, const namespace_enum namespace, struct symtab **symtab); + +static +struct symbol *lookup_symbol_aux_using (const char *name, + const char *mangled_name, + const struct block *block, + const namespace_enum namespace, + struct symtab **symtab); + +static +struct symbol *lookup_symbol_aux_using_loop (const char *prefix, + int prefix_len, + const char *rest, + struct using_direct_node *using, + const char *mangled_name, + namespace_enum namespace, + struct symtab **symtab); + static struct symbol *lookup_symbol_aux_minsyms (const char *name, const char *mangled_name, @@ -785,16 +810,27 @@ lookup_symbol_aux (const char *name, const char *mangled_name, of the desired name as a global, then do psymtab-to-symtab conversion on the fly and return the found symbol. */ - sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, mangled_name, - namespace, symtab); - if (sym != NULL) - return sym; - - sym = lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, mangled_name, + sym = lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, name, mangled_name, namespace, symtab); if (sym != NULL) return sym; + /* If we're in the C++ case, check to see if the symbol is defined + in a namespace accessible via a "using" declaration. */ + + /* FIXME: carlton/2002-10-10: is "is_a_field_of_this" always + non-NULL if we're in the C++ case? Maybe we should always do + this, and delete the two previous searches: this will always + search the global namespace, after all. */ + + if (is_a_field_of_this) + { + sym = lookup_symbol_aux_using (name, mangled_name, block, namespace, + symtab); + if (sym != NULL) + return sym; + } + #ifndef HPUXHPPA /* Check for the possibility of the symbol being a function or a @@ -816,17 +852,11 @@ lookup_symbol_aux (const char *name, const char *mangled_name, desired name as a file-level static, then do psymtab-to-symtab conversion on the fly and return the found symbol. */ - sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, mangled_name, - namespace, symtab); - if (sym != NULL) - return sym; - - sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, mangled_name, + sym = lookup_symbol_aux_nonlocal (STATIC_BLOCK, name, mangled_name, namespace, symtab); if (sym != NULL) return sym; - #ifdef HPUXHPPA /* Check for the possibility of the symbol being a function or a @@ -903,6 +933,32 @@ lookup_symbol_aux_local (const char *name, const char *mangled_name, return NULL; } +/* Check to see if the symbol is defined in one of the symtabs or + psymtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or + STATIC_BLOCK, depending on whether or not we want to search global + symbols or static symbols. */ + +/* FIXME: carlton/2002-10-11: Should this also do some minsym + lookup? */ + +static struct symbol * +lookup_symbol_aux_nonlocal (int block_index, + const char *name, + const char *mangled_name, + const namespace_enum namespace, + struct symtab **symtab) +{ + struct symbol *sym; + + sym = lookup_symbol_aux_symtabs (block_index, name, mangled_name, + namespace, symtab); + if (sym != NULL) + return sym; + + return lookup_symbol_aux_psymtabs (block_index, name, mangled_name, + namespace, symtab); +} + /* Check to see if the symbol is defined in one of the symtabs. BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK, depending on whether or not we want to search global symbols or @@ -996,6 +1052,134 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name, return NULL; } +/* This function gathers using directives from BLOCK and its + superblocks, and then searches for symbols in the global namespace + by trying to apply those various using directives. */ +static struct symbol *lookup_symbol_aux_using (const char *name, + const char *mangled_name, + const struct block *block, + const namespace_enum namespace, + struct symtab **symtab) +{ + struct using_direct_node *using = NULL; + struct symbol *sym; + + while (block != NULL) + { + using = cp_copy_usings (BLOCK_USING (block), using); + block = BLOCK_SUPERBLOCK (block); + } + + sym = lookup_symbol_aux_using_loop ("", 0, name, using, mangled_name, + namespace, symtab); + cp_free_usings (using); + + return sym; +} + +/* This tries to look up REST in the namespace given by the initial + substring of PREFIX of length PREFIX_LEN. + + Basically, assume that we have using directives adding A to the + global namespace, adding A::inner to namespace A, and adding B to + the global namespace. Then, when looking up a symbol "foo", we + want to recurse by looking up stuff in A::foo and seeing which + using directives still apply. The only one that still applies + converts that to A::inner::foo: we _don't_ want to then look at + B::A::foo (let alone A::A::foo!). So we end up just looking at + A::foo, A::inner::foo, and B::foo. (Though if the original caller + to lookup_symbol had specified A::foo, we would want to look up + stuff in A::A::foo, A::inner::A::foo, A::inner::foo, and + B::A::foo). */ + +/* FIXME: carlton/2002-10-11: There are still some places where this + will return false positives. For example, if you have namespaces + C, C::D, C::E, and C::D::E, then, from a function defined in C::D, + all references to variables E::var _should_ be treated as + C::D::E::var, but this function will also see variables in + C::E::var. I don't think this can be fixed without making + namespaces first-class objects. (Which is certainly a good idea + for other reasons, but it will take a little while.) */ + +static struct symbol * +lookup_symbol_aux_using_loop (const char *prefix, + int prefix_len, + const char *rest, + struct using_direct_node *using, + const char *mangled_name, + namespace_enum namespace, + struct symtab **symtab) +{ + struct using_direct_node *current; + struct symbol *sym; + + for (current = using; current; current = current->next) + { + /* First, see if the prefix matches the start of this using + directive. */ + if (prefix_len <= current->current->outer_length + && strncmp (prefix, current->current->name, prefix_len) == 0) + { + /* Great, it matches: now does the rest of the using + directive match the rest of the name? */ + + const char *rest_of_outer = current->current->name + prefix_len; + int rest_of_outer_len + = current->current->outer_length - prefix_len; + /* Should we skip some colons? Should be true unless + PREFIX_LEN is zero (and hence we're in the global + namespace) or we've finished all of outer. */ + if (rest_of_outer_len != 0 && *rest_of_outer == ':') + { + rest_of_outer += 2; + rest_of_outer_len -= 2; + } + if (strncmp (rest_of_outer, rest, rest_of_outer_len) == 0) + { + /* Everything matches! Yippee! So apply the using + directive and recurse. */ + const char *new_rest = rest + rest_of_outer_len; + if (*new_rest == ':') + new_rest += 2; + + sym = lookup_symbol_aux_using_loop + (current->current->name, + current->current->inner_length, + new_rest, + using, + mangled_name, + namespace, + symtab); + if (sym != NULL) + return sym; + } + } + } + + /* We didn't find anything by applying any of the using directives + that are still applicable; so let's see if we've got a match + using the current name. */ + + if (prefix_len == 0) + { + return lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, rest, mangled_name, + namespace, symtab); + } + else + { + char *concatenated_name + = xmalloc (prefix_len + 2 + strlen (rest) + 1); + strncpy (concatenated_name, prefix, prefix_len); + strcpy (concatenated_name + prefix_len, "::"); + strcpy (concatenated_name + prefix_len + 2, rest); + sym = lookup_symbol_aux_nonlocal (GLOBAL_BLOCK, concatenated_name, + mangled_name, namespace, symtab); + + xfree (concatenated_name); + return sym; + } +} + /* Check for the possibility of the symbol being a function or a mangled variable that is stored in one of the minimal symbol tables. Eventually, all global symbols might be resolved in this diff --git a/gdb/symtab.h b/gdb/symtab.h index a78607d..9aca9c1 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -25,6 +25,7 @@ /* Opaque declarations. */ struct obstack; +struct using_direct_node; /* Don't do this; it means that if some .o's are compiled with GNU C and some are not (easy to do accidentally the way we configure @@ -373,6 +374,23 @@ struct block struct block *superblock; + /* Used for language-specific info. */ + + union + { + struct + { + /* Contains information about what using directives or other + similar features are added by this block. This should always + be NULL for global blocks: if there are using directives that + affect an entire file, put it in the static block. */ + + struct using_direct_node *using; + } + cplus_specific; + } + language_specific; + /* Version of GCC used to compile the function corresponding to this block, or 0 if not compiled with GCC. When possible, GCC should be compatible with the native compiler, or if that @@ -418,6 +436,7 @@ struct block #define BLOCK_END(bl) (bl)->endaddr #define BLOCK_FUNCTION(bl) (bl)->function #define BLOCK_SUPERBLOCK(bl) (bl)->superblock +#define BLOCK_USING(bl) (bl)->language_specific.cplus_specific.using #define BLOCK_GCC_COMPILED(bl) (bl)->gcc_compile_flag #define BLOCK_HASHTABLE(bl) (bl)->hashtable diff --git a/gdb/testsuite/ChangeLog.cplus b/gdb/testsuite/ChangeLog.cplus new file mode 100644 index 0000000..3436b73 --- /dev/null +++ b/gdb/testsuite/ChangeLog.cplus @@ -0,0 +1,6 @@ +2002-10-22 David Carlton <carlton@math.stanford.edu> + + * gdb.c++/namespace.exp: Add tests involving namespaces + starting from C. + * gdb.c++/namespace.cc: Add namespaces with names starting + from C and their contents. diff --git a/gdb/testsuite/gdb.c++/namespace.cc b/gdb/testsuite/gdb.c++/namespace.cc index 7667266..6298b91 100644 --- a/gdb/testsuite/gdb.c++/namespace.cc +++ b/gdb/testsuite/gdb.c++/namespace.cc @@ -68,6 +68,148 @@ void marker1(void) return; } +namespace +{ + int X = 9; + + namespace G + { + int Xg = 10; + + namespace + { + int XgX = 11; + } + } +} + +namespace H +{ + int h = 14; +} + +namespace I = H; + +namespace J +{ + int j = 15; +} + +using namespace J; + +namespace K +{ + int k = 16; +} + +namespace L +{ + using namespace K; +} + +namespace O +{ + int o = 18; +} + +namespace P +{ + using namespace O; +} + +namespace Q +{ + using namespace P; +} + +namespace R +{ + int r1 = 19; + int r2 = 20; +} + +using R::r1; + +namespace C +{ + int c = 1; + int shadow = 12; + + namespace + { + int cX = 6; + + namespace F + { + int cXf = 7; + + namespace + { + int cXfX = 8; + } + } + } + + namespace C + { + int cc = 2; + } + + namespace E + { + int ce = 4; + } + + namespace D + { + int cd = 3; + int shadow = 13; + + namespace E + { + int cde = 5; + } + + namespace M + { + int cdm = 17; + } + + using namespace M; + + void marker2 (void) + { + // NOTE: carlton/2002-10-11: I'm listing the expressions that I + // plan to have GDB try to print out, just to make sure that the + // compiler and I agree which ones should be legal! It's easy + // to screw up when testing the boundaries of namespace stuff. + c; + //cc; + C::cc; + cd; + E::cde; + shadow; + //E::ce; + cX; + F::cXf; + F::cXfX; + X; + G::Xg; + G::XgX; + I::h; + j; + L::k; + //k; + cdm; + Q::o; + //o; + r1; + //r2; + return; + } + + } +} int main () { @@ -94,10 +236,6 @@ int main () c1 = cl.xyzq('e'); marker1(); - -} - - - - + C::D::marker2 (); +} diff --git a/gdb/testsuite/gdb.c++/namespace.exp b/gdb/testsuite/gdb.c++/namespace.exp index 3e502c4..ebe845e 100644 --- a/gdb/testsuite/gdb.c++/namespace.exp +++ b/gdb/testsuite/gdb.c++/namespace.exp @@ -186,3 +186,71 @@ gdb_expect { timeout { fail "(timeout) break BBB::Class::xyzq" } } +# Test to see if the appropriate namespaces are in scope when trying +# to print out stuff from within a function defined within a +# namespace. + +if ![runto "'C::D::marker2'"] then { + perror "couldn't run to marker2" + continue +} + +gdb_test "print c" "\\$\[0-9\].* = 1" "print c" +gdb_test "print cc" "No symbol \"cc\" in current context." "print cc" +gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2" "print C::cc" +gdb_test "print cd" "\\$\[0-9\].* = 3" "print cd" +gdb_test "print 'C::D::cd'" "\\$\[0-9\].* = 3" "print C::D::cd" +gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5" "print E::cde" + +# FIXME: carlton/2002-10-17: It's somewhat accidental that we +# currently get this one right. (Delete this comment once namespace +# scope issues have been handled correctly!) + +gdb_test "print shadow" "\\$\[0-9\].* = 13" "print shadow" + + +# NOTE: carlton/2002-10-17: This one won't get fixed until namespaces +# are first-class objects. + +setup_xfail "*-*-*" +gdb_test "print 'E::ce'" "No symbol \"E::ce\" in current context." "print E::ce" + +# Some anonymous namespace tests. + +gdb_test "print cX" "\\$\[0-9\].* = 6" "print cX" +gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7" "print F::cXf" +gdb_test "print 'F::cXfX'" "\\$\[0-9\].* = 8" "print F::cXfX" +gdb_test "print X" "\\$\[0-9\].* = 9" "print X" +gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10" "print G::Xg" +gdb_test "print 'G::XgX'" "\\$\[0-9\].* = 11" "print G::XgX" + +# Test namespace renaming. + +setup_xfail "*-*-*" +gdb_test "print 'I::h'" "\\$\[0-9\].* = 14" "print I::h" + +# Test using directives. + +# NOTE: carlton/2002-10-17: Some of these are easy, but some of these +# have unfortunate interactions with namespace scope issues. As of +# this writing, some of these pass, but they pass for the wrong reasons. + +setup_xfail "*-*-*" +gdb_test "print j" "\\$\[0-9\].* = 15" "print j" +setup_xfail "*-*-*" +gdb_test "print 'L::k'" "\\$\[0-9\].* = 16" "print L::k" +setup_xfail "*-*-*" +gdb_test "print k" "No symbol \"k\" in current context." "print k" +setup_xfail "*-*-*" +gdb_test "print cdm" "\\$\[0-9\].* = 17" "print cdm" +setup_xfail "*-*-*" +gdb_test "print 'Q::o'" "\\$\[0-9\].* = 18" "print Q::o" +setup_xfail "*-*-*" +gdb_test "print o" "No symbol \"o\" in current context." "print o" + +# Test using declarations. I should probably test these more. + +setup_xfail "*-*-*" +gdb_test "print r1" "\\$\[0-9\].* = 19" "print r1" +setup_xfail "*-*-*" +gdb_test "print r2" "No symbol \"r2\" in current context." "print r2" |