aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Carlton <carlton@bactrian.org>2002-10-22 19:59:37 +0000
committerDavid Carlton <carlton@bactrian.org>2002-10-22 19:59:37 +0000
commit2d185a21dfe1493b6f24b73faa4be4b1608f718f (patch)
treefd6414a8ad3efa921ae4b064458ce50d164c92f4
parent58fabab07992522e0e08e42d1c25d119ad78e9b4 (diff)
downloadbinutils-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.cplus59
-rw-r--r--gdb/Makefile.in7
-rw-r--r--gdb/buildsym.c158
-rw-r--r--gdb/buildsym.h9
-rw-r--r--gdb/cp-support.c201
-rw-r--r--gdb/cp-support.h63
-rw-r--r--gdb/dwarf2read.c211
-rw-r--r--gdb/jv-lang.c1
-rw-r--r--gdb/symfile.c6
-rw-r--r--gdb/symfile.h6
-rw-r--r--gdb/symtab.c210
-rw-r--r--gdb/symtab.h19
-rw-r--r--gdb/testsuite/ChangeLog.cplus6
-rw-r--r--gdb/testsuite/gdb.c++/namespace.cc150
-rw-r--r--gdb/testsuite/gdb.c++/namespace.exp68
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"