[drow-cplus-branch rfa] using directives support

David Carlton
2002-10-22T00:10:12Z

Here's some code to add support in GDB for using directives; it uses
this to look up names from within functions defined in namespaces and
for anonymous namespaces. In the latter case, it uses DWARF 2 (DWARF
3, actually) debugging info if its there; if not, it tries to deduce
it on its own.

It contains the code in
<http://sources.redhat.com/ml/gdb-patches/2002-10/msg00240.html>; I'm
including that because some of the relevant bits have changed (a few
bugs in the lookup_symbol stuff that I didn't find until multiple
using directives were in affect, and because struct using_direct has
changed a bit. Unfortunately, it's not done changing yet - the more I
understand the name lookup rules from the C++ Standard, the more of
the mess it looks like. So there are some bugs that I know about
involving in the way namespaces are handled in this code (basically, I
try to fake "namespace scope" by adding a bunch of using directives),
but it's a reasonable first start. Not ready for mainline, though.

The modifications to the dwarf2read.c might be useful for you when
you're trying to get classes located in the correct namespace.

I've tested this by doing make check with a standard GCC and with a
GCC that has been modified by first applying the patch in
<http://sources.redhat.com/ml/gdb/2002-08/msg00312.html> and then
applying the following patch:

--- dwarf2out.c-danielb Fri Oct 18 11:39:46 2002
+++ dwarf2out.c Fri Oct 18 11:38:46 2002
@@ -11453,7 +11453,11 @@ gen_namespace_die (decl, context_die)
{
/* Output a real namespace */
dw_die_ref namespace_die = new_die (DW_TAG_namespace, context_die, decl);
- add_name_and_src_coords_attributes (namespace_die, decl);
+ /* Anonymous namespaces shouldn't have a DW_AT_name. */
+ if (strncmp (dwarf2_name (decl, 0), "_GLOBAL__N", 10) == 0)
+ add_src_coords_attributes (namespace_die, decl);
+ else
+ add_name_and_src_coords_attributes (namespace_die, decl);
equate_decl_number_to_die (decl, namespace_die);
}
else

It works both ways.

Tell me what you think. I realize that this is pretty large; I
promise that I won't submit another patch for approval to the branch
until this one (or a variant of it) has been approved, to cut down on
the sizes of future patches...

David Carlton
carlton@math.stanford.edu

2002-10-21 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>

* 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.

Index: buildsym.c
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.c,v
retrieving revision 1.20
diff -u -p -r1.20 buildsym.c
--- buildsym.c 10 Sep 2002 23:45:26 -0000 1.20
+++ buildsym.c 21 Oct 2002 23:23:15 -0000
@@ -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;
+
\f
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);
\f

/* 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 *symbo
}

(*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 *lis
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, str
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, str
}
}
}
+
+ /* 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,
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 o
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
@@ -1068,6 +1196,32 @@ end_symtab (CORE_ADDR end_addr, struct o
pending_macros = NULL;

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
Index: buildsym.h
===================================================================
RCS file: /cvs/src/src/gdb/buildsym.h,v
retrieving revision 1.5
diff -u -p -r1.5 buildsym.h
--- buildsym.h 21 Aug 2002 00:57:42 -0000 1.5
+++ buildsym.h 21 Oct 2002 23:23:15 -0000
@@ -93,6 +93,12 @@ EXTERN unsigned char processing_acc_comp

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;
@@ -239,6 +245,9 @@ extern void add_symbol_to_list (struct s

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,
Index: cp-support.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.c,v
retrieving revision 1.1
diff -u -p -r1.1 cp-support.c
--- cp-support.c 14 Sep 2002 02:09:39 -0000 1.1
+++ cp-support.c 21 Oct 2002 23:23:15 -0000
@@ -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
@@ -138,4 +168,175 @@ method_name_from_physname (const char *p

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;
+ }
+ }
}
Index: cp-support.h
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.h,v
retrieving revision 1.1
diff -u -p -r1.1 cp-support.h
--- cp-support.h 14 Sep 2002 02:09:39 -0000 1.1
+++ cp-support.h 21 Oct 2002 23:23:15 -0000
@@ -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);
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.67
diff -u -p -r1.67 dwarf2read.c
--- dwarf2read.c 1 Oct 2002 23:51:43 -0000 1.67
+++ dwarf2read.c 21 Oct 2002 23:45:21 -0000
@@ -367,6 +367,13 @@ static struct partial_die_info zeroed_pa
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
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

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, st

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, st
{
*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, st
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, st
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_symt
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, struc
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,
}
}

+/* 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 *di
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 unsig
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>";
}
Index: jv-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/jv-lang.c,v
retrieving revision 1.12
diff -u -p -r1.12 jv-lang.c
--- jv-lang.c 11 Jul 2002 20:46:19 -0000 1.12
+++ jv-lang.c 21 Oct 2002 23:23:16 -0000
@@ -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;

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.268
diff -u -p -r1.268 Makefile.in
--- Makefile.in 2 Oct 2002 21:33:58 -0000 1.268
+++ Makefile.in 21 Oct 2002 23:23:15 -0000
@@ -1541,7 +1541,7 @@ buildsym.o: buildsym.c $(defs_h) $(bfd_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_str
$(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)
$(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)
Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.69
diff -u -p -r1.69 symfile.c
--- symfile.c 20 Sep 2002 14:58:58 -0000 1.69
+++ symfile.c 21 Oct 2002 23:23:16 -0000
@@ -299,16 +299,16 @@ sort_symtab_syms (register struct symtab
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++;
}
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.13
diff -u -p -r1.13 symfile.h
--- symfile.h 22 Apr 2002 10:19:04 -0000 1.13
+++ symfile.h 21 Oct 2002 23:23:16 -0000
@@ -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 sym
(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. */
Index: symtab.c
===================================================================
RCS file: /cvs/src/src/gdb/symtab.c,v
retrieving revision 1.70.4.1
diff -u -p -r1.70.4.1 symtab.c
--- symtab.c 11 Oct 2002 16:20:45 -0000 1.70.4.1
+++ symtab.c 21 Oct 2002 23:23:17 -0000
@@ -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_
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_psymtab
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, con
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, con
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 *nam
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
@@ -994,6 +1050,134 @@ lookup_symbol_aux_psymtabs (int block_in
}

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
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gdb/symtab.h,v
retrieving revision 1.42
diff -u -p -r1.42 symtab.h
--- symtab.h 20 Sep 2002 14:58:58 -0000 1.42
+++ symtab.h 21 Oct 2002 23:23:17 -0000
@@ -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

Index: testsuite/gdb.c++/namespace.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.cc,v
retrieving revision 1.1
diff -u -p -r1.1 namespace.cc
--- testsuite/gdb.c++/namespace.cc 12 Jun 2000 01:31:41 -0000 1.1
+++ testsuite/gdb.c++/namespace.cc 21 Oct 2002 23:23:17 -0000
@@ -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 ();
+}
Index: testsuite/gdb.c++/namespace.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/namespace.exp,v
retrieving revision 1.12
diff -u -p -r1.12 namespace.exp
--- testsuite/gdb.c++/namespace.exp 10 Jan 2002 20:46:16 -0000 1.12
+++ testsuite/gdb.c++/namespace.exp 21 Oct 2002 23:23:17 -0000
@@ -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"