2003-05-19 David Carlton <carlton@bactrian.org>
authorDavid Carlton <carlton@bactrian.org>
Tue, 20 May 2003 03:56:29 +0000 (03:56 +0000)
committerDavid Carlton <carlton@bactrian.org>
Tue, 20 May 2003 03:56:29 +0000 (03:56 +0000)
Partial fix for PR c++/827.
* cp-support.h: Include symtab.h.
Declare cp_lookup_symbol_nonlocal, cp_lookup_symbol_namespace.
* cp-namespace.c: Update contributors.
(cp_lookup_symbol_nonlocal): New.
(lookup_namespace_scope, cp_lookup_symbol_namespace)
(lookup_symbol_file): Ditto.
* c-lang.c (cplus_language_defn): Use cp_lookup_symbol_nonlocal.
* block.h: Declare block_scope, block_using, block_global_block.
* block.c (block_scope): New.
(block_using, block_global_block): Ditto.
* Makefile.in (cp_support_h): Depend on symtab_h.
* config/djgpp/fnchange.lst: Add testsuite/gdb.c++/namespace1.cc.

2003-05-19  David Carlton  <carlton@bactrian.org>

* gdb.c++/namespace.exp: Add namespace scope and anonymous
namespace tests.
Bump copyright date.
* gdb.c++/namespace.cc: Add anonymous namespace and namespace C.
(main): Call C::D::marker2.
* gdb.c++/namespace1.cc: New file.

gdb/ChangeLog
gdb/Makefile.in
gdb/block.c
gdb/block.h
gdb/c-lang.c
gdb/config/djgpp/fnchange.lst
gdb/cp-namespace.c
gdb/cp-support.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.c++/namespace.cc
gdb/testsuite/gdb.c++/namespace.exp

index 8f1ab3dc211dd2af0995f4f3f665cf5c5a3419df..1425ca79263acec20c9553c5f567959119a0a9c6 100644 (file)
@@ -1,3 +1,19 @@
+2003-05-19  David Carlton  <carlton@bactrian.org>
+
+       Partial fix for PR c++/827.
+       * cp-support.h: Include symtab.h.
+       Declare cp_lookup_symbol_nonlocal, cp_lookup_symbol_namespace.
+       * cp-namespace.c: Update contributors.
+       (cp_lookup_symbol_nonlocal): New.
+       (lookup_namespace_scope, cp_lookup_symbol_namespace)
+       (lookup_symbol_file): Ditto.
+       * c-lang.c (cplus_language_defn): Use cp_lookup_symbol_nonlocal.
+       * block.h: Declare block_scope, block_using, block_global_block.
+       * block.c (block_scope): New.
+       (block_using, block_global_block): Ditto.
+       * Makefile.in (cp_support_h): Depend on symtab_h.
+       * config/djgpp/fnchange.lst: Add testsuite/gdb.c++/namespace1.cc.
+
 2003-05-19  David Carlton  <carlton@bactrian.org>
 
        * language.h (struct language_defn): Add 'la_value_of_this'
index 197d17704f40ad5ef444390982c5064b667e4bad..b01642a006b7090a7d0aa5fc9f84da9ff7d39694 100644 (file)
@@ -626,7 +626,7 @@ complaints_h = complaints.h
 completer_h = completer.h
 config_h = config.h
 cp_abi_h = cp-abi.h
-cp_support_h = cp-support.h
+cp_support_h = cp-support.h $(symtab_h)
 dcache_h = dcache.h
 defs_h = defs.h $(config_h) $(gdb_locale_h) $(gdb_signals_h) $(ansidecl_h) \
        $(libiberty_h) $(progress_h) $(bfd_h) $(tui_h) $(ui_file_h) $(xm_h) \
index 1360a1589d0f36fa079d7f688f5d7bdff71ebccf..3396c8aa96c442903c09be8036f8e0793ce91996 100644 (file)
@@ -155,8 +155,25 @@ block_for_pc (register CORE_ADDR pc)
   return block_for_pc_sect (pc, find_pc_mapped_section (pc));
 }
 
