]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
2002-10-22 David Carlton <carlton@math.stanford.edu>
authorDavid Carlton <carlton@bactrian.org>
Tue, 22 Oct 2002 19:59:37 +0000 (19:59 +0000)
committerDavid Carlton <carlton@bactrian.org>
Tue, 22 Oct 2002 19:59:37 +0000 (19:59 +0000)
* 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.

15 files changed:
gdb/ChangeLog.cplus
gdb/Makefile.in
gdb/buildsym.c
gdb/buildsym.h
gdb/cp-support.c
gdb/cp-support.h
gdb/dwarf2read.c
gdb/jv-lang.c
gdb/symfile.c
gdb/symfile.h
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/ChangeLog.cplus [new file with mode: 0644]
gdb/testsuite/gdb.c++/namespace.cc
gdb/testsuite/gdb.c++/namespace.exp

index d764cd31794099b386baef8cf2788ca89a35e550..07bf6d2359074cc2803549a0a367867f56d29da7 100644 (file)
@@ -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
index 95330c0950b4e328129cd4588842bd38bc944a1a..08882077a96c0a1f5c1a84ab874fb8e06c61866f 100644 (file)
@@ -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)
index 9d9b4f74482b6e806e136857ac81f53d210f4f56..7bbc0e6f8a87ef94743cf6e7d98b50de54d237fc 100644 (file)
@@ -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 *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.  */
index 8a252cb2b4c63fbccf496f3df63efa004fbf8885..3b8c16fa19f22938aeed4266a59d0cd2a11e4597 100644 (file)
@@ -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,
index 46363a8b3bf0a419d34c23e8c0f5d75953ff820a..a13967f9f8292c87055df5abad975f0b57b76218 100644 (file)
 #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;
+       }
+    }
+}
index a7d333f28b201b531e3e159c4f11c14fcdaf915d..bb89c6fe26f7ed097f4d095fecc24489b5c47aa3 100644 (file)
    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 b62b0282b3ff305785590314f61863de3f594c24..84a8bbb88cc4894f746e9d39e9db691a9c44de63 100644 (file)
@@ -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>";
     }
index 3afdebdb46727fdbe622493f1c4c167d525a66da..03bf565da8a8a1f28116b772746eda8be21c5f4a 100644 (file)
@@ -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 66bbf7149844f448329f35dda9f008ad745038f6..ae0578d499582a89a90cac43b66f1d6780fe51d9 100644 (file)
@@ -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++;
   }
index 39eb3080f13c9522d31e2f97da660cc29016a211..62dfcefb54b56574a2aef45334890936f1cde18a 100644 (file)
 
 /* 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.  */
index 9227fe7aec01672b1290cbb726f3068600ad01cd..8e76be8f639309755b7ace1f3585f4f48c701145 100644 (file)
@@ -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. */
@@ -94,6 +95,13 @@ static struct symbol *lookup_symbol_aux_local (const char *name,
                                               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,
@@ -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
index a78607d584e6f866ecb79056e050c462f6d65939..9aca9c1245771e72917b703757f02e7fd2ed0154 100644 (file)
@@ -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 (file)
index 0000000..3436b73
--- /dev/null
@@ -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.
index 7667266c278a15370cc9b8526bc30b5edccf152b..6298b91762d5f72d8e863cec34ce260cae858459 100644 (file)
@@ -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 3e502c4b50a937eeb7a6a2b4ba2c89231b94341d..ebe845e16e327ecec429dfc9216a7ba47f5819c7 100644 (file)
@@ -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"