Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 1/2] namespace support
@ 2009-05-22 14:48 Sami Wagiaalla
  2009-06-02 15:13 ` Sami Wagiaalla
  2009-06-05  0:27 ` Tom Tromey
  0 siblings, 2 replies; 7+ messages in thread
From: Sami Wagiaalla @ 2009-05-22 14:48 UTC (permalink / raw)
  To: GDB Patches

[-- Attachment #1: Type: text/plain, Size: 15330 bytes --]


Currently imports statements are stored in the nearest static
block. Also, these import statements only correspond to the
implicit importing of annonymous namespaces.

This patch enables each block to own its own 'using
directives', and creates using directives for non anonymous
imports.



diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cf44f2a..4614659 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,26 @@
+2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* dwarf2read.c (process_die): Handle import statements
+	(DW_TAG_imported_declaration, case DW_TAG_imported_module)
+	(read_import_statement): New.
+	(read_func_scope): Update using_directives to point to current context
+	(read_lexical_block_scope): Ditto.
+	* cp-support.h: Added prototype for cp_add_using.
+	* cp-namespace.c: Removed local context_stack.
+	(cp_initialize_namespace): Deleted.
+	(cp_finalize_namespace): Deleted.
+	(cp_add_using_directive): Use using_directives instead of using_list.
+	(cp_add_using): No longer static.
+	* buildsym.h: Created global using_direct variable.
+	Created using_direct variable in context_stack.
+	* buildsym.c (finish_block): Set using directives for the block	under
+	construction.
+	(start_symtab): Removed call to cp_initialize_namespace().
+	(end_symtab): Removed call to cp_finalize_namespace().
+	(push_context): Save and reset using_directives.
+	* block.c (block_using): Return using directives for given
+	block instead of static block.
+
  2009-05-19  Jan Kratochvil  <jan.kratochvil@redhat.com>

  	Remove the PROT parameter from openp.
diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..da36f7c 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,17 @@ 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.  */
+/* This returns the using directives list associated to BLOCK, if
+   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
+   imported at that code point - even those from its parent blocks.  */

  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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
      return NULL;
    else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
  }

  /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 6de817f..8c4f53b 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
        opblock = pblock;
      }

+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
    record_pending_block (objfile, block, opblock);

    return block;
@@ -815,10 +817,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
    /* We shouldn't have any address map at this point.  */
    gdb_assert (! pending_addrmap);

-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
    /* Initialize the list of sub source files with one entry for this
       file (the top-level source file).  */

@@ -1015,8 +1013,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
      }

    /* Read the line table if it has to be read separately.  */
@@ -1228,10 +1224,12 @@ push_context (int desc, CORE_ADDR valu)
    new->params = param_symbols;
    new->old_blocks = pending_blocks;
    new->start_addr = valu;
+  new->using_directives = using_directives;
    new->name = NULL;

    local_symbols = NULL;
    param_symbols = NULL;
+  using_directives = NULL;

    return new;
  }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..f542aca 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;

  EXTERN struct pending *param_symbols;

+/* using directives local to lexical context */
+
+EXTERN struct using_direct *using_directives;
+
  /* Stack representing unclosed lexical contexts (that will become
     blocks, eventually).  */

@@ -138,6 +142,10 @@ struct context_stack

      struct pending *params;

+    /* Pending using directives at the time we entered */
+
+    struct using_direct *using_directives;
+
      /* Pointer into blocklist as of entry */

      struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..8bb341f 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
  #include "dictionary.h"
  #include "command.h"
  #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"

  static struct using_direct *cp_copy_usings (struct using_direct *using,
  					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);

  static void maintenance_cplus_namespace (char *args, int from_tty);

-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
  /* Check to see if SYMBOL refers to an object contained within an
     anonymous namespace; if so, add an appropriate using directive.  */

@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,

    /* Has it already been added?  */

-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
      {
        if ((strncmp (current->inner, name, inner_length) == 0)
  	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
  	return;
      }

-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+      using_directives);
  }

  /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
     using xmalloc.  It copies the strings, so NAME can be a temporary
     string.  */

-static struct using_direct *
+struct using_direct *
  cp_add_using (const char *name,
  	      unsigned int inner_len,
  	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
  				    unsigned int outer_length,
  				    unsigned int inner_length);

+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
  extern void cp_initialize_namespace (void);

  extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6ddaecd..dd7cf67 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -971,6 +971,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);

  static void read_module (struct die_info *die, struct dwarf2_cu *cu);

+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
  static const char *namespace_name (struct die_info *die,
  				   int *is_anonymous, struct dwarf2_cu *);

@@ -2880,14 +2882,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
        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.  */
        processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
        break;
      default:
        new_symbol (die, NULL, cu);
@@ -2933,6 +2933,38 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
    return name;
  }

+/* Read the import statement specified by the given die and record it.  */
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = namespace_name (imported_die, &is_anonymous, cu);
+  if (imported_name == NULL)
+    {
+      /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - why?  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
  static void
  initialize_cu_func_list (struct dwarf2_cu *cu)
  {
@@ -3266,6 +3298,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
       back to building a containing block's symbol lists.  */
    local_symbols = new->locals;
    param_symbols = new->params;
+  using_directives = new->using_directives;

    /* If we've finished processing a top-level function, subsequent
       symbols go in the file symbol list.  */
@@ -3328,6 +3361,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
        dwarf2_record_block_ranges (die, block, baseaddr, cu);
      }
    local_symbols = new->locals;
+  using_directives = new->using_directives;
  }

  /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 70ded08..4b34527 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* gdb.cp/namespace-using.exp: New test.
+	* gdb.cp/namespace-using.cc: New test program.
+
  2009-05-18  Jon Beniston <jon@beniston.com>

          * gdb.asm/asm-source.exp: Add lm32 target.
diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
new file mode 100644
index 0000000..4786fd5
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.cc
@@ -0,0 +1,45 @@
+namespace A
+{
+  int _a = 1;
+  int x = 2;
+}
+
+int marker4(){
+	using A::x;
+	return 0;
+}
+
+int marker3(){
+	return marker4();
+}
+
+int marker2()
+{
+  namespace B = A;
+  B::_a;
+  return marker3();
+}
+
+int marker1()
+{
+  int total = 0;
+  {
+    int b = 1;
+    {
+      using namespace A;
+      int c = 2;
+      {
+        int d = 3;
+        total = _a + b + c + d + marker2(); // marker1 stop
+      }
+    }
+  }
+  return total;
+}
+
+int main()
+{
+  using namespace A;
+  _a;
+  return marker1();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp
new file mode 100644
index 0000000..2e57927
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.exp
@@ -0,0 +1,87 @@
+# Copyright 2008 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-using
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+# test printing of namespace imported within
+# the function.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print _a" "= 1"
+
+############################################
+# test printing of namespace imported into
+# a scope containing the pc.
+
+gdb_breakpoint [gdb_get_line_number "marker1 stop"]
+gdb_continue_to_breakpoint "marker1 stop"
+
+gdb_test "print _a" "= 1" "print _a in a nested scope"
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/7935" "*-*-*"
+if ![runto marker2] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print B::a" "= 1"
+
+############################################
+# Test that names are not printed when they
+# are not imported
+
+send_gdb "break marker3\n"
+gdb_continue_to_breakpoint "marker3"
+
+gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import"
+
+############################################
+# Test printing of individually imported elements
+
+setup_kfail "gdb/7936" "*-*-*"
+if ![runto marker4] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print x" "= 2"

[-- Attachment #2: namespace-1.patch --]
[-- Type: text/plain, Size: 14990 bytes --]

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index cf44f2a..4614659 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,26 @@
+2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* dwarf2read.c (process_die): Handle import statements 
+	(DW_TAG_imported_declaration, case DW_TAG_imported_module)
+	(read_import_statement): New.
+	(read_func_scope): Update using_directives to point to current context
+	(read_lexical_block_scope): Ditto.
+	* cp-support.h: Added prototype for cp_add_using.
+	* cp-namespace.c: Removed local context_stack.
+	(cp_initialize_namespace): Deleted.
+	(cp_finalize_namespace): Deleted.
+	(cp_add_using_directive): Use using_directives instead of using_list.
+	(cp_add_using): No longer static.
+	* buildsym.h: Created global using_direct variable.
+	Created using_direct variable in context_stack.
+	* buildsym.c (finish_block): Set using directives for the block	under
+	construction.
+	(start_symtab): Removed call to cp_initialize_namespace().
+	(end_symtab): Removed call to cp_finalize_namespace().
+	(push_context): Save and reset using_directives.
+	* block.c (block_using): Return using directives for given
+	block instead of static block.
+
 2009-05-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
 	Remove the PROT parameter from openp.
diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..da36f7c 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,17 @@ 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.  */
+/* This returns the using directives list associated to BLOCK, if
+   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
+   imported at that code point - even those from its parent blocks.  */
 
 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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
     return NULL;
   else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
 }
 
 /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 6de817f..8c4f53b 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
       opblock = pblock;
     }
 
