From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13175 invoked by alias); 8 Sep 2010 19:25:11 -0000 Received: (qmail 13158 invoked by uid 22791); 8 Sep 2010 19:25:09 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00,TW_BJ,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 08 Sep 2010 19:25:04 +0000 Received: (qmail 22079 invoked from network); 8 Sep 2010 19:25:02 -0000 Received: from unknown (HELO caradoc.them.org) (dan@127.0.0.2) by mail.codesourcery.com with ESMTPA; 8 Sep 2010 19:25:02 -0000 Date: Wed, 08 Sep 2010 20:39:00 -0000 From: Daniel Jacobowitz To: gdb-patches@sourceware.org Subject: [commit] Delay reading of struct members Message-ID: <20100908192459.GH28036@caradoc.them.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-09/txt/msg00188.txt.bz2 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 Empty { }; template class FunctionArg { public: int method(Empty)> &); }; 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)> 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. 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)> 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)" 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 * dwarf2read.c (read_structure_type): Move processing of fields and member functions from here... (process_structure_scope): ... to here. 2010-09-08 Daniel Jacobowitz * 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 T Garply::garply (i } } +template class Empty +{ +}; + +template class FunctionArg +{ +public: + int method(Empty)> &); +}; + +template int FunctionArg::method(Empty)> &arg) +{ + return 75; +} + +Empty)> empty; +FunctionArg 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 *\\)>" + gdb_test "ptype empty" \ + "type = class $empty_re {.*.*}" + + gdb_test "ptype arg" \ + "type = class FunctionArg {.*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