-/* Now come some functions designed to deal with C++ namespace
-   issues.  */
+/* Now come some functions designed to deal with C++ namespace issues.
+   The accessors are safe to use even in the non-C++ case.  */
+
+/* This returns the namespace that BLOCK is enclosed in, or "" if it
+   isn't enclosed in a namespace at all.  This travels the chain of
+   superblocks looking for a scope, if necessary.  */
+
+const char *
+block_scope (const struct block *block)
+{
+  for (; block != NULL; block = BLOCK_SUPERBLOCK (block))
+    {
+      if (BLOCK_NAMESPACE (block) != NULL
+         && BLOCK_NAMESPACE (block)->scope != NULL)
+       return BLOCK_NAMESPACE (block)->scope;
+    }
+
+  return "";
+}
 
 /* Set BLOCK's scope member to SCOPE; if needed, allocate memory via
    OBSTACK.  (It won't make a copy of SCOPE, however, so that already
@@ -171,6 +188,27 @@ block_set_scope (struct block *block, const char *scope,
   BLOCK_NAMESPACE (block)->scope = scope;
 }
 
+/* This returns the first using directives associated to BLOCK, if
+   any.  */
+
+/* FIXME: carlton/2003-04-23: This uses the fact that we currently
+   only have using directives in static blocks, because we only
+   generate using directives from anonymous namespaces.  Eventually,
+   when we support using directives everywhere, we'll want to replace
+   this by some iterator functions.  */
+
+struct using_direct *
+block_using (const struct block *block)
+{
+  const struct block *static_block = block_static_block (block);
+
+  if (static_block == NULL
+      || BLOCK_NAMESPACE (static_block) == NULL)
+    return NULL;
+  else
+    return BLOCK_NAMESPACE (static_block)->using;
+}
+
 /* Set BLOCK's using member to USING; if needed, allocate memory via
    OBSTACK.  (It won't make a copy of USING, however, so that already
    has to be allocated correctly.)  */
@@ -214,3 +252,18 @@ block_static_block (const struct block *block)
 
   return block;
 }
+
+/* Return the static block associated to BLOCK.  Return NULL if block
+   is NULL.  */
+
+const struct block *
+block_global_block (const struct block *block)
+{
+  if (block == NULL)
+    return NULL;
+
+  while (BLOCK_SUPERBLOCK (block) != NULL)
+    block = BLOCK_SUPERBLOCK (block);
+
+  return block;
+}
index 17c726dc17f954e7ef1e0897de9eae98d2d117a9..442fa4a86e46ee9518be7ea4d459179ef1165050 100644 (file)
@@ -200,13 +200,19 @@ extern struct block *block_for_pc (CORE_ADDR);
 
 extern struct block *block_for_pc_sect (CORE_ADDR, asection *);
 
+extern const char *block_scope (const struct block *block);
+
 extern void block_set_scope (struct block *block, const char *scope,
                             struct obstack *obstack);
 
+extern struct using_direct *block_using (const struct block *block);
+
 extern void block_set_using (struct block *block,
                             struct using_direct *using,
                             struct obstack *obstack);
 
 extern const struct block *block_static_block (const struct block *block);
 
+extern const struct block *block_global_block (const struct block *block);
+
 #endif /* BLOCK_H */
index 9f7ba8ef7e65dc794aaba96d13c2e43a94a7548a..bdbbb54172c59a602a04c18d2bdd2cbecb9139b8 100644 (file)
@@ -32,6 +32,7 @@
 #include "charset.h"
 #include "gdb_string.h"
 #include "demangle.h"
+#include "cp-support.h"
 
 extern void _initialize_c_language (void);
 static void c_emit_char (int c, struct ui_file * stream, int quoter);
@@ -610,7 +611,7 @@ const struct language_defn cplus_language_defn =
   c_value_print,               /* Print a top-level value */
   NULL,                                /* Language specific skip_trampoline */
   value_of_this,               /* value_of_this */
-  basic_lookup_symbol_nonlocal,        /* lookup_symbol_nonlocal */
+  cp_lookup_symbol_nonlocal,   /* lookup_symbol_nonlocal */
   cplus_demangle,              /* Language specific symbol demangler */
   {"", "", "", ""},            /* Binary format info */
   {"0%lo", "0", "o", ""},      /* Octal format info */
index 1b9fd8bf26170965e9049a528443ae34ca656996..10287c9f89467cafa1a98dcc1e57da10eea43d73 100644 (file)
 @V@/gdb/testsuite/gdb.c++/misc.cc @V@/gdb/testsuite/gdb.cxx/misc.cc
 @V@/gdb/testsuite/gdb.c++/misc.exp @V@/gdb/testsuite/gdb.cxx/misc.exp
 @V@/gdb/testsuite/gdb.c++/namespace.cc @V@/gdb/testsuite/gdb.cxx/namespace.cc