+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
   record_pending_block (objfile, block, opblock);
 
   return block;
@@ -815,10 +817,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
   /* We shouldn't have any address map at this point.  */
   gdb_assert (! pending_addrmap);
 
-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
   /* Initialize the list of sub source files with one entry for this
      file (the top-level source file).  */
 
@@ -1015,8 +1013,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
     }
 
   /* Read the line table if it has to be read separately.  */
@@ -1228,10 +1224,12 @@ push_context (int desc, CORE_ADDR valu)
   new->params = param_symbols;
   new->old_blocks = pending_blocks;
   new->start_addr = valu;
+  new->using_directives = using_directives;
   new->name = NULL;
 
   local_symbols = NULL;
   param_symbols = NULL;
+  using_directives = NULL;
 
   return new;
 }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..f542aca 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;
 
 EXTERN struct pending *param_symbols;
 
+/* using directives local to lexical context */
+
+EXTERN struct using_direct *using_directives;
+
 /* Stack representing unclosed lexical contexts (that will become
    blocks, eventually).  */
 
@@ -138,6 +142,10 @@ struct context_stack
 
     struct pending *params;
 
+    /* Pending using directives at the time we entered */
+
+    struct using_direct *using_directives;
+
     /* Pointer into blocklist as of entry */
 
     struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..8bb341f 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
 #include "dictionary.h"
 #include "command.h"
 #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"
 
 static struct using_direct *cp_copy_usings (struct using_direct *using,
 					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);
 
 static void maintenance_cplus_namespace (char *args, int from_tty);
 
-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
 /* Check to see if SYMBOL refers to an object contained within an
    anonymous namespace; if so, add an appropriate using directive.  */
 
@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 
   /* Has it already been added?  */
 
-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
     {
       if ((strncmp (current->inner, name, inner_length) == 0)
 	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 	return;
     }
 
-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+      using_directives);
 }
 
 /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
    using xmalloc.  It copies the strings, so NAME can be a temporary
    string.  */
 
-static struct using_direct *
+struct using_direct *
 cp_add_using (const char *name,
 	      unsigned int inner_len,
 	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
 				    unsigned int outer_length,
 				    unsigned int inner_length);
 
+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
 extern void cp_initialize_namespace (void);
 
 extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6ddaecd..dd7cf67 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -971,6 +971,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
 static void read_module (struct die_info *die, struct dwarf2_cu *cu);
 
+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
 static const char *namespace_name (struct die_info *die,
 				   int *is_anonymous, struct dwarf2_cu *);
 
@@ -2880,14 +2882,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       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.  */
       processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
       break;
     default:
       new_symbol (die, NULL, cu);
@@ -2933,6 +2933,38 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
   return name;
 }
 
+/* Read the import statement specified by the given die and record it.  */ 
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+  
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = namespace_name (imported_die, &is_anonymous, cu);
+  if (imported_name == NULL)
+    {
+      /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - why?  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+  
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
 static void
 initialize_cu_func_list (struct dwarf2_cu *cu)
 {
@@ -3266,6 +3298,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
      back to building a containing block's symbol lists.  */
   local_symbols = new->locals;
   param_symbols = new->params;
+  using_directives = new->using_directives;
 
   /* If we've finished processing a top-level function, subsequent
      symbols go in the file symbol list.  */
@@ -3328,6 +3361,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       dwarf2_record_block_ranges (die, block, baseaddr, cu);
     }
   local_symbols = new->locals;
+  using_directives = new->using_directives;
 }
 
 /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 70ded08..4b34527 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* gdb.cp/namespace-using.exp: New test.
+	* gdb.cp/namespace-using.cc: New test program.
+
 2009-05-18  Jon Beniston <jon@beniston.com>
 
         * gdb.asm/asm-source.exp: Add lm32 target.
diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
new file mode 100644
index 0000000..4786fd5
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.cc
@@ -0,0 +1,45 @@
+namespace A
+{
+  int _a = 1;
+  int x = 2;
+}
+
+int marker4(){
+	using A::x;
+	return 0;
+}
+
+int marker3(){
+	return marker4();
+}
+
+int marker2()
+{
+  namespace B = A;
+  B::_a;
+  return marker3();
+}
+
+int marker1()
+{
+  int total = 0;
+  {
+    int b = 1;
+    {
+      using namespace A;
+      int c = 2;
+      {
+        int d = 3;
+        total = _a + b + c + d + marker2(); // marker1 stop
+      }
+    }
+  }
+  return total;
+}
+
+int main()
+{
+  using namespace A;
+  _a;
+  return marker1();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp
new file mode 100644
index 0000000..2e57927
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.exp
@@ -0,0 +1,87 @@
+# Copyright 2008 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-using
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+# test printing of namespace imported within
+# the function.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print _a" "= 1"
+
+############################################
+# test printing of namespace imported into 
+# a scope containing the pc.
+
+gdb_breakpoint [gdb_get_line_number "marker1 stop"]
+gdb_continue_to_breakpoint "marker1 stop"
+
+gdb_test "print _a" "= 1" "print _a in a nested scope"
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/7935" "*-*-*"
+if ![runto marker2] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print B::a" "= 1"
+
+############################################
+# Test that names are not printed when they 
+# are not imported
+
+send_gdb "break marker3\n"
+gdb_continue_to_breakpoint "marker3"
+
+gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import"
+
+############################################
+# Test printing of individually imported elements
+
+setup_kfail "gdb/7936" "*-*-*"
+if ![runto marker4] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print x" "= 2"

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-05-22 14:48 [PATCH 1/2] namespace support Sami Wagiaalla
@ 2009-06-02 15:13 ` Sami Wagiaalla
  2009-06-05  0:27 ` Tom Tromey
  1 sibling, 0 replies; 7+ messages in thread
From: Sami Wagiaalla @ 2009-06-02 15:13 UTC (permalink / raw)
  To: GDB Patches

Ping

Sami Wagiaalla wrote:
> 
> Currently imports statements are stored in the nearest static
> block. Also, these import statements only correspond to the
> implicit importing of annonymous namespaces.
> 
> This patch enables each block to own its own 'using
> directives', and creates using directives for non anonymous
> imports.
> 
> 
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index cf44f2a..4614659 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,26 @@
> +2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
> +
> +    * dwarf2read.c (process_die): Handle import statements
> +    (DW_TAG_imported_declaration, case DW_TAG_imported_module)
> +    (read_import_statement): New.
> +    (read_func_scope): Update using_directives to point to current context
> +    (read_lexical_block_scope): Ditto.
> +    * cp-support.h: Added prototype for cp_add_using.
> +    * cp-namespace.c: Removed local context_stack.
> +    (cp_initialize_namespace): Deleted.
> +    (cp_finalize_namespace): Deleted.
> +    (cp_add_using_directive): Use using_directives instead of using_list.
> +    (cp_add_using): No longer static.
> +    * buildsym.h: Created global using_direct variable.
> +    Created using_direct variable in context_stack.
> +    * buildsym.c (finish_block): Set using directives for the block    
> under
> +    construction.
> +    (start_symtab): Removed call to cp_initialize_namespace().
> +    (end_symtab): Removed call to cp_finalize_namespace().
> +    (push_context): Save and reset using_directives.
> +    * block.c (block_using): Return using directives for given
> +    block instead of static block.
> +
>  2009-05-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
>      Remove the PROT parameter from openp.
> diff --git a/gdb/block.c b/gdb/block.c
> index 8f0140c..da36f7c 100644
> --- a/gdb/block.c
> +++ b/gdb/block.c
> @@ -206,25 +206,17 @@ 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.  */
> +/* This returns the using directives list associated to BLOCK, if
> +   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
> +   imported at that code point - even those from its parent blocks.  */
> 
>  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)
> +  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
>      return NULL;
>    else
> -    return BLOCK_NAMESPACE (static_block)->using;
> +    return BLOCK_NAMESPACE (block)->using;
>  }
> 
>  /* Set BLOCK's using member to USING; if needed, allocate memory via
> diff --git a/gdb/buildsym.c b/gdb/buildsym.c
> index 6de817f..8c4f53b 100644
> --- a/gdb/buildsym.c
> +++ b/gdb/buildsym.c
> @@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending 
> **listhead,
>        opblock = pblock;
>      }
> 
> +  block_set_using (block, using_directives, &objfile->objfile_obstack);
> +
>    record_pending_block (objfile, block, opblock);
> 
>    return block;
> @@ -815,10 +817,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR 
> start_addr)
>    /* We shouldn't have any address map at this point.  */
>    gdb_assert (! pending_addrmap);
> 
> -  /* Set up support for C++ namespace support, in case we need it.  */
> -
> -  cp_initialize_namespace ();
> -
>    /* Initialize the list of sub source files with one entry for this
>       file (the top-level source file).  */
> 
> @@ -1015,8 +1013,6 @@ 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);
> -      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, 
> STATIC_BLOCK),
> -                 &objfile->objfile_obstack);
>      }
> 
>    /* Read the line table if it has to be read separately.  */
> @@ -1228,10 +1224,12 @@ push_context (int desc, CORE_ADDR valu)
>    new->params = param_symbols;
>    new->old_blocks = pending_blocks;
>    new->start_addr = valu;
> +  new->using_directives = using_directives;
>    new->name = NULL;
> 
>    local_symbols = NULL;
>    param_symbols = NULL;
> +  using_directives = NULL;
> 
>    return new;
>  }
> diff --git a/gdb/buildsym.h b/gdb/buildsym.h
> index bf23ecc..f542aca 100644
> --- a/gdb/buildsym.h
> +++ b/gdb/buildsym.h
> @@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;
> 
>  EXTERN struct pending *param_symbols;
> 
> +/* using directives local to lexical context */
> +
> +EXTERN struct using_direct *using_directives;
> +
>  /* Stack representing unclosed lexical contexts (that will become
>     blocks, eventually).  */
> 
> @@ -138,6 +142,10 @@ struct context_stack
> 
>      struct pending *params;
> 
> +    /* Pending using directives at the time we entered */
> +
> +    struct using_direct *using_directives;
> +
>      /* Pointer into blocklist as of entry */
> 
>      struct pending_block *old_blocks;
> diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
> index c6c5617..8bb341f 100644
> --- a/gdb/cp-namespace.c
> +++ b/gdb/cp-namespace.c
> @@ -30,15 +30,7 @@
>  #include "dictionary.h"
>  #include "command.h"
>  #include "frame.h"
> -
> -/* List of using directives that are active in the current file.  */
> -
> -static struct using_direct *using_list;
> -
> -static struct using_direct *cp_add_using (const char *name,
> -                      unsigned int inner_len,
> -                      unsigned int outer_len,
> -                      struct using_direct *next);
> +#include "buildsym.h"
> 
>  static struct using_direct *cp_copy_usings (struct using_direct *using,
>                          struct obstack *obstack);
> @@ -78,31 +70,6 @@ static struct symbol 
> *lookup_possible_namespace_symbol (const char *name);
> 
>  static void maintenance_cplus_namespace (char *args, int from_tty);
> 
> -/* Set up support for dealing with C++ namespace info in the current
> -   symtab.  */
> -
> -void cp_initialize_namespace ()
> -{
> -  using_list = NULL;
> -}
> -
> -/* Add all the using directives we've gathered to the current symtab.
> -   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
> -   for allocation.  */
> -
> -void
> -cp_finalize_namespace (struct block *static_block,
> -               struct obstack *obstack)
> -{
> -  if (using_list != NULL)
> -    {
> -      block_set_using (static_block,
> -               cp_copy_usings (using_list, obstack),
> -               obstack);
> -      using_list = NULL;
> -    }
> -}
> -
>  /* Check to see if SYMBOL refers to an object contained within an
>     anonymous namespace; if so, add an appropriate using directive.  */
> 
> @@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned 
> int outer_length,
> 
>    /* Has it already been added?  */
> 
> -  for (current = using_list; current != NULL; current = current->next)
> +  for (current = using_directives; current != NULL; current = 
> current->next)
>      {
>        if ((strncmp (current->inner, name, inner_length) == 0)
>        && (strlen (current->inner) == inner_length)
> @@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned 
> int outer_length,
>      return;
>      }
> 
> -  using_list = cp_add_using (name, inner_length, outer_length,
> -                 using_list);
> +  using_directives = cp_add_using (name, inner_length, outer_length,
> +      using_directives);
>  }
> 
>  /* Record the namespace that the function defined by SYMBOL was
> @@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
>     using xmalloc.  It copies the strings, so NAME can be a temporary
>     string.  */
> 
> -static struct using_direct *
> +struct using_direct *
>  cp_add_using (const char *name,
>            unsigned int inner_len,
>            unsigned int outer_len,
> diff --git a/gdb/cp-support.h b/gdb/cp-support.h
> index 837ca6c..e577f7d 100644
> --- a/gdb/cp-support.h
> +++ b/gdb/cp-support.h
> @@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
>                      unsigned int outer_length,
>                      unsigned int inner_length);
> 
> +extern struct using_direct *cp_add_using (const char *name,
> +                      unsigned int inner_len,
> +                      unsigned int outer_len,
> +                      struct using_direct *next);
> +
>  extern void cp_initialize_namespace (void);
> 
>  extern void cp_finalize_namespace (struct block *static_block,
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 6ddaecd..dd7cf67 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -971,6 +971,8 @@ static void read_namespace (struct die_info *die, 
> struct dwarf2_cu *);
> 
>  static void read_module (struct die_info *die, struct dwarf2_cu *cu);
> 
> +static void read_import_statement (struct die_info *die, struct 
> dwarf2_cu *);
> +
>  static const char *namespace_name (struct die_info *die,
>                     int *is_anonymous, struct dwarf2_cu *);
> 
> @@ -2880,14 +2882,12 @@ process_die (struct die_info *die, struct 
> dwarf2_cu *cu)
>        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.  */
>        processing_has_namespace_info = 1;
> -      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
> -         dwarf_tag_name (die->tag));
> +      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
> +                 || cu->language != language_fortran))
> +    complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
> +           dwarf_tag_name (die->tag));
> +      read_import_statement (die, cu);
>        break;
>      default:
>        new_symbol (die, NULL, cu);
> @@ -2933,6 +2933,38 @@ dwarf2_full_name (struct die_info *die, struct 
> dwarf2_cu *cu)
>    return name;
>  }
> 
> +/* Read the import statement specified by the given die and record it.  */
> +
> +static void
> +read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
> +{
> +  struct attribute *import_attr;
> +  struct die_info *imported_die;
> +  const char *imported_name;
> +  int is_anonymous = 0;
> +
> +  import_attr = dwarf2_attr (die, DW_AT_import, cu);
> +  if (import_attr == NULL)
> +    {
> +      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
> +         dwarf_tag_name (die->tag));
> +      return;
> +    }
> +
> +  imported_die = follow_die_ref (die, import_attr, &cu);
> +  imported_name = namespace_name (imported_die, &is_anonymous, cu);
> +  if (imported_name == NULL)
> +    {
> +      /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - 
> why?  */
> +      return;
> +    }
> +
> +  /* FIXME: dwarf2_name (die); for the local name after import.  */
> +
> +  using_directives = cp_add_using (imported_name, strlen 
> (imported_name), 0,
> +                                   using_directives);
> +}
> +
>  static void
>  initialize_cu_func_list (struct dwarf2_cu *cu)
>  {
> @@ -3266,6 +3298,7 @@ read_func_scope (struct die_info *die, struct 
> dwarf2_cu *cu)
>       back to building a containing block's symbol lists.  */
>    local_symbols = new->locals;
>    param_symbols = new->params;
> +  using_directives = new->using_directives;
> 
>    /* If we've finished processing a top-level function, subsequent
>       symbols go in the file symbol list.  */
> @@ -3328,6 +3361,7 @@ read_lexical_block_scope (struct die_info *die, 
> struct dwarf2_cu *cu)
>        dwarf2_record_block_ranges (die, block, baseaddr, cu);
>      }
>    local_symbols = new->locals;
> +  using_directives = new->using_directives;
>  }
> 
>  /* Get low and high pc attributes from DW_AT_ranges attribute value 
> OFFSET.
> diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
> index 70ded08..4b34527 100644
> --- a/gdb/testsuite/ChangeLog
> +++ b/gdb/testsuite/ChangeLog
> @@ -1,3 +1,8 @@
> +2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
> +
> +    * gdb.cp/namespace-using.exp: New test.
> +    * gdb.cp/namespace-using.cc: New test program.
> +
>  2009-05-18  Jon Beniston <jon@beniston.com>
> 
>          * gdb.asm/asm-source.exp: Add lm32 target.
> diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc 
> b/gdb/testsuite/gdb.cp/namespace-using.cc
> new file mode 100644
> index 0000000..4786fd5
> --- /dev/null
> +++ b/gdb/testsuite/gdb.cp/namespace-using.cc
> @@ -0,0 +1,45 @@
> +namespace A
> +{
> +  int _a = 1;
> +  int x = 2;
> +}
> +
> +int marker4(){
> +    using A::x;
> +    return 0;
> +}
> +
> +int marker3(){
> +    return marker4();
> +}
> +
> +int marker2()
> +{
> +  namespace B = A;
> +  B::_a;
> +  return marker3();
> +}
> +
> +int marker1()
> +{
> +  int total = 0;
> +  {
> +    int b = 1;
> +    {
> +      using namespace A;
> +      int c = 2;
> +      {
> +        int d = 3;
> +        total = _a + b + c + d + marker2(); // marker1 stop
> +      }
> +    }
> +  }
> +  return total;
> +}
> +
> +int main()
> +{
> +  using namespace A;
> +  _a;
> +  return marker1();
> +}
> diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp 
> b/gdb/testsuite/gdb.cp/namespace-using.exp
> new file mode 100644
> index 0000000..2e57927
> --- /dev/null
> +++ b/gdb/testsuite/gdb.cp/namespace-using.exp
> @@ -0,0 +1,87 @@
> +# Copyright 2008 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
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
> +
> +if $tracelevel then {
> +    strace $tracelevel
> +}
> +
> +set prms_id 0
> +set bug_id 0
> +
> +set testfile namespace-using
> +set srcfile ${testfile}.cc
> +set binfile ${objdir}/${subdir}/${testfile}
> +if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" 
> executable {debug c++}] != "" } {
> +    untested "Couldn't compile test program"
> +    return -1
> +}
> +
> +# Get things started.
> +
> +gdb_exit
> +gdb_start
> +gdb_reinitialize_dir $srcdir/$subdir
> +gdb_load ${binfile}
> +
> +############################################
> +# test printing of namespace imported within
> +# the function.
> +
> +if ![runto_main] then {
> +    perror "couldn't run to breakpoint main"
> +    continue
> +}
> +
> +gdb_test "print _a" "= 1"
> +
> +############################################
> +# test printing of namespace imported into
> +# a scope containing the pc.
> +
> +gdb_breakpoint [gdb_get_line_number "marker1 stop"]
> +gdb_continue_to_breakpoint "marker1 stop"
> +
> +gdb_test "print _a" "= 1" "print _a in a nested scope"
> +
> +############################################
> +# Test printing of namespace aliases
> +
> +setup_kfail "gdb/7935" "*-*-*"
> +if ![runto marker2] then {
> +    perror "couldn't run to breakpoint marker2"
> +    continue
> +}
> +
> +gdb_test "print B::a" "= 1"
> +
> +############################################
> +# Test that names are not printed when they
> +# are not imported
> +
> +send_gdb "break marker3\n"
> +gdb_continue_to_breakpoint "marker3"
> +
> +gdb_test "print _a" "No symbol \"_a\" in current context." "Print a 
> without import"
> +
> +############################################
> +# Test printing of individually imported elements
> +
> +setup_kfail "gdb/7936" "*-*-*"
> +if ![runto marker4] then {
> +    perror "couldn't run to breakpoint marker2"
> +    continue
> +}
> +
> +gdb_test "print x" "= 2"
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-05-22 14:48 [PATCH 1/2] namespace support Sami Wagiaalla
  2009-06-02 15:13 ` Sami Wagiaalla
@ 2009-06-05  0:27 ` Tom Tromey
  2009-06-19 19:43   ` Sami Wagiaalla
  1 sibling, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2009-06-05  0:27 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: GDB Patches

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Sami> Currently imports statements are stored in the nearest static
Sami> block. Also, these import statements only correspond to the
Sami> implicit importing of annonymous namespaces.

This looks pretty reasonable to me.
A few nits and such...

Sami> +/* This returns the using directives list associated to BLOCK, if
Sami> +   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
Sami> +   imported at that code point - even those from its parent blocks.  */

