[commit] Delay reading of struct members

Daniel Jacobowitz dan@codesourcery.com
Wed Sep 8 20:39:00 GMT 2010


Our DWARF-2 type reading has two phases.  We read the type itself in
whatever order we come across it (read_type_die), and then we create a
symbol for the type when our depth-first walk of the DIE tree reaches
its DIE (process_die).

We already rely on doing both steps for types; for instance, we don't
add the list of enumerators to an enumeration type until we've reached
the type via process_die.  This patch does something similar for
structures.  Now, we don't add fields or member functions during type
reading, only during DIE processing.

I made this change for the benefit of template parameters.  From the
included test case:

template<class C> class Empty
{
};

template<class C> class FunctionArg
{
public:
  int method(Empty<void (FunctionArg<C>)> &);
};

Suppose we've got a compiler which emits
DW_TAG_template_type_parameter, and doesn't also put template
parameters into DW_AT_name.  ARM's RealView is such a compiler; you
can achieve the same effect by manually removing the "<...>" bits from
GCC's assembler output.

We happen to encounter Empty<void (FunctionArg<int>)> first.  We
create an empty type, but we can not assign the type to the die
(set_die_type) until we know the type's name.  To figure out the
type's name, we have to recurse through the function type to
FunctionArg<int>.  We can easily work out the name of this type,
and then we finish it up by processing its methods.  This takes us to
"method", and back around to the DIE for the Empty<void
(FunctionArg<int>)> type that we've already started on.  We haven't
registered its type in the hash table yet, though, so we don't know
we've started on it!

Things go bad from there because we've started processing the DIE
for "void (FunctionArg<C>)" but we haven't finished it yet, so the
type of the first argument is a NULL pointer.

I've tested this on x86_64-linux and arm-eabi, using GCC 4.4, GCC 4.5,
and RealView; I also tested it on hand-modified GCC output to trigger
the template argument support.  No regressions; committed to HEAD.

-- 
Daniel Jacobowitz
CodeSourcery

2010-09-08  Daniel Jacobowitz  <dan@codesourcery.com>

	* dwarf2read.c (read_structure_type): Move processing of
	fields and member functions from here...
	(process_structure_scope): ... to here.

2010-09-08  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.cp/templates.cc (Empty, FunctionArg): New classes.
	(FunctionArg::method): New function.
	(empty, arg): New variables.
	(main): Call arg.method.
	* gdb.cp/templates.exp (test_template_args): New function.
	(do_tests): Call it.

Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.450
diff -u -p -r1.450 dwarf2read.c
--- dwarf2read.c	1 Sep 2010 21:50:24 -0000	1.450
+++ dwarf2read.c	8 Sep 2010 17:28:44 -0000
@@ -6677,11 +6677,12 @@ quirk_gcc_member_function_pointer (struc
 }
 
 /* Called when we find the DIE that starts a structure or union scope
-   (definition) to process all dies that define the members of the
-   structure or union.
+   (definition) to create a type for the structure or union.  Fill in
+   the type's name and general properties; the members will not be
+   processed until process_structure_type.
 
-   NOTE: we need to call struct_type regardless of whether or not the
-   DIE has an at_name attribute, since it might be an anonymous
+   NOTE: we need to call these functions regardless of whether or not the
+   DIE has a DW_AT_name attribute, since it might be an anonymous
    structure or union.  This gets the type entered into our set of
    user defined types.
 
@@ -6699,7 +6700,6 @@ read_structure_type (struct die_info *di
   struct type *type;
   struct attribute *attr;
   char *name;
-  struct cleanup *back_to;
 
   /* If the definition of this type lives in .debug_types, read that type.
      Don't follow DW_AT_specification though, that will take us back up
@@ -6721,8 +6721,6 @@ read_structure_type (struct die_info *di
       return set_die_type (die, type, cu);
     }
 
-  back_to = make_cleanup (null_cleanup, 0);
-
   type = alloc_type (objfile);
   INIT_CPLUS_SPECIFIC (type);
 
@@ -6797,11 +6795,29 @@ read_structure_type (struct die_info *di
   /* set_die_type should be already done.  */
   set_descriptive_type (type, die, cu);
 