+@V@/gdb/testsuite/gdb.c++/namespace1.cc @V@/gdb/testsuite/gdb.cxx/namesp1.cc
 @V@/gdb/testsuite/gdb.c++/namespace.exp @V@/gdb/testsuite/gdb.cxx/namespace.exp
 @V@/gdb/testsuite/gdb.c++/overload.cc @V@/gdb/testsuite/gdb.cxx/overload.cc
 @V@/gdb/testsuite/gdb.c++/overload.exp @V@/gdb/testsuite/gdb.cxx/overload.exp
index 7205cf738387f8f99d4fb13033d1135c9d1f4800..a4c7b8d3570a755dc070b1810e61d72c77eb1f0f 100644 (file)
@@ -1,7 +1,7 @@
 /* Helper routines for C++ support in GDB.
    Copyright 2003 Free Software Foundation, Inc.
 
-   Contributed by David Carlton.
+   Contributed by David Carlton and by Kealia, Inc.
 
    This file is part of GDB.
 
@@ -52,6 +52,21 @@ static struct using_direct *cp_add_using (const char *name,
 static struct using_direct *cp_copy_usings (struct using_direct *using,
                                            struct obstack *obstack);
 
+static struct symbol *lookup_namespace_scope (const char *name,
+                                             const char *linkage_name,
+                                             const struct block *block,
+                                             const domain_enum domain,
+                                             struct symtab **symtab,
+                                             const char *scope,
+                                             int scope_len);
+
+static struct symbol *lookup_symbol_file (const char *name,
+                                         const char *linkage_name,
+                                         const struct block *block,
+                                         const domain_enum domain,
+                                         struct symtab **symtab,
+                                         int anonymous_namespace);
+
 /* Set up support for dealing with C++ namespace info in the current
    symtab.  */
 
@@ -264,3 +279,177 @@ cp_copy_usings (struct using_direct *using,
       return retval;
     }
 }