I think the caps on "USING" here are weird.
Maybe just:

    The result contains all the [...]

Sami> +/* using directives local to lexical context */

Comments should in general be sentences -- starting with a capital
letter and ending with a period and two spaces.
Here I would probably write:

  /* "using" directives local to lexical context.  */

... avoiding the capital since "using" is a keyword.

Sami> +EXTERN struct using_direct *using_directives;

Eww, buildsym is full of globals.  Not your problem :-), but yet
another thing that would be nice to clean up.

Sami> +    /* Pending using directives at the time we entered */

Likewise about the period and spaces.

Sami> -  using_list = cp_add_using (name, inner_length, outer_length,
Sami> -			     using_list);
Sami> +  using_directives = cp_add_using (name, inner_length, outer_length,
Sami> +      using_directives);

Looks like a formatting change; the old code was indented correctly.

Sami> +static void
Sami> +read_import_statement (struct die_info *die, struct dwarf2_cu *cu)

[...]

Sami> +  if (imported_name == NULL)
Sami> +    {
Sami> +      /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - why?  */

It would be nice to understand this before the patch goes in.

Sami> +  /* FIXME: dwarf2_name (die); for the local name after import.  */

It would also be nice if we could not add new FIXMEs.
Or is that handled in a later patch?

Sami> +  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
Sami> +                                   using_directives);
Sami> +}

I didn't look -- but are there other buildsym globals which are
actively updated by the dwarf reader like this?  I'm wondering whether
this is something that should be hidden inside a call, like a new
wrapper for cp_add_using.

This is not a big deal.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-06-05  0:27 ` Tom Tromey
@ 2009-06-19 19:43   ` Sami Wagiaalla
  2009-06-19 20:15     ` Sami Wagiaalla
  2009-06-19 21:33     ` Tom Tromey
  0 siblings, 2 replies; 7+ messages in thread
From: Sami Wagiaalla @ 2009-06-19 19:43 UTC (permalink / raw)
  To: tromey; +Cc: GDB Patches

[-- Attachment #1: Type: text/plain, Size: 14959 bytes --]

Tom Tromey wrote:
>>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:
> 
> Sami> Currently imports statements are stored in the nearest static
> Sami> block. Also, these import statements only correspond to the
> Sami> implicit importing of annonymous namespaces.
> 
> This looks pretty reasonable to me.
> A few nits and such...
> 
> Sami> +/* This returns the using directives list associated to BLOCK, if
> Sami> +   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
> Sami> +   imported at that code point - even those from its parent blocks.  */
> 
> I think the caps on "USING" here are weird.
> Maybe just:
> 
>     The result contains all the [...]

I changed it to:

/* This returns the using directives list associated with BLOCK, if
     any.  */

The second part of the comment is not correct.

> 
> Sami> +/* using directives local to lexical context */
> 
> Comments should in general be sentences -- starting with a capital
> letter and ending with a period and two spaces.
> Here I would probably write:
> 
>   /* "using" directives local to lexical context.  */
> 
> ... avoiding the capital since "using" is a keyword.
> 
> Sami> +EXTERN struct using_direct *using_directives;
> 
> Eww, buildsym is full of globals.  Not your problem :-), but yet
> another thing that would be nice to clean up.
> 

There is a nice clean up for this suggested by Jan. That is using the
variables in the current context object and automating saving/and
restoration of that. I'll post a patch if I get to it.

> 
> Sami> +static void
> Sami> +read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
> 
> [...]
> 
> Sami> +  if (imported_name == NULL)
> Sami> +    {
> Sami> +      /* C++ imports from std:: DW_TAG_base_type with no DW_AT_name - why?  */
> 
> It would be nice to understand this before the patch goes in.
> 

This is a gcc bug. I filed it here:
https://bugzilla.redhat.com/show_bug.cgi?id=506524 and improved the comment.
and improved the comment.

also I changed the line above the comment to use dwarf2_name instead of
namespace_name which is incorrect.

-  imported_name = namespace_name (imported_die, &is_anonymous, cu);
+  imported_name = dwarf2_name (imported_die, cu);

> Sami> +  /* FIXME: dwarf2_name (die); for the local name after import.  */
> 
> It would also be nice if we could not add new FIXMEs.
> Or is that handled in a later patch?
> 

Yes, it will be handled in a later patch.

> Sami> +  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
> Sami> +                                   using_directives);
> Sami> +}
> 
> I didn't look -- but are there other buildsym globals which are
> actively updated by the dwarf reader like this?  I'm wondering whether
> this is something that should be hidden inside a call, like a new
> wrapper for cp_add_using.
> 

