gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 27 Apr 2009 08:36:17 +0000 (08:36 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 27 Apr 2009 08:36:17 +0000 (08:36 +0000)
PR gdb/9675:
* dwarf2read.c (unsigned_int_compar, inherit_abstract_dies): New.
(read_func_scope): Call inherit_abstract_dies.

gdb/testsuite/
* gdb.cp/abstract-origin.exp, gdb.cp/abstract-origin.cc: New test.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.cp/abstract-origin.cc [new file with mode: 0644]
gdb/testsuite/gdb.cp/abstract-origin.exp [new file with mode: 0644]

index 44d76e3215da12f8cb0e744ee8a419ddb89ae409..32622b4ae717d93aadb84a9b0b4af98ad7efd085 100644 (file)
@@ -1,3 +1,9 @@
+2009-04-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       PR gdb/9675:
+       * dwarf2read.c (unsigned_int_compar, inherit_abstract_dies): New.
+       (read_func_scope): Call inherit_abstract_dies.
+
 2009-04-25  Eli Zaretskii  <eliz@gnu.org>
 
        * Makefile.in (ALLDEPFILES): Remove duplicate entries for
index c3f38385882cc3977ff0eb1632a052807b346463..ee1490d61c7c26181a51e789a567d6f51d99ca62 100644 (file)
@@ -3089,6 +3089,103 @@ add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
   cu->last_fn = thisfn;
 }
 
+/* qsort helper for inherit_abstract_dies.  */
+
+static int
+unsigned_int_compar (const void *ap, const void *bp)
+{
+  unsigned int a = *(unsigned int *) ap;
+  unsigned int b = *(unsigned int *) bp;
+
+  return (a > b) - (b > a);
+}
+
+/* DW_AT_abstract_origin inherits whole DIEs (not just their attributes).
+   Inherit only the children of the DW_AT_abstract_origin DIE not being already
+   referenced by DW_AT_abstract_origin from the children of the current DIE.  */
+
+static void
+inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct die_info *child_die;
+  unsigned die_children_count;
+  /* CU offsets which were referenced by children of the current DIE.  */
+  unsigned *offsets;
+  unsigned *offsets_end, *offsetp;
+  /* Parent of DIE - referenced by DW_AT_abstract_origin.  */
+  struct die_info *origin_die;
+  /* Iterator of the ORIGIN_DIE children.  */
+  struct die_info *origin_child_die;
+  struct cleanup *cleanups;
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+  if (!attr)
+    return;
+
+  origin_die = follow_die_ref (die, attr, &cu);
+  if (die->tag != origin_die->tag)
+    complaint (&symfile_complaints,
+              _("DIE 0x%x and its abstract origin 0x%x have different tags"),
+              die->offset, origin_die->offset);
+
+  child_die = die->child;
+  die_children_count = 0;
+  while (child_die && child_die->tag)
+    {
+      child_die = sibling_die (child_die);
+      die_children_count++;
+    }
+  offsets = xmalloc (sizeof (*offsets) * die_children_count);
+  cleanups = make_cleanup (xfree, offsets);
+
+  offsets_end = offsets;
+  child_die = die->child;
+  while (child_die && child_die->tag)
+    {
+      attr = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+      /* According to DWARF3 3.3.8.2 #3 new entries without their abstract
+        counterpart may exist.  */
+      if (attr)
+       {
+         struct die_info *child_origin_die;
+
+         child_origin_die = follow_die_ref (child_die, attr, &cu);
+         if (child_die->tag != child_origin_die->tag)
+           complaint (&symfile_complaints,
+                      _("Child DIE 0x%x and its abstract origin 0x%x have "
+                        "different tags"), child_die->offset,
+                      child_origin_die->offset);
+         *offsets_end++ = child_origin_die->offset;
+       }
+      child_die = sibling_die (child_die);
+    }
+  qsort (offsets, offsets_end - offsets, sizeof (*offsets),
+        unsigned_int_compar);
+  for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++)
+    if (offsetp[-1] == *offsetp)
+      complaint (&symfile_complaints, _("Multiple children of DIE 0x%x refer "
+                                       "to DIE 0x%x as their abstract origin"),
+                die->offset, *offsetp);
+
+  offsetp = offsets;
+  origin_child_die = origin_die->child;
+  while (origin_child_die && origin_child_die->tag)
+    {
+      /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children?  */
+      while (offsetp < offsets_end && *offsetp < origin_child_die->offset)
+       offsetp++;
+      if (offsetp >= offsets_end || *offsetp > origin_child_die->offset)
+       {
+         /* Found that ORIGIN_CHILD_DIE is really not referenced.  */
+         process_die (origin_child_die, cu);
+       }
+      origin_child_die = sibling_die (origin_child_die);
+    }
+
+  do_cleanups (cleanups);
+}
+
 static void
 read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
@@ -3147,6 +3244,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
        }
     }
 
+  inherit_abstract_dies (die, cu);
+
   new = pop_context ();
   /* Make a block for the local symbols within.  */
   block = finish_block (new->name, &local_symbols, new->old_blocks,
index 1bb8743c8a8f371aa15e836602cc84ed4011991f..fac1f1970c341ab7024f9fa634ce66432761ccf3 100644 (file)
@@ -1,3 +1,7 @@
+2009-04-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+       * gdb.cp/abstract-origin.exp, gdb.cp/abstract-origin.cc: New test.
+
 2009-04-22  Joseph Myers  <joseph@codesourcery.com>
 
        * lib/gdb.exp (get_compiler_info): Use -E -o in remote-host case.
diff --git a/gdb/testsuite/gdb.cp/abstract-origin.cc b/gdb/testsuite/gdb.cp/abstract-origin.cc
new file mode 100644 (file)
index 0000000..9621ed6
--- /dev/null
@@ -0,0 +1,42 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.
+   */
+
+extern void f (int *);
+
+class A
+{
+public:
+  A(int i);
+};
+
+A::A(int i)
+{
+  static int *problem = new int(i);
+  f (problem);                         /* break-here */
+}
+
+void f (int *)
+{
+}
+
+int
+main (void)
+{
+  A a(42);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.cp/abstract-origin.exp b/gdb/testsuite/gdb.cp/abstract-origin.exp
new file mode 100644 (file)
index 0000000..9ba1194
--- /dev/null
@@ -0,0 +1,31 @@
+# Copyright 2009 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/>.
+
+set testfile abstract-origin
+set srcfile ${testfile}.cc
+if [prepare_for_testing $testfile.exp $testfile $srcfile {debug c++}] {
+    return -1
+}
+
+if ![runto_main] {
+    untested abstract-origin
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here"
+
+# The Bug was: No symbol "problem" in current context.
+gdb_test "p problem" " = \\(int \\*\\) 0x.*"