+
+/* The C++-specific version of name lookup for static and global
+   names.  This makes sure that names get looked for in all namespaces
+   that are in scope.  NAME is the natural name of the symbol that
+   we're looking for, LINKAGE_NAME (which is optional) is its linkage
+   name, BLOCK is the block that we're searching within, DOMAIN says
+   what kind of symbols we're looking for, and if SYMTAB is non-NULL,
+   we should store the symtab where we found the symbol in it.  */
+
+struct symbol *
+cp_lookup_symbol_nonlocal (const char *name,
+                          const char *linkage_name,
+                          const struct block *block,
+                          const domain_enum domain,
+                          struct symtab **symtab)
+{
+  return lookup_namespace_scope (name, linkage_name, block, domain,
+                                symtab, block_scope (block), 0);
+}
+
+/* Lookup NAME at namespace scope (or, in C terms, in static and
+   global variables).  SCOPE is the namespace that the current
+   function is defined within; only consider namespaces whose length
+   is at least SCOPE_LEN.  Other arguments are as in
+   cp_lookup_symbol_nonlocal.
+
+   For example, if we're within a function A::B::f and looking for a
+   symbol f, this will get called with NAME = "f", SCOPE = "A::B", and
+   SCOPE_LEN = 0.  It then calls itself with NAME and SCOPE the same,
+   but with SCOPE_LEN = 1.  And then it calls itself with NAME and
+   SCOPE the same, but with SCOPE_LEN = 4.  This third call looks for
+   "A::B::x"; if it doesn't find it, then the second call looks for
+   "A::x", and if that call fails, then the first call looks for
+   "x".  */
+
+static struct symbol *
+lookup_namespace_scope (const char *name,
+                       const char *linkage_name,
+                       const struct block *block,
+                       const domain_enum domain,
+                       struct symtab **symtab,
+                       const char *scope,
+                       int scope_len)
+{
+  char *namespace;
+
+  if (scope[scope_len] != '\0')
+    {
+      /* Recursively search for names in child namespaces first.  */
+
+      struct symbol *sym;
+      int new_scope_len = scope_len;
+
+      /* If the current scope is followed by "::", skip past that.  */
+      if (new_scope_len != 0)
+       {
+         gdb_assert (scope[new_scope_len] == ':');
+         new_scope_len += 2;
+       }
+      new_scope_len += cp_find_first_component (scope + new_scope_len);
+      sym = lookup_namespace_scope (name, linkage_name, block,
+                                   domain, symtab,
+                                   scope, new_scope_len);
+      if (sym != NULL)
+       return sym;
+    }
+
+  /* Okay, we didn't find a match in our children, so look for the
+     name in the current namespace.  */
+
+  namespace = alloca (scope_len + 1);
+  strncpy (namespace, scope, scope_len);
+  namespace[scope_len] = '\0';
+  return cp_lookup_symbol_namespace (namespace, name, linkage_name,
+                                    block, domain, symtab);
+}
+
+/* Look up NAME in the C++ namespace NAMESPACE, applying the using
+   directives that are active in BLOCK.  Other arguments are as in
+   cp_lookup_symbol_nonlocal.  */
+
+struct symbol *
+cp_lookup_symbol_namespace (const char *namespace,
+                           const char *name,
+                           const char *linkage_name,
+                           const struct block *block,
+                           const domain_enum domain,
+                           struct symtab **symtab)
+{
+  const struct using_direct *current;
+  struct symbol *sym;
+
+  /* First, go through the using directives.  If any of them add new
+     names to the namespace we're searching in, see if we can find a
+     match by applying them.  */
+
+  for (current = block_using (block);
+       current != NULL;
+       current = current->next)
+    {
+      if (strcmp (namespace, current->outer) == 0)
+       {
+         sym = cp_lookup_symbol_namespace (current->inner,
+                                           name,
+                                           linkage_name,
+                                           block,
+                                           domain,
+                                           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 namespace.  */
+  
+  if (namespace[0] == '\0')
+    {
+      return lookup_symbol_file (name, linkage_name, block,
+                                domain, symtab, 0);
+    }
+  else
+    {
+      char *concatenated_name
+       = alloca (strlen (namespace) + 2 + strlen (name) + 1);
+      strcpy (concatenated_name, namespace);
+      strcat (concatenated_name, "::");
+      strcat (concatenated_name, name);
+      sym = lookup_symbol_file (concatenated_name, linkage_name,
+                               block, domain, symtab,
+                               cp_is_anonymous (namespace));
+      return sym;
+    }
+}
+
+/* Look up NAME in BLOCK's static block and in global blocks.  If
+   ANONYMOUS_NAMESPACE is nonzero, the symbol in question is located
+   within an anonymous namespace.  Other arguments are as in
+   cp_lookup_symbol_nonlocal.  */
+
+static struct symbol *
+lookup_symbol_file (const char *name,
+                   const char *linkage_name,
+                   const struct block *block,
+                   const domain_enum domain,
+                   struct symtab **symtab,
+                   int anonymous_namespace)
+{
+  struct symbol *sym = NULL;
+
+  sym = lookup_symbol_static (name, linkage_name, block, domain, symtab);
+  if (sym != NULL)
+    return sym;
+
+  if (anonymous_namespace)
+    {
+      /* Symbols defined in anonymous namespaces have external linkage
+        but should be treated as local to a single file nonetheless.
+        So we only search the current file's global block.  */
+
+      const struct block *global_block = block_global_block (block);
+      
+      if (global_block != NULL)
+       return lookup_symbol_aux_block (name, linkage_name, global_block,
+                                       domain, symtab);
+      else
+       return NULL;
+    }
+  else
+    {
+      return lookup_symbol_global (name, linkage_name, domain, symtab);
+    }
+}
index 76e842b5d1fb93d31b9d802bfc663878fccf56e4..952d6a2b17b3c3595a80d66d97e938c1ec45ca4e 100644 (file)
 #ifndef CP_SUPPORT_H
 #define CP_SUPPORT_H
 
+/* We need this for 'domain_enum', alas...  */
+
+#include "symtab.h"
+
 /* Opaque declarations.  */
 
 struct obstack;
 struct block;
-struct symbol;
 
 /* This struct is designed to store data from using directives.  It
    says that names from namespace INNER should be visible within
@@ -78,4 +81,17 @@ extern void cp_set_block_scope (const struct symbol *symbol,
 
 extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol);
 
+extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
+                                                const char *linkage_name,
+                                                const struct block *block,
+                                                const domain_enum domain,
+                                                struct symtab **symtab);
+
+extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
+                                                 const char *name,
+                                                 const char *linkage_name,
+                                                 const struct block *block,
+                                                 const domain_enum domain,
+                                                 struct symtab **symtab);
+
 #endif /* CP_SUPPORT_H */
index 27eae486e2fbd2970a1a720f0c6e6b01b31b9be1..a2fb2dbec80245578d05805c1ad04107327c48de 100644 (file)
@@ -1,3 +1,12 @@
+2003-05-19  David Carlton  <carlton@bactrian.org>
+
+       * gdb.c++/namespace.exp: Add namespace scope and anonymous
+       namespace tests.
+       Bump copyright date.
+       * gdb.c++/namespace.cc: Add anonymous namespace and namespace C.
+       (main): Call C::D::marker2.
+       * gdb.c++/namespace1.cc: New file.
+
 2003-05-14  Jeff Johnston  <jjohnstn@redhat.com>
 
        Roland McGrath  <roland@redhat.com>
index 7667266c278a15370cc9b8526bc30b5edccf152b..7b9a173d819b8b745d87c668cb58e66cee3ee4eb 100644 (file)
@@ -68,6 +68,70 @@ void marker1(void)
   return;
 }
 
+namespace
+{
+  int X = 9;
+
+  namespace G
+  {
+    int Xg = 10;
+  }
+}
+
+namespace C
+{
+  int c = 1;
+  int shadow = 12;
+
+  namespace
+  {
+    int cX = 6;
+    
+    namespace F
+    {
+      int cXf = 7;
+    }
+  }
+
+  namespace C
+  {
+    int cc = 2;
+  }
+
+  namespace D
+  {
+    int cd = 3;
+    int shadow = 13;
+
+    namespace E
+    {
+      int cde = 5;
+    }
+
+    void marker2 (void)
+    {
+      // NOTE: carlton/2003-04-23: 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;
+      cX;
+      F::cXf;
+      X;
+      G::Xg;
+      //cXOtherFile;
+      //XOtherFile;
+
+      return;
+    }
+
+  }
+}
 
 int main ()
 {
@@ -95,9 +159,5 @@ int main ()
 
   marker1();
   
+  C::D::marker2 ();
 }
-
-  
-
-
-
index 3e502c4b50a937eeb7a6a2b4ba2c89231b94341d..f4efaf64d2373f56dd6d20723b9dc199eaacbe4a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
+# Copyright 1997, 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -39,20 +39,26 @@ if { [skip_cplus_tests] } { continue }
 
 set testfile "namespace"
 set srcfile ${testfile}.cc
+set objfile ${objdir}/${subdir}/${testfile}.o
+set srcfile1 ${testfile}1.cc
+set objfile1 ${objdir}/${subdir}/${testfile}1.o
 set binfile ${objdir}/${subdir}/${testfile}
 
 if [get_compiler_info ${binfile}] {
     return -1;
 }
 
-
-
-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
-     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will a
-utomatically fail."
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objfile}" object {debug c++}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
 }
 
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile1}" "${objfile1}" object {debug c++}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
 
+if  { [gdb_compile "${objfile} ${objfile1}" "${binfile}" executable {debug c++}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
 
 gdb_exit
 gdb_start
@@ -186,3 +192,28 @@ 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"
+gdb_test "print cc" "No symbol \"cc\" in current context."
+gdb_test "print 'C::cc'" "\\$\[0-9\].* = 2"
+gdb_test "print cd" "\\$\[0-9\].* = 3"
+gdb_test "print 'E::cde'" "\\$\[0-9\].* = 5"
+gdb_test "print shadow" "\\$\[0-9\].* = 13"
+gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
+
+# Some anonymous namespace tests.
+
+gdb_test "print cX" "\\$\[0-9\].* = 6"
+gdb_test "print 'F::cXf'" "\\$\[0-9\].* = 7"
+gdb_test "print X" "\\$\[0-9\].* = 9"
+gdb_test "print 'G::Xg'" "\\$\[0-9\].* = 10"
+gdb_test "print cXOtherFile" "No symbol \"cXOtherFile\" in current context."
+gdb_test "print XOtherFile" "No symbol \"XOtherFile\" in current context."