For now using_directives is a global. I wrote this to be parallel to
local_symbols. If the context clean up is done cp_add_using can just
request  the current context

> This is not a big deal.
> 
> Tom

-----------------------------------------


  2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>

	* dwarf2read.c (process_die): Handle import statements
  	(DW_TAG_imported_declaration, case DW_TAG_imported_module)
  	(read_import_statement): New.
  	(read_func_scope): Update using_directives to point to current context
  	(read_lexical_block_scope): Ditto.
  	* cp-support.h: Added prototype for cp_add_using.
  	* cp-namespace.c: Removed local context_stack.
  	(cp_initialize_namespace): Deleted.
  	(cp_finalize_namespace): Deleted.
  	(cp_add_using_directive): Use using_directives instead of using_list.
  	(cp_add_using): No longer static.
  	* buildsym.h: Created global using_direct variable.
  	Created using_direct variable in context_stack.
  	* buildsym.c (finish_block): Set using directives for the block	under
  	construction.
  	(start_symtab): Removed call to cp_initialize_namespace().
  	(end_symtab): Removed call to cp_finalize_namespace().
  	(push_context): Save and reset using_directives.
  	* block.c (block_using): Return using directives for given
  	block instead of static block.


diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..9ebe975 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,16 @@ block_set_scope (struct block *block, const char *scope,
    BLOCK_NAMESPACE (block)->scope = scope;
  }

-/* This returns the first using directives associated to BLOCK, if
+/* This returns the using directives list associated with 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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
      return NULL;
    else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
  }

  /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index e7c48fe..e6ef9c6 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
        opblock = pblock;
      }

+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
    record_pending_block (objfile, block, opblock);

    return block;
@@ -812,10 +814,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
    /* We shouldn't have any address map at this point.  */
    gdb_assert (! pending_addrmap);

-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
    /* Initialize the list of sub source files with one entry for this
       file (the top-level source file).  */

@@ -1012,8 +1010,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
      }

    /* Read the line table if it has to be read separately.  */
@@ -1225,10 +1221,12 @@ push_context (int desc, CORE_ADDR valu)
    new->params = param_symbols;
    new->old_blocks = pending_blocks;
    new->start_addr = valu;
+  new->using_directives = using_directives;
    new->name = NULL;

    local_symbols = NULL;
    param_symbols = NULL;
+  using_directives = NULL;

    return new;
  }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..6f8b09f 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;

  EXTERN struct pending *param_symbols;

+/* "using" directives local to lexical context.  */
+
+EXTERN struct using_direct *using_directives;
+
  /* Stack representing unclosed lexical contexts (that will become
     blocks, eventually).  */

@@ -138,6 +142,10 @@ struct context_stack

      struct pending *params;

+    /* Pending using directives at the time we entered.  */
+
+    struct using_direct *using_directives;
+
      /* Pointer into blocklist as of entry */

      struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..f3b2194 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
  #include "dictionary.h"
  #include "command.h"
  #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"

  static struct using_direct *cp_copy_usings (struct using_direct *using,
  					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);

  static void maintenance_cplus_namespace (char *args, int from_tty);

-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
  /* Check to see if SYMBOL refers to an object contained within an
     anonymous namespace; if so, add an appropriate using directive.  */

@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,

    /* Has it already been added?  */

-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
      {
        if ((strncmp (current->inner, name, inner_length) == 0)
  	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
  	return;
      }

-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+                                   using_directives);
  }

  /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
     using xmalloc.  It copies the strings, so NAME can be a temporary
     string.  */

-static struct using_direct *
+struct using_direct *
  cp_add_using (const char *name,
  	      unsigned int inner_len,
  	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
  				    unsigned int outer_length,
  				    unsigned int inner_length);

+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
  extern void cp_initialize_namespace (void);

  extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ae8870c..6569798 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -946,6 +946,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);

  static void read_module (struct die_info *die, struct dwarf2_cu *cu);

+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
  static const char *namespace_name (struct die_info *die,
  				   int *is_anonymous, struct dwarf2_cu *);

@@ -2984,14 +2986,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
        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.  */
        processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
        break;
      default:
        new_symbol (die, NULL, cu);
@@ -3037,6 +3037,69 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
    return name;
  }

+/* Read the import statement specified by the given die and record it.  */
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = dwarf2_name (imported_die, cu);
+  if (imported_name == NULL)
+    {
+      /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524
+
+        The import in the following code:
+        namespace A
+          {
+            typedef int B;
+          }
+
+        int main ()
+          {
+            using A::B;
+            B b;
+            return b;
+          }
+
+        ...
+         <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
+            <52>   DW_AT_decl_file   : 1
+            <53>   DW_AT_decl_line   : 6
+            <54>   DW_AT_import      : <0x75>
+         <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
+            <59>   DW_AT_name        : B
+            <5b>   DW_AT_decl_file   : 1
+            <5c>   DW_AT_decl_line   : 2
+            <5d>   DW_AT_type        : <0x6e>
+        ...
+         <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
+            <76>   DW_AT_byte_size   : 4
+            <77>   DW_AT_encoding    : 5        (signed)
+
+        imports the wrong die ( 0x75 instead of 0x58 ).
+        This case will be ignored until the gcc bug is fixed.  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
  static void
  initialize_cu_func_list (struct dwarf2_cu *cu)
  {
@@ -3370,6 +3433,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
       back to building a containing block's symbol lists.  */
    local_symbols = new->locals;
    param_symbols = new->params;
+  using_directives = new->using_directives;

    /* If we've finished processing a top-level function, subsequent
       symbols go in the file symbol list.  */
@@ -3432,6 +3496,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
        dwarf2_record_block_ranges (die, block, baseaddr, cu);
      }
    local_symbols = new->locals;
+  using_directives = new->using_directives;
  }

  /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.


[-- Attachment #2: namespace-1.1.patch --]
[-- Type: text/plain, Size: 11779 bytes --]


 2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
 
	* dwarf2read.c (process_die): Handle import statements 
 	(DW_TAG_imported_declaration, case DW_TAG_imported_module)
 	(read_import_statement): New.
 	(read_func_scope): Update using_directives to point to current context
 	(read_lexical_block_scope): Ditto.
 	* cp-support.h: Added prototype for cp_add_using.
 	* cp-namespace.c: Removed local context_stack.
 	(cp_initialize_namespace): Deleted.
 	(cp_finalize_namespace): Deleted.
 	(cp_add_using_directive): Use using_directives instead of using_list.
 	(cp_add_using): No longer static.
 	* buildsym.h: Created global using_direct variable.
 	Created using_direct variable in context_stack.
 	* buildsym.c (finish_block): Set using directives for the block	under
 	construction.
 	(start_symtab): Removed call to cp_initialize_namespace().
 	(end_symtab): Removed call to cp_finalize_namespace().
 	(push_context): Save and reset using_directives.
 	* block.c (block_using): Return using directives for given
 	block instead of static block.


diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..9ebe975 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,16 @@ block_set_scope (struct block *block, const char *scope,
   BLOCK_NAMESPACE (block)->scope = scope;
 }
 
-/* This returns the first using directives associated to BLOCK, if
+/* This returns the using directives list associated with 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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
     return NULL;
   else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
 }
 
 /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index e7c48fe..e6ef9c6 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
       opblock = pblock;
     }
 
+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
   record_pending_block (objfile, block, opblock);
 
   return block;
@@ -812,10 +814,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
   /* We shouldn't have any address map at this point.  */
   gdb_assert (! pending_addrmap);
 
-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
   /* Initialize the list of sub source files with one entry for this
      file (the top-level source file).  */
 
@@ -1012,8 +1010,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
     }
 
   /* Read the line table if it has to be read separately.  */
@@ -1225,10 +1221,12 @@ push_context (int desc, CORE_ADDR valu)
   new->params = param_symbols;
   new->old_blocks = pending_blocks;
   new->start_addr = valu;
+  new->using_directives = using_directives;
   new->name = NULL;
 
   local_symbols = NULL;
   param_symbols = NULL;
