+2002-10-11 David Carlton <carlton@math.stanford.edu>
+
+ * jv-lang.c (get_java_class_symtab): Initialize BLOCK_USING (bl)
+ to NULL.
+ * cp-support.c: Change all uses of 'struct using_data' and 'struct
+ using_data_node' to 'struct using_direct' and 'struct
+ using_direct_node'.
+ (cp_free_usings): Fix loop.
+ * symtab.c: Ditto.
+ * symtab.h: Ditto
+ * cp-support.h: Delete declarations for commented-out functions.
+ Rename 'struct using_data' and 'struct using_data_node' to 'struct
+ using_direct' and 'struct using_direct_node'.
+ * cp-support.c: Delete commented-out functions.
+
+2002-10-10 David Carlton <carlton@math.stanford.edu>
+
+ * symtab.c (lookup_symbol_aux_using_loop): New function.
+ (lookup_symbol_aux_nonlocal): New function.
+ (lookup_symbol_aux): Call lookup_symbol_aux_nonlocal instead of
+ lookup_symbol_aux_symtabs and lookup_symbol_aux_psymtabs.
+
+ * Makefile.in (symtab.o): Depend on $(cp_support_h).
+
+ * symtab.c: #include "cp-support.h"
+
+ * cp-support.h: Declare cp_copy_usings, cp_free_usings.
+
+ * cp-support.c (cp_free_usings): New function.
+ (cp_copy_usings): New function.
+
+ * symtab.c (lookup_symbol_aux): Call lookup_symbol_aux_using to
+ apply using directives.
+ (lookup_symbol_aux_using): New function.
+
2002-10-09 David Carlton <carlton@math.stanford.edu>
* cp-support.c: Comment out cp_find_last_component and
$(gdbcmd_h) $(call_cmds_h) $(gdb_regex_h) $(expression_h) \
$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) \
$(filenames_h) $(dictionary_h) $(gdb_obstack_h) \
- $(gdb_string_h) $(gdb_stat_h) $(cp_abi_h) $(source_h)
+ $(gdb_string_h) $(gdb_stat_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)
return ret;
}
-#if 0
-
-/* FIXME: carlton/2002-10-09: cp_locate_arguments and
- cp_find_last_component are broken: they don't deal with operator<<
- and the like. Oops. I decided to fix this by starting from the
- front, leading to cp_find_first_component (which may or may not be
- correct...); if I don't find other uses for cp_locate_arguments and
- cp_find_last_component soon, I'll delete them. */
-
-/* Given a name that may or may not be the demangled name of a
- function or method, this returns a pointer to the last character
- that isn't part of the arguments, if there are any. I.e. given a
- pointer to "foo", it returns a pointer to the trailing '\0'; given
- a pointer to "C::foo() const", it returns a pointer to the '('. */
+/* This allocates a new using_direct structure initialized to contain
+ OUTER and INNER, 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. */
-const char *
-cp_locate_arguments (const char *name)
+struct using_direct_node *
+cp_add_using (const char *outer, const char *inner,
+ struct using_direct_node *next,
+ struct obstack *obstack)
{
-/* NOTE: carlton/2002-10-08: we search from the front rather than from
- the back to avoid getting screwed up by the 'const' on the end.
- ARGSOK says when a parenthesis should be the start of the arguments
- to a function: otherwise, we get screwed up by 'A::(anonymous
- namespace)::foo' and its ilk. */
-
- const char *current = name;
- const char *end = name + strlen(name);
- /* The nesting depth. */
- int depth = 0;
- /* Might a parenthesis be the start of arguments? */
- int argsok = 0;
+ struct using_direct *current
+ = obstack_alloc (obstack, sizeof (struct using_direct));
+ struct using_direct_node *retval
+ = obstack_alloc (obstack, sizeof (struct using_direct_node));
- while (current < end)
- {
- switch (*current)
- {
- case '(':
- if (depth == 0 && argsok)
- return current;
- ++depth;
- argsok = 0;
- break;
- case '<':
- ++depth;
- argsok = 0;
- break;
- case ')':
- case '>':
- --depth;
- argsok = 1;
- break;
- case ':':
- argsok = 0;
- break;
- default:
- argsok = 1;
- break;
- }
- ++current;
- }
+ current->outer = outer;
+ current->inner = inner;
+ retval->current = current;
+ retval->next = next;
- return current;
+ return retval;
}
-/* Given pointers FIRST and LAST such that [FIRST,LAST) is a substring
- of a demangled name, not including the arguments (i.e. call
- cp_locate_arguments first!), this returns a pointer to the
- beginning of the end of the last component. For example, given
- either "A::B::C::foo" or "foo", it returns a pointer to 'f'. */
-
-/* FIXME: carlton/2002-10-08: This overlaps dreadfully with
- find_last_component. Sigh. */
-
-const char *
-cp_find_last_component (const char *first, const char *last)
+/* This copies the using_direct_nodes in TOCOPY, using xmalloc, and
+ sticks them onto a list ending in TAIL. */
+struct using_direct_node *
+cp_copy_usings (struct using_direct_node *tocopy,
+ struct using_direct_node *tail)
{
- const char *current;
- int depth;
+ struct using_direct_node *new_node;
+
+ if (tocopy == NULL)
+ return tail;
- for (current = last - 1, depth = 0;
- current >= first;
- --current)
- {
- switch (*current)
- {
- case '(':
- case '<':
- --depth;
- break;
- case ')':
- case '>':
- ++depth;
- break;
- case ':':
- if (depth == 0)
- return current + 1;
- break;
- default:
- break;
- }
- }
+ new_node = xmalloc (sizeof (struct using_direct_node));
+ new_node->current = tocopy->current;
+ new_node->next = cp_copy_usings (tocopy->next, tail);
- return first;
+ return new_node;
}
-#endif /* 0 */
-
-/* This allocates a new using_data structure initialized to contain
- OUTER and INNER, and puts it at the beginning of the linked list
- given by NEXT. It returns the resulting struct using_data_node.
- All memory is allocated using OBSTACK. */
-struct using_data_node *
-cp_add_using (const char *outer, const char *inner,
- struct using_data_node *next,
- struct obstack *obstack)
+/* 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_data *current
- = obstack_alloc (obstack, sizeof (struct using_data));
- struct using_data_node *retval
- = obstack_alloc (obstack, sizeof (struct using_data_node));
+ struct using_direct_node *next;
- current->outer = outer;
- current->inner = inner;
- retval->current = current;
- retval->next = next;
-
- return retval;
+ 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
extern char *method_name_from_physname (const char *physname);
-extern const char *cp_locate_arguments (const char *name);
-
-extern const char *cp_find_last_component (const char *first,
- const char *last);
-
extern const char *cp_find_first_component (const char *name);
/* This is a struct to store data from "using directives" and similar
language constructs. It contains two strings, OUTER and INNER;
- both should be fully-qualified namespace names, OUTER should be an
- initial substring of INNER, and it says that names in the namespace
- INNER should be imported into namespace OUTER. For example, if it
- is used to represent the directive "using namespace std;" then
- INNER should be "std" and new should be "". For a more complicated
- example, if there is an anonymous namespace with a named namespace
- A, then INNER should be "A::(anonymous namespace)" and new should
- be "A". */
+ both should be fully-qualified namespace names, OUTER should be a
+ strict initial substring of INNER, and it says that names in the
+ namespace INNER should be imported into namespace OUTER. For
+ example, if it is used to represent the directive "using namespace
+ std;" then INNER should be "std" and new should be "". For a more
+ complicated example, if there is an anonymous namespace with a
+ named namespace A, then INNER should be "A::(anonymous namespace)"
+ and new should be "A". */
/* FIXME: carlton/2002-10-07: That anonymous namespace example isn't
that great, since it really depends not only on what the
alas, it doesn't, but should, leaving us with no way to distinguish
between anonymous namespaces in different files. Sigh... */
-struct using_data
+struct using_direct
{
const char *outer;
const char *inner;
};
-/* This is a struct for a linked list of using_data's. */
+/* This is a struct for a linked list of using_direct's. */
-struct using_data_node
+struct using_direct_node
{
- struct using_data *current;
- struct using_data_node *next;
+ struct using_direct *current;
+ struct using_direct_node *next;
};
-extern struct using_data_node *cp_add_using (const char *outer,
- const char *inner,
- struct using_data_node *next,
- struct obstack *obstack);
+extern struct using_direct_node *cp_add_using (const char *outer,
+ const char *inner,
+ struct using_direct_node *next,
+ struct obstack *obstack);
+
+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);
BLOCK_SUPERBLOCK (bl) = NULL;
BLOCK_DICT (bl) = dict_create_linear (&objfile->symbol_obstack,
NULL);
+ BLOCK_USING (bl) = NULL;
BLOCK_GCC_COMPILED (bl) = 0;
BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl;
#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. */
const namespace_enum namespace,
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,
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,
+ 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,
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
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
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
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 ("", name, using, mangled_name,
+ namespace, symtab);
+ cp_free_usings (using);
+
+ return sym;
+}
+
+/* This tries to look up a symbol whose name is the concatenation of
+ PREFIX, "::", and REST, where "::" is ommitted if PREFIX is the
+ empty string, applying the various using directives given in USING.
+ When applying the using directives, however, it assumes that the
+ part of the name given by PREFIX is immutable, so it only adds
+ symbols to namespaces whose names contain PREFIX.
+
+ 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).
+
+ The reason why this treates the case of PREFIX = "" specially is to
+ avoid having to create temporary strings with "::" stuck on the end
+ of them. */
+
+/* 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, 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;
+ int prefix_len = strlen (prefix);
+
+ for (current = using; current; current = current->next)
+ {
+ /* First, see if the prefix matches the start of this using
+ directive. */
+ if (strncmp (prefix, current->current->outer, 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->outer + prefix_len;
+ /* Should we skip some colons? */
+ if (*rest_of_outer == ':')
+ rest_of_outer += 2;
+ int rest_of_outer_len = strlen (rest_of_outer);
+ 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->inner,
+ 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);
+ strcpy (concatenated_name, prefix);
+ 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
/* Opaque declarations. */
struct obstack;
struct dictionary;
-struct using_data_node;
+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
struct dictionary *dict;
/* Used for language-specific info. */
+
union
{
struct
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_data_node *using;
+
+ struct using_direct_node *using;
}
cplus_specific;
}
+2002-10-11 David Carlton <carlton@math.stanford.edu>
+
+ * gdb.c++/namespace.exp: Add tests from within C::D::marker2.
+ * gdb.c++/namespace.cc: Add namespace C and its contents.
+
2002-09-26 Keith Seitz <keiths@redhat.com>
* lib/insight-support.exp (gdbtk_start): Figure out where
return;
}
+namespace C
+{
+ int c = 1;
+
+ namespace C
+ {
+ int cc = 2;
+ }
+
+ namespace E
+ {
+ int ce = 4;
+ }
+
+ namespace D
+ {
+ int cd = 3;
+
+ namespace E
+ {
+ int cde = 5;
+ }
+
+ 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;
+ //E::ce;
+ return;
+ }
+
+ }
+}
+
int main ()
{
c1 = cl.xyzq('e');
marker1();
-
-}
-
-
-
-
+ C::D::marker2 ();
+}
timeout { fail "(timeout) break BBB::Class::xyzq" }
}
+# Now, 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-11: It would be nice to test printing
+# "E::ce", but unfortunately GDB will print it out even though it
+# shouldn't. Oops.