+  return type;
+}
+
+/* Finish creating a structure or union type, including filling in
+   its members and creating a symbol for it.  */
+
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct die_info *child_die = die->child;
+  struct type *type;
+
+  type = get_die_type (die, cu);
+  if (type == NULL)
+    type = read_structure_type (die, cu);
+
   if (die->child != NULL && ! die_is_declaration (die, cu))
     {
       struct field_info fi;
       struct die_info *child_die;
       VEC (symbolp) *template_args = NULL;
+      struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
       memset (&fi, 0, sizeof (struct field_info));
 
@@ -6952,24 +6968,12 @@ read_structure_type (struct die_info *di
 	      *dest = *src;
 	    }
 	}
+
+      do_cleanups (back_to);
     }
 
   quirk_gcc_member_function_pointer (type, cu->objfile);
 
-  do_cleanups (back_to);
-  return type;
-}
-
-static void
-process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
-{
-  struct die_info *child_die = die->child;
-  struct type *this_type;
-
-  this_type = get_die_type (die, cu);
-  if (this_type == NULL)
-    this_type = read_structure_type (die, cu);
-
   /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
      snapshots) has been known to create a die giving a declaration
      for a class that has, as a child, a die giving a definition for a
@@ -6998,7 +7002,7 @@ process_structure_scope (struct die_info
      attribute, and a declaration attribute.  */
   if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
       || !die_is_declaration (die, cu))
-    new_symbol (die, this_type, cu);
+    new_symbol (die, type, cu);
 }
 
 /* Given a DW_AT_enumeration_type die, set its type.  We do not
Index: testsuite/gdb.cp/templates.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/templates.cc,v
retrieving revision 1.4
diff -u -p -r1.4 templates.cc
--- testsuite/gdb.cp/templates.cc	28 Dec 2009 21:45:24 -0000	1.4
+++ testsuite/gdb.cp/templates.cc	8 Sep 2010 18:48:55 -0000
@@ -712,6 +712,23 @@ template<class T> T Garply<T>::garply (i
     }
 }
 
+template<class C> class Empty
+{
+};
+
+template<class C> class FunctionArg
+{
+public:
+  int method(Empty<void (FunctionArg<C>)> &);
+};
+
+template<class C> int FunctionArg<C>::method(Empty<void (FunctionArg<C>)> &arg)
+{
+  return 75;
+}
+
+Empty<void(FunctionArg<int>)> empty;
+FunctionArg<int> arg;
 
 int main()
 {
@@ -785,18 +802,7 @@ int main()
 
   t5i.value();
 
+  arg.method(empty);
+
   return 0;
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
Index: testsuite/gdb.cp/templates.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/templates.exp,v
retrieving revision 1.26
diff -u -p -r1.26 templates.exp
--- testsuite/gdb.cp/templates.exp	2 Jun 2010 20:03:16 -0000	1.26
+++ testsuite/gdb.cp/templates.exp	8 Sep 2010 18:48:55 -0000
@@ -196,6 +196,16 @@ proc test_template_typedef {} {
 	"print destructor of template typedef"
 }
 
+proc test_template_args {} {
+
+    set empty_re "Empty *<void *\\(FunctionArg *<int>\\)>"
+    gdb_test "ptype empty" \
+	"type = class $empty_re {.*<no data fields>.*}"
+
+    gdb_test "ptype arg" \
+	"type = class FunctionArg<int> {.*int method\\($empty_re \\&\\);.*}"
+}
+
 proc do_tests {} {
     global subdir
     global objdir
@@ -220,6 +230,7 @@ proc do_tests {} {
     test_ptype_of_templates
     test_template_breakpoints
     test_template_typedef
+    test_template_args
 
     if [ runto_main] {
 	test_template_calls



More information about the Gdb-patches mailing list