+  using_directives = NULL;
 
   return new;
 }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..6f8b09f 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;
 
 EXTERN struct pending *param_symbols;
 
+/* "using" directives local to lexical context.  */
+
+EXTERN struct using_direct *using_directives;
+
 /* Stack representing unclosed lexical contexts (that will become
    blocks, eventually).  */
 
@@ -138,6 +142,10 @@ struct context_stack
 
     struct pending *params;
 
+    /* Pending using directives at the time we entered.  */
+
+    struct using_direct *using_directives;
+
     /* Pointer into blocklist as of entry */
 
     struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..f3b2194 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
 #include "dictionary.h"
 #include "command.h"
 #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"
 
 static struct using_direct *cp_copy_usings (struct using_direct *using,
 					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);
 
 static void maintenance_cplus_namespace (char *args, int from_tty);
 
-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
 /* Check to see if SYMBOL refers to an object contained within an
    anonymous namespace; if so, add an appropriate using directive.  */
 
@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 
   /* Has it already been added?  */
 
-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
     {
       if ((strncmp (current->inner, name, inner_length) == 0)
 	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 	return;
     }
 
-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+                                   using_directives);
 }
 
 /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
    using xmalloc.  It copies the strings, so NAME can be a temporary
    string.  */
 
-static struct using_direct *
+struct using_direct *
 cp_add_using (const char *name,
 	      unsigned int inner_len,
 	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
 				    unsigned int outer_length,
 				    unsigned int inner_length);
 
+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
 extern void cp_initialize_namespace (void);
 
 extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ae8870c..6569798 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -946,6 +946,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
 static void read_module (struct die_info *die, struct dwarf2_cu *cu);
 
+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
 static const char *namespace_name (struct die_info *die,
 				   int *is_anonymous, struct dwarf2_cu *);
 
@@ -2984,14 +2986,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       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.  */
       processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
       break;
     default:
       new_symbol (die, NULL, cu);
@@ -3037,6 +3037,69 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
   return name;
 }
 
