This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: using directive patch


Here is a second version of the patch after incorporating the suggestions and adding a test case.

I should also explain what the patch is doing:

Traditionally gdb only supported using directives only for anonymous name spaces. It did that by adding to the static block (block representing compilation unit scope) a list of using directives which state that namespace x is visible in scope y.

This patch make it so that every block not just the static block can own a list of using directives. That list states that namespace x is visible in 'this' block. The patch also initializes this list during the exploration of dies.

During the exploration of the die tree, when a new scope is started the context corresponding to the parent still unfinished scope is pushed into a context stack (i.e. local variables and parameters for the outer scope are saved aside until the exploration of the current one is done) once the current scope is finished the information is saved in a block object and the parent context is restored (poped). This patch add initialization of using directives parallel to the pattern described above.

this patch can be seen on the branch origin/archer-swagiaal-using-directive

git branch archer-swagiaal-using-directive origin/archer-swagiaal-using-directive
diff --git a/ChangeLog b/ChangeLog
index 5114518..3258557 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2008-09-09  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* dwarf2read.c (process_die): Added call to
+	read_import_statement to the appropriate dies.
+	(read_import_statement): New function.
+	(read_func_scope): Resets the using directives from saved
+	context.	
+	* cp-namespace.c: Changed cp_adding_using to extern.
+	Moved cp_adding_using prototype from here...
+	* cp-support.h: ...to here.
+	* buildsym.h: Add global variable using_directives.
+	Added using_directives variable to context struct.
+	Added extern prototype for
+	* buildsym.c (finish_block): Set using directives for
+	the block, and reset the global variable.
+	(push_context): Save and reset using_directives.
+	* block.c (block_using): Return using directives for
+	the given block instead of its owning static block.
+
 2008-08-31  Aaron W. LaFramboise  <aaronavay62@aaronwl.com>
 
 	* configure.ac (RPATH_ENVVAR): Use PATH on Windows.
diff --git a/gdb/block.c b/gdb/block.c
index 58dcf72..45c10bf 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -207,24 +207,16 @@ block_set_scope (struct block *block, const char *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.  */
+   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 1945c22..171d5d0 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;
@@ -1202,10 +1204,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 294bc41..189fcec 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 4b45f6c..5830af6 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -35,11 +35,6 @@
 
 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);
-
 static struct using_direct *cp_copy_usings (struct using_direct *using,
 					    struct obstack *obstack);
 
@@ -237,7 +232,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 a004783..ce34022 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 1b68e2a..1d82944 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -937,6 +937,8 @@ static void read_common_block (struct die_info *, struct dwarf2_cu *);
 
 static void read_namespace (struct die_info *die, struct dwarf2_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 *);
 
@@ -2756,14 +2758,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);
@@ -2809,6 +2809,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)
 {
@@ -3043,6 +3075,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.  */
@@ -3105,6 +3138,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 f078b70..88d233a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-09-09  Sami Wagiaalla  <swagiaal@redhat.com>
+
+	* gdb.cp/namespace-using.cc: New test.
+	* gdb.cp/namespace-using.exp: New test.
+
 2008-09-09  Pedro Alves  <pedro@codesourcery.com>
 
 	* gdb.base/hook-stop-continue.c: New.
diff --git a/gdb/testsuite/gdb.cp/namespace-using.cc b/gdb/testsuite/gdb.cp/namespace-using.cc
new file mode 100644
index 0000000..562e50d
--- /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..9e161ba
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-using.exp
@@ -0,0 +1,135 @@
+# 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
+}
+
+send_gdb "print a\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = 1" { pass "print a test1" }
+   -re ".*$gdb_prompt $" { fail "print a test1" }
+   timeout { fail "(timeout) print a" }
+}
+
+# Test that names are not printed when they 
+# are not imported
+
+send_gdb "break marker3\n"
+gdb_continue_to_breakpoint "marker3"
+
+send_gdb "print a\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = 1" { fail "print a" }
+   -re ".*$gdb_prompt $" { pass "print a" }
+   timeout { fail "(timeout) print a" }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+############################################
+# test printing of namespace imported into 
+# a scope containing the pc.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "marker1 stop"]
+gdb_continue_to_breakpoint "marker1 stop"
+
+send_gdb "print a\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = 1" { pass "print a" }
+   -re ".*$gdb_prompt $" { fail "print a" }
+   timeout { fail "(timeout) print a" }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/380" "*-*-*"
+if ![runto marker2] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+send_gdb "print B::a\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = 1" { pass "print B::a" }
+   -re ".*$gdb_prompt $" { fail "print B::a" }
+   timeout { fail "(timeout) print B::a" }
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+
+############################################
+# Test printing of namespace aliases
+
+setup_kfail "gdb/381" "*-*-*"
+if ![runto marker4] then {
+    perror "couldn't run to breakpoint marker2"
+    continue
+}
+
+send_gdb "print x\n"
+gdb_expect {
+   -re "\\$\[0-9\]* = 2" { pass "print x" }
+   -re ".*$gdb_prompt $" { fail "print x" }
+   timeout { fail "(timeout) print x" }
+}
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]