+/* Read the import statement specified by the given die and record it.  */
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = dwarf2_name (imported_die, cu);
+  if (imported_name == NULL)
+    {
+      /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524
+
+        The import in the following code:
+        namespace A
+          {
+            typedef int B;
+          }
+
+        int main ()
+          {
+            using A::B;
+            B b;
+            return b;
+          }
+
+        ...
+         <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
+            <52>   DW_AT_decl_file   : 1
+            <53>   DW_AT_decl_line   : 6
+            <54>   DW_AT_import      : <0x75>
+         <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
+            <59>   DW_AT_name        : B
+            <5b>   DW_AT_decl_file   : 1
+            <5c>   DW_AT_decl_line   : 2
+            <5d>   DW_AT_type        : <0x6e>
+        ...
+         <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
+            <76>   DW_AT_byte_size   : 4
+            <77>   DW_AT_encoding    : 5        (signed)
+
+        imports the wrong die ( 0x75 instead of 0x58 ).
+        This case will be ignored until the gcc bug is fixed.  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
 static void
 initialize_cu_func_list (struct dwarf2_cu *cu)
 {
@@ -3370,6 +3433,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
      back to building a containing block's symbol lists.  */
   local_symbols = new->locals;
   param_symbols = new->params;
+  using_directives = new->using_directives;
 
   /* If we've finished processing a top-level function, subsequent
      symbols go in the file symbol list.  */
@@ -3432,6 +3496,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       dwarf2_record_block_ranges (die, block, baseaddr, cu);
     }
   local_symbols = new->locals;
+  using_directives = new->using_directives;
 }
 
 /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-06-19 19:43   ` Sami Wagiaalla
@ 2009-06-19 20:15     ` Sami Wagiaalla
  2009-06-19 21:33     ` Tom Tromey
  1 sibling, 0 replies; 7+ messages in thread
From: Sami Wagiaalla @ 2009-06-19 20:15 UTC (permalink / raw)
  To: tromey; +Cc: GDB Patches

[-- Attachment #1: Type: text/plain, Size: 15460 bytes --]

Ops. The patch in the previous message was missing the test case.
Here is the same patch with the test case included:


     2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>

        * dwarf2read.c (process_die): Handle import statements
        (DW_TAG_imported_declaration, case DW_TAG_imported_module)
        (read_import_statement): New.
        (read_func_scope): Update using_directives to point to current context
        (read_lexical_block_scope): Ditto.
        * cp-support.h: Added prototype for cp_add_using.
        * cp-namespace.c: Removed local context_stack.
        (cp_initialize_namespace): Deleted.
        (cp_finalize_namespace): Deleted.
        (cp_add_using_directive): Use using_directives instead of using_list.
        (cp_add_using): No longer static.
        * buildsym.h: Created global using_direct variable.
        Created using_direct variable in context_stack.
        * buildsym.c (finish_block): Set using directives for the block	under
        construction.
        (start_symtab): Removed call to cp_initialize_namespace().
        (end_symtab): Removed call to cp_finalize_namespace().
        (push_context): Save and reset using_directives.
        * block.c (block_using): Return using directives for given
        block instead of static block.

diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..9ebe975 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,16 @@ block_set_scope (struct block *block, const char *scope,
    BLOCK_NAMESPACE (block)->scope = scope;
  }

-/* This returns the first using directives associated to BLOCK, if
+/* This returns the using directives list associated with 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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
      return NULL;
    else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
  }

  /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index e7c48fe..e6ef9c6 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
        opblock = pblock;
      }

+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
    record_pending_block (objfile, block, opblock);

    return block;
@@ -812,10 +814,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
    /* We shouldn't have any address map at this point.  */
    gdb_assert (! pending_addrmap);

-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
    /* Initialize the list of sub source files with one entry for this
       file (the top-level source file).  */

@@ -1012,8 +1010,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
      }

    /* Read the line table if it has to be read separately.  */
@@ -1225,10 +1221,12 @@ push_context (int desc, CORE_ADDR valu)
    new->params = param_symbols;
    new->old_blocks = pending_blocks;
    new->start_addr = valu;
+  new->using_directives = using_directives;
    new->name = NULL;

    local_symbols = NULL;
    param_symbols = NULL;
+  using_directives = NULL;

    return new;
  }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..6f8b09f 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;

  EXTERN struct pending *param_symbols;

+/* "using" directives local to lexical context.  */
+
+EXTERN struct using_direct *using_directives;
+
  /* Stack representing unclosed lexical contexts (that will become
     blocks, eventually).  */

@@ -138,6 +142,10 @@ struct context_stack

      struct pending *params;

+    /* Pending using directives at the time we entered.  */
+
+    struct using_direct *using_directives;
+
      /* Pointer into blocklist as of entry */

      struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..f3b2194 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
  #include "dictionary.h"
  #include "command.h"
  #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"

  static struct using_direct *cp_copy_usings (struct using_direct *using,
  					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);

  static void maintenance_cplus_namespace (char *args, int from_tty);

-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
  /* Check to see if SYMBOL refers to an object contained within an
     anonymous namespace; if so, add an appropriate using directive.  */

@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,

    /* Has it already been added?  */

-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
      {
        if ((strncmp (current->inner, name, inner_length) == 0)
  	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
  	return;
      }

-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+                                   using_directives);
  }

  /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
     using xmalloc.  It copies the strings, so NAME can be a temporary
     string.  */

-static struct using_direct *
+struct using_direct *
  cp_add_using (const char *name,
  	      unsigned int inner_len,
  	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
  				    unsigned int outer_length,
  				    unsigned int inner_length);

+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
  extern void cp_initialize_namespace (void);

  extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ae8870c..6569798 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -946,6 +946,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);

  static void read_module (struct die_info *die, struct dwarf2_cu *cu);

+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
  static const char *namespace_name (struct die_info *die,
  				   int *is_anonymous, struct dwarf2_cu *);

@@ -2984,14 +2986,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
        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.  */
        processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
        break;
      default:
        new_symbol (die, NULL, cu);
@@ -3037,6 +3037,69 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
    return name;
  }

+/* Read the import statement specified by the given die and record it.  */
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = dwarf2_name (imported_die, cu);
+  if (imported_name == NULL)
+    {
+      /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524
+
+        The import in the following code:
+        namespace A
+          {
+            typedef int B;
+          }
+
+        int main ()
+          {
+            using A::B;
+            B b;
+            return b;
+          }
+
+        ...
+         <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
+            <52>   DW_AT_decl_file   : 1
+            <53>   DW_AT_decl_line   : 6
+            <54>   DW_AT_import      : <0x75>
+         <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
+            <59>   DW_AT_name        : B
+            <5b>   DW_AT_decl_file   : 1
+            <5c>   DW_AT_decl_line   : 2
+            <5d>   DW_AT_type        : <0x6e>
+        ...
+         <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
+            <76>   DW_AT_byte_size   : 4
+            <77>   DW_AT_encoding    : 5        (signed)
+
+        imports the wrong die ( 0x75 instead of 0x58 ).
+        This case will be ignored until the gcc bug is fixed.  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
  static void
  initialize_cu_func_list (struct dwarf2_cu *cu)
  {
@@ -3370,6 +3433,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
       back to building a containing block's symbol lists.  */
    local_symbols = new->locals;
    param_symbols = new->params;
+  using_directives = new->using_directives;

    /* If we've finished processing a top-level function, subsequent
       symbols go in the file symbol list.  */
@@ -3432,6 +3496,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
        dwarf2_record_block_ranges (die, block, baseaddr, cu);
      }
    local_symbols = new->locals;
+  using_directives = new->using_directives;
  }

  /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
new file mode 100644
index 0000000..4786fd5
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.cc
@@ -0,0 +1,45 @@
+namespace A
+{
+  int _a = 1;
+  int x = 2;
+}
+
+int marker4(){
+	using A::x;
+	return 0;
+}
+
+int marker3(){
+	return marker4();
+}
+
+int marker2()
+{
+  namespace B = A;
+  B::_a;
+  return marker3();
+}
+
+int marker1()
+{
+  int total = 0;
+  {
+    int b = 1;
+    {
+      using namespace A;
+      int c = 2;
+      {
+        int d = 3;
+        total = _a + b + c + d + marker2(); // marker1 stop
+      }
+    }
+  }
+  return total;
+}
+
+int main()
+{
+  using namespace A;
+  _a;
+  return marker1();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp
new file mode 100644
index 0000000..f24973f
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.exp
@@ -0,0 +1,87 @@
+# Copyright 2008 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-using
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+# test printing of namespace imported within
+# the function.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print _a" "= 1"
+
+############################################
+# test printing of namespace imported into
+# a scope containing the pc.
+
+gdb_breakpoint [gdb_get_line_number "marker1 stop"]
+gdb_continue_to_breakpoint "marker1 stop"
+
+gdb_test "print _a" "= 1" "print _a in a nested scope"
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/7935" "*-*-*"
+if ![runto marker2] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print B::a" "= 1"
+
+############################################
+# Test that names are not printed when they
+# are not imported
+
+gdb_breakpoint "marker3"
+gdb_continue_to_breakpoint "marker3"
+
+gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import"
+
+############################################
+# Test printing of individually imported elements
+
+setup_kfail "gdb/7936" "*-*-*"
+if ![runto marker4] then {
+    perror "couldn't run to breakpoint marker4"
+    continue
+}
+
+gdb_test "print x" "= 2"

[-- Attachment #2: namespace-1.1.patch --]
[-- Type: text/plain, Size: 15276 bytes --]

    
    2009-05-21  Sami Wagiaalla  <swagiaal@redhat.com>
    
       * dwarf2read.c (process_die): Handle import statements
       (DW_TAG_imported_declaration, case DW_TAG_imported_module)
       (read_import_statement): New.
       (read_func_scope): Update using_directives to point to current context
       (read_lexical_block_scope): Ditto.
       * cp-support.h: Added prototype for cp_add_using.
       * cp-namespace.c: Removed local context_stack.
       (cp_initialize_namespace): Deleted.
       (cp_finalize_namespace): Deleted.
       (cp_add_using_directive): Use using_directives instead of using_list.
       (cp_add_using): No longer static.
       * buildsym.h: Created global using_direct variable.
       Created using_direct variable in context_stack.
       * buildsym.c (finish_block): Set using directives for the block	under
       construction.
       (start_symtab): Removed call to cp_initialize_namespace().
       (end_symtab): Removed call to cp_finalize_namespace().
       (push_context): Save and reset using_directives.
       * block.c (block_using): Return using directives for given
       block instead of static block.

diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..9ebe975 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -206,25 +206,16 @@ block_set_scope (struct block *block, const char *scope,
   BLOCK_NAMESPACE (block)->scope = scope;
 }
 
-/* This returns the first using directives associated to BLOCK, if
+/* This returns the using directives list associated with 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)
+  if (block == NULL || BLOCK_NAMESPACE (block) == NULL)
     return NULL;
   else
-    return BLOCK_NAMESPACE (static_block)->using;
+    return BLOCK_NAMESPACE (block)->using;
 }
 
 /* Set BLOCK's using member to USING; if needed, allocate memory via
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index e7c48fe..e6ef9c6 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -384,6 +384,8 @@ finish_block (struct symbol *symbol, struct pending **listhead,
       opblock = pblock;
     }
 
+  block_set_using (block, using_directives, &objfile->objfile_obstack);
+
   record_pending_block (objfile, block, opblock);
 
   return block;
@@ -812,10 +814,6 @@ start_symtab (char *name, char *dirname, CORE_ADDR start_addr)
   /* We shouldn't have any address map at this point.  */
   gdb_assert (! pending_addrmap);
 
-  /* Set up support for C++ namespace support, in case we need it.  */
-
-  cp_initialize_namespace ();
-
   /* Initialize the list of sub source files with one entry for this
      file (the top-level source file).  */
 
@@ -1012,8 +1010,6 @@ 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);
-      cp_finalize_namespace (BLOCKVECTOR_BLOCK (blockvector, STATIC_BLOCK),
-			     &objfile->objfile_obstack);
     }
 
   /* Read the line table if it has to be read separately.  */
@@ -1225,10 +1221,12 @@ push_context (int desc, CORE_ADDR valu)
   new->params = param_symbols;
   new->old_blocks = pending_blocks;
   new->start_addr = valu;
+  new->using_directives = using_directives;
   new->name = NULL;
 
   local_symbols = NULL;
   param_symbols = NULL;
+  using_directives = NULL;
 
   return new;
 }
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index bf23ecc..6f8b09f 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -125,6 +125,10 @@ EXTERN struct pending *local_symbols;
 
 EXTERN struct pending *param_symbols;
 
+/* "using" directives local to lexical context.  */
+
+EXTERN struct using_direct *using_directives;
+
 /* Stack representing unclosed lexical contexts (that will become
    blocks, eventually).  */
 
@@ -138,6 +142,10 @@ struct context_stack
 
     struct pending *params;
 
+    /* Pending using directives at the time we entered.  */
+
+    struct using_direct *using_directives;
+
     /* Pointer into blocklist as of entry */
 
     struct pending_block *old_blocks;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c6c5617..f3b2194 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -30,15 +30,7 @@
 #include "dictionary.h"
 #include "command.h"
 #include "frame.h"
-
-/* List of using directives that are active in the current file.  */
-
-static struct using_direct *using_list;
-
-static struct using_direct *cp_add_using (const char *name,
-					  unsigned int inner_len,
-					  unsigned int outer_len,
-					  struct using_direct *next);
+#include "buildsym.h"
 
 static struct using_direct *cp_copy_usings (struct using_direct *using,
 					    struct obstack *obstack);
@@ -78,31 +70,6 @@ static struct symbol *lookup_possible_namespace_symbol (const char *name);
 
 static void maintenance_cplus_namespace (char *args, int from_tty);
 
-/* Set up support for dealing with C++ namespace info in the current
-   symtab.  */
-
-void cp_initialize_namespace ()
-{
-  using_list = NULL;
-}
-
-/* Add all the using directives we've gathered to the current symtab.
-   STATIC_BLOCK should be the symtab's static block; OBSTACK is used
-   for allocation.  */
-
-void
-cp_finalize_namespace (struct block *static_block,
-		       struct obstack *obstack)
-{
-  if (using_list != NULL)
-    {
-      block_set_using (static_block,
-		       cp_copy_usings (using_list, obstack),
-		       obstack);
-      using_list = NULL;
-    }
-}
-
 /* Check to see if SYMBOL refers to an object contained within an
    anonymous namespace; if so, add an appropriate using directive.  */
 
@@ -170,7 +137,7 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 
   /* Has it already been added?  */
 
-  for (current = using_list; current != NULL; current = current->next)
+  for (current = using_directives; current != NULL; current = current->next)
     {
       if ((strncmp (current->inner, name, inner_length) == 0)
 	  && (strlen (current->inner) == inner_length)
@@ -178,8 +145,8 @@ cp_add_using_directive (const char *name, unsigned int outer_length,
 	return;
     }
 
-  using_list = cp_add_using (name, inner_length, outer_length,
-			     using_list);
+  using_directives = cp_add_using (name, inner_length, outer_length,
+                                   using_directives);
 }
 
 /* Record the namespace that the function defined by SYMBOL was
@@ -237,7 +204,7 @@ cp_is_anonymous (const char *namespace)
    using xmalloc.  It copies the strings, so NAME can be a temporary
    string.  */
 
-static struct using_direct *
+struct using_direct *
 cp_add_using (const char *name,
 	      unsigned int inner_len,
 	      unsigned int outer_len,
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 837ca6c..e577f7d 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -80,6 +80,11 @@ extern void cp_add_using_directive (const char *name,
 				    unsigned int outer_length,
 				    unsigned int inner_length);
 
+extern struct using_direct *cp_add_using (const char *name,
+					  unsigned int inner_len,
+					  unsigned int outer_len,
+					  struct using_direct *next);
+
 extern void cp_initialize_namespace (void);
 
 extern void cp_finalize_namespace (struct block *static_block,
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ae8870c..6569798 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -946,6 +946,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
 static void read_module (struct die_info *die, struct dwarf2_cu *cu);
 
+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
 static const char *namespace_name (struct die_info *die,
 				   int *is_anonymous, struct dwarf2_cu *);
 
@@ -2984,14 +2986,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
       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.  */
       processing_has_namespace_info = 1;
-      complaint (&symfile_complaints, _("unsupported tag: '%s'"),
-		 dwarf_tag_name (die->tag));
+      if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
+				 || cu->language != language_fortran))
+	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
+		   dwarf_tag_name (die->tag));
+      read_import_statement (die, cu);
       break;
     default:
       new_symbol (die, NULL, cu);
@@ -3037,6 +3037,69 @@ dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
   return name;
 }
 
+/* Read the import statement specified by the given die and record it.  */
+
+static void
+read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *import_attr;
+  struct die_info *imported_die;
+  const char *imported_name;
+  int is_anonymous = 0;
+
+  import_attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (import_attr == NULL)
+    {
+      complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+		 dwarf_tag_name (die->tag));
+      return;
+    }
+
+  imported_die = follow_die_ref (die, import_attr, &cu);
+  imported_name = dwarf2_name (imported_die, cu);
+  if (imported_name == NULL)
+    {
+      /* GCC bug: https://bugzilla.redhat.com/show_bug.cgi?id=506524
+
+        The import in the following code:
+        namespace A
+          {
+            typedef int B;
+          }
+
+        int main ()
+          {
+            using A::B;
+            B b;
+            return b;
+          }
+
+        ...
+         <2><51>: Abbrev Number: 3 (DW_TAG_imported_declaration)
+            <52>   DW_AT_decl_file   : 1
+            <53>   DW_AT_decl_line   : 6
+            <54>   DW_AT_import      : <0x75>
+         <2><58>: Abbrev Number: 4 (DW_TAG_typedef)
+            <59>   DW_AT_name        : B
+            <5b>   DW_AT_decl_file   : 1
+            <5c>   DW_AT_decl_line   : 2
+            <5d>   DW_AT_type        : <0x6e>
+        ...
+         <1><75>: Abbrev Number: 7 (DW_TAG_base_type)
+            <76>   DW_AT_byte_size   : 4
+            <77>   DW_AT_encoding    : 5        (signed)
+
+        imports the wrong die ( 0x75 instead of 0x58 ).
+        This case will be ignored until the gcc bug is fixed.  */
+      return;
+    }
+
+  /* FIXME: dwarf2_name (die); for the local name after import.  */
+
+  using_directives = cp_add_using (imported_name, strlen (imported_name), 0,
+                                   using_directives);
+}
+
 static void
 initialize_cu_func_list (struct dwarf2_cu *cu)
 {
@@ -3370,6 +3433,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
      back to building a containing block's symbol lists.  */
   local_symbols = new->locals;
   param_symbols = new->params;
+  using_directives = new->using_directives;
 
   /* If we've finished processing a top-level function, subsequent
      symbols go in the file symbol list.  */
@@ -3432,6 +3496,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       dwarf2_record_block_ranges (die, block, baseaddr, cu);
     }
   local_symbols = new->locals;
+  using_directives = new->using_directives;
 }
 
 /* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
new file mode 100644
index 0000000..4786fd5
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.cc
@@ -0,0 +1,45 @@
+namespace A
+{
+  int _a = 1;
+  int x = 2;
+}
+
+int marker4(){
+	using A::x;
+	return 0;
+}
+
+int marker3(){
+	return marker4();
+}
+
+int marker2()
+{
+  namespace B = A;
+  B::_a;
+  return marker3();
+}
+
+int marker1()
+{
+  int total = 0;
+  {
+    int b = 1;
+    {
+      using namespace A;
+      int c = 2;
+      {
+        int d = 3;
+        total = _a + b + c + d + marker2(); // marker1 stop
+      }
+    }
+  }
+  return total;
+}
+
+int main()
+{
+  using namespace A;
+  _a;
+  return marker1();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-using.exp b/gdb/testsuite/gdb.cp/namespace-using.exp
new file mode 100644
index 0000000..f24973f
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.exp
@@ -0,0 +1,87 @@
+# Copyright 2008 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
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-using
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+# test printing of namespace imported within
+# the function.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print _a" "= 1"
+
+############################################
+# test printing of namespace imported into 
+# a scope containing the pc.
+
+gdb_breakpoint [gdb_get_line_number "marker1 stop"]
+gdb_continue_to_breakpoint "marker1 stop"
+
+gdb_test "print _a" "= 1" "print _a in a nested scope"
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/7935" "*-*-*"
+if ![runto marker2] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+gdb_test "print B::a" "= 1"
+
+############################################
+# Test that names are not printed when they 
+# are not imported
+
+gdb_breakpoint "marker3"
+gdb_continue_to_breakpoint "marker3"
+
+gdb_test "print _a" "No symbol \"_a\" in current context." "Print a without import"
+
+############################################
+# Test printing of individually imported elements
+
+setup_kfail "gdb/7936" "*-*-*"
+if ![runto marker4] then {
+    perror "couldn't run to breakpoint marker4"
+    continue
+}
+
+gdb_test "print x" "= 2"

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-06-19 19:43   ` Sami Wagiaalla
  2009-06-19 20:15     ` Sami Wagiaalla
@ 2009-06-19 21:33     ` Tom Tromey
  2009-06-19 21:44       ` Tom Tromey
  1 sibling, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2009-06-19 21:33 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: GDB Patches

>>>>> "Sami" == Sami Wagiaalla <swagiaal@redhat.com> writes:

Tom> Eww, buildsym is full of globals.  Not your problem :-), but yet
Tom> another thing that would be nice to clean up.

Sami> There is a nice clean up for this suggested by Jan. That is using the
Sami> variables in the current context object and automating saving/and
Sami> restoration of that. I'll post a patch if I get to it.

FWIW I would prefer a fuller cleanup.  This approach makes it sound
like there would still be one global -- but I don't see why we need
any globals at all.  At least, we don't need them in the dwarf reader;
I don't care as much whether the other readers have module-private
globals if that makes the change simpler.

Sami> This is a gcc bug. I filed it here:
Sami> https://bugzilla.redhat.com/show_bug.cgi?id=506524 and improved
Sami> the comment.  and improved the comment.

For future reference, it is better to file gcc bugs in the gcc
bugzilla.  They are more likely to be seen there.

Also, for some reason in your messages, the patch shows up twice.
Does anybody else see that?

The version of this patch with the new test case is ok.
Thanks.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] namespace support
  2009-06-19 21:33     ` Tom Tromey
@ 2009-06-19 21:44       ` Tom Tromey
  0 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2009-06-19 21:44 UTC (permalink / raw)
  To: Sami Wagiaalla; +Cc: GDB Patches

>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:

Tom> The version of this patch with the new test case is ok.
Tom> Thanks.

I saw you didn't have write access, so I set you up with
write-after-approval access.

Tom


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-06-19 21:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-22 14:48 [PATCH 1/2] namespace support Sami Wagiaalla
2009-06-02 15:13 ` Sami Wagiaalla
2009-06-05  0:27 ` Tom Tromey
2009-06-19 19:43   ` Sami Wagiaalla
2009-06-19 20:15     ` Sami Wagiaalla
2009-06-19 21:33     ` Tom Tromey
2009-06-19 21:44       ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox