From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14063 invoked by alias); 8 Mar 2004 17:29:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 14020 invoked from network); 8 Mar 2004 17:29:24 -0000 Received: from unknown (HELO coconut.kealia.com) (209.3.10.89) by sources.redhat.com with SMTP; 8 Mar 2004 17:29:24 -0000 Received: from coconut.kealia.com (localhost.localdomain [127.0.0.1]) by coconut.kealia.com (8.12.8/8.12.8) with ESMTP id i28HT5SH025828; Mon, 8 Mar 2004 09:29:06 -0800 Received: (from carlton@localhost) by coconut.kealia.com (8.12.8/8.12.8/Submit) id i28HT52d025826; Mon, 8 Mar 2004 09:29:05 -0800 X-Authentication-Warning: coconut.kealia.com: carlton set sender to carlton@kealia.com using -f To: gdb-patches@sources.redhat.com Cc: Elena Zannoni , Jim Blandy , Daniel Jacobowitz Subject: [rfa+6.1]: Revised patch for PR c++/1553 From: David Carlton Date: Mon, 08 Mar 2004 17:29:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2004-03.o/txt/msg00160.txt Here's a revision for my patch for PR c++/1553 that I posted a couple of weeks ago. The stuff that was in that patch hasn't changed (except for syncing it up with current sources), but this version also includes changes to determine_prefix. Specifically, it fixes a bug in that code that Daniel pointed out, and it rewrites determine_prefix to use my new determine_class_name function (so that all the class name lookup stuff is in one place) and to look at TYPE_TAG_NAME (to avoid recalculating the same name over and over again if possible). The determine_prefix stuff could be a separate patch from my earlier changes; I just wanted to get it submitted now because it's possible that there will be a hiccup in my copyright assignment. Also, it seems like a good idea to get patches into 6.1 as early as possible, to increase the amount of testing that they'll get. I couldn't come up with any test cases for the new part of the patch; it depends very much on how the compiler is generating output. :-( Tested on i686-pc-linux-gnu, DWARF-2, several different GCC versions. Ok for mainline and 6.1? David Carlton carlton@kealia.com 2004-03-08 David Carlton Fix for PR c++/1553: * dwarf2read.c (read_structure_scope): Determine type name by calling determine_class_name. (determine_class_name): New. (determine_prefix): Look at TYPE_TAG_NAME and call determine_class_name when appropriate. (determine_prefix_aux, class_name): Delete. 2004-03-05 David Carlton * gdb.cp/pr-1553.exp: New. Tests for PR c++/1553. * gdb.cp/pr-1553.cc: Ditto. * gdb.cp/local.exp (ptype NestedInnerLocal): Add comment, third pass branch. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.136 diff -u -p -r1.136 dwarf2read.c --- dwarf2read.c 5 Mar 2004 03:30:36 -0000 1.136 +++ dwarf2read.c 8 Mar 2004 17:18:57 -0000 @@ -779,12 +779,8 @@ static void read_type_die (struct die_in static char *determine_prefix (struct die_info *die, struct dwarf2_cu *); -static char *determine_prefix_aux (struct die_info *die, struct dwarf2_cu *); - static char *typename_concat (const char *prefix, const char *suffix); -static char *class_name (struct die_info *die, struct dwarf2_cu *); - static void read_typedef (struct die_info *, struct dwarf2_cu *); static void read_base_type (struct die_info *, struct dwarf2_cu *); @@ -819,6 +815,8 @@ static void dwarf2_attach_fn_fields_to_t static void read_structure_scope (struct die_info *, struct dwarf2_cu *); +static char *determine_class_name (struct die_info *die, struct dwarf2_cu *cu); + static void read_common_block (struct die_info *, struct dwarf2_cu *); static void read_namespace (struct die_info *die, struct dwarf2_cu *); @@ -3016,13 +3014,8 @@ read_structure_scope (struct die_info *d struct objfile *objfile = cu->objfile; struct type *type; struct attribute *attr; - char *name = NULL; const char *previous_prefix = processing_current_prefix; struct cleanup *back_to = NULL; - /* This says whether or not we want to try to update the structure's - name to include enclosing namespace/class information, if - any. */ - int need_to_update_name = 0; type = alloc_type (objfile); @@ -3030,41 +3023,20 @@ read_structure_scope (struct die_info *d attr = dwarf2_attr (die, DW_AT_name, cu); if (attr && DW_STRING (attr)) { - name = DW_STRING (attr); - if (cu->language == language_cplus) { - struct die_info *spec_die = die_specification (die, cu); - - if (spec_die != NULL) - { - char *specification_prefix = determine_prefix (spec_die, cu); - processing_current_prefix = specification_prefix; - back_to = make_cleanup (xfree, specification_prefix); - } - } - - if (processing_has_namespace_info) - { - /* FIXME: carlton/2003-11-10: This variable exists only for - const-correctness reasons. When I tried to change - TYPE_TAG_NAME to be a const char *, I ran into a cascade - of changes which would have forced decode_line_1 to take - a const char **. */ - char *new_prefix = obconcat (&objfile->objfile_obstack, - processing_current_prefix, - processing_current_prefix[0] == '\0' - ? "" : "::", - name); - TYPE_TAG_NAME (type) = new_prefix; + char *new_prefix = determine_class_name (die, cu); + TYPE_TAG_NAME (type) = obsavestring (new_prefix, + strlen (new_prefix), + &objfile->objfile_obstack); + back_to = make_cleanup (xfree, new_prefix); processing_current_prefix = new_prefix; } else { /* The name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ - TYPE_TAG_NAME (type) = name; - need_to_update_name = (cu->language == language_cplus); + TYPE_TAG_NAME (type) = DW_STRING (attr); } } @@ -3125,41 +3097,6 @@ read_structure_scope (struct die_info *d /* C++ member function. */ process_die (child_die, cu); dwarf2_add_member_fn (&fi, child_die, type, cu); - if (need_to_update_name) - { - /* The demangled names of member functions contain - information about enclosing namespaces/classes, - if any. */ - - /* FIXME: carlton/2003-11-10: The excessive - demangling here is a bit wasteful, as is the - memory usage for names. */ - - /* NOTE: carlton/2003-11-10: As commented in - add_partial_structure, the demangler sometimes - prints the type info in a different form from the - debug info. We could solve this by using the - demangled name to get the prefix; if doing so, - however, we'd need to be careful when reading a - class that's nested inside a template class. - That would also cause problems when trying to - determine RTTI information, since we use the - demangler to determine the appropriate class - name. */ - char *actual_class_name - = class_name_from_physname (dwarf2_linkage_name - (child_die, cu)); - if (actual_class_name != NULL - && strcmp (actual_class_name, name) != 0) - { - TYPE_TAG_NAME (type) - = obsavestring (actual_class_name, - strlen (actual_class_name), - &objfile->objfile_obstack); - } - xfree (actual_class_name); - need_to_update_name = 0; - } } else if (child_die->tag == DW_TAG_inheritance) { @@ -3241,6 +3178,62 @@ read_structure_scope (struct die_info *d do_cleanups (back_to); } +/* Determine the name of the type represented by DIE, which should be + a named C++ compound type. Return the name in question; the caller + is responsible for xfree()'ing it. */ + +static char * +determine_class_name (struct die_info *die, struct dwarf2_cu *cu) +{ + struct cleanup *back_to = NULL; + struct die_info *spec_die = die_specification (die, cu); + char *new_prefix = NULL; + + /* If this is the definition of a class that is declared by another + die, then processing_current_prefix may not be accurate; see + read_func_scope for a similar example. */ + if (spec_die != NULL) + { + char *specification_prefix = determine_prefix (spec_die, cu); + processing_current_prefix = specification_prefix; + back_to = make_cleanup (xfree, specification_prefix); + } + + /* If we don't have namespace debug info, guess the name by trying + to demangle the names of members, just like we did in + add_partial_structure. */ + if (!processing_has_namespace_info) + { + struct die_info *child; + + for (child = die->child; + child != NULL && child->tag != 0; + child = sibling_die (child)) + { + if (child->tag == DW_TAG_subprogram) + { + new_prefix = class_name_from_physname (dwarf2_linkage_name + (child, cu)); + + if (new_prefix != NULL) + break; + } + } + } + + if (new_prefix == NULL) + { + const char *name = dwarf2_name (die, cu); + new_prefix = typename_concat (processing_current_prefix, + name ? name : "<>"); + } + + if (back_to != NULL) + do_cleanups (back_to); + + return new_prefix; +} + /* Given a pointer to a die which begins an enumeration, process all the dies that define the members of the enumeration. @@ -3529,6 +3522,7 @@ read_namespace (struct die_info *die, st TYPE_TAG_NAME (type) = TYPE_NAME (type); new_symbol (die, type, cu); + die->type = type; if (is_anonymous) cp_add_using_directive (processing_current_prefix, @@ -6086,18 +6080,6 @@ read_type_die (struct die_info *die, str static char * determine_prefix (struct die_info *die, struct dwarf2_cu *cu) { - char *prefix = determine_prefix_aux (die, cu); - - return prefix ? prefix : xstrdup (""); -} - -/* Return the name of the namespace/class that DIE is defined - within, or NULL if we can't tell. The caller should xfree the - result. */ - -static char * -determine_prefix_aux (struct die_info *die, struct dwarf2_cu *cu) -{ struct die_info *parent; if (cu->language != language_cplus) @@ -6107,49 +6089,55 @@ determine_prefix_aux (struct die_info *d if (parent == NULL) { - return (processing_has_namespace_info ? xstrdup ("") : NULL); + return xstrdup (""); } else { - char *parent_prefix = determine_prefix_aux (parent, cu); - char *retval; - switch (parent->tag) { case DW_TAG_namespace: { - int dummy; - - retval = typename_concat (parent_prefix, - namespace_name (parent, &dummy, cu)); + // FIXME: carlton/2004-03-05: Should I follow extension dies + // before doing this check? + if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL) + { + return xstrdup (TYPE_TAG_NAME (parent->type)); + } + else + { + int dummy; + char *parent_prefix = determine_prefix (parent, cu); + char *retval = typename_concat (parent_prefix, + namespace_name (parent, &dummy, + cu)); + xfree (parent_prefix); + return retval; + } } break; case DW_TAG_class_type: case DW_TAG_structure_type: { - if (parent_prefix != NULL) + if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL) { - const char *parent_name = dwarf2_name (parent, cu); - - if (parent_name != NULL) - retval = typename_concat (parent_prefix, dwarf2_name (parent, cu)); - else - /* FIXME: carlton/2003-11-10: I'm not sure what the - best thing to do here is. */ - retval = typename_concat (parent_prefix, - "<>"); + return xstrdup (TYPE_TAG_NAME (parent->type)); } else - retval = class_name (parent, cu); + { + const char *old_prefix = processing_current_prefix; + char *new_prefix = determine_prefix (parent, cu); + char *retval; + + processing_current_prefix = new_prefix; + retval = determine_class_name (parent, cu); + processing_current_prefix = old_prefix; + + xfree (new_prefix); + return retval; + } } - break; default: - retval = parent_prefix; - break; + return determine_prefix (parent, cu); } - - if (retval != parent_prefix) - xfree (parent_prefix); - return retval; } } @@ -6172,28 +6160,6 @@ typename_concat (const char *prefix, con return retval; } -} - -/* Return a newly-allocated string giving the name of the class given - by DIE. */ - -static char * -class_name (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child; - const char *name; - - for (child = die->child; child != NULL; child = sibling_die (child)) - { - if (child->tag == DW_TAG_subprogram) - return class_name_from_physname (dwarf2_linkage_name (child, cu)); - } - - name = dwarf2_name (die, cu); - if (name != NULL) - return xstrdup (name); - else - return xstrdup (""); } static struct type * --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ pr-1553.exp 2004-02-24 10:00:13.000000000 -0800 @@ -0,0 +1,62 @@ +# Copyright 2004 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Test for PR gdb/1553. + +# This file is part of the gdb testsuite. + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + +if { [skip_cplus_tests] } { continue } + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "pr-1553" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile} "c++"] { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +gdb_test "ptype c_var" "type = class A::C \{${ws}private:${ws}int a_c;${ws}\} \\*" + +gdb_test "ptype E::F" "type = class E::F \{${ws}public:${ws}int e_f;${ws}E::F & operator=\\(E::F const ?&\\);${ws}\}" + +gdb_exit +return 0 --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ pr-1553.cc 2004-02-24 09:48:02.000000000 -0800 @@ -0,0 +1,53 @@ +class A { +public: + class B; + class C; +}; + +class A::B { + int a_b; + +public: + C* get_c(int i); +}; + +class A::C +{ + int a_c; +}; + +class E { +public: + class F; +}; + +class E::F { +public: + int e_f; + + F& operator=(const F &other); +}; + +void refer_to (E::F *f) { + // Do nothing. +} + +void refer_to (A::C **ref) { + // Do nothing. But, while we're at it, force out debug info for + // A::B and E::F. + + A::B b; + E::F f; + + refer_to (&f); +} + +int main () { + A::C* c_var; + A::B* b_var; + E *e_var; + + // Keep around a reference so that GCC 3.4 doesn't optimize the variable + // away. + refer_to (&c_var); +} Index: local.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/local.exp,v retrieving revision 1.5 diff -u -p -r1.5 local.exp --- local.exp 11 Feb 2004 14:01:25 -0000 1.5 +++ local.exp 24 Feb 2004 17:10:00 -0000 @@ -263,10 +263,20 @@ gdb_expect { # # chastain 2002-04-08 +# NOTE (2004-02-24, carlton): This test really is invalid - +# 'NestedInnerLocal' shouldn't be visible, so only the third +# expression should count as a pass. I'm leaving in the earlier +# passes, however, given the current problematic state of our local +# class support, but once we fix PR gdb/482, we should delete this +# test. + send_gdb "ptype NestedInnerLocal\n" gdb_expect { -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" } -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*NestedInnerLocal *& *operator *= *\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((void|)\\);\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" } + -re "No symbol \"NestedInnerLocal\" in current context\.\r\n$gdb_prompt $" { + pass "ptype NestedInnerLocal" + } -re ".*$gdb_prompt $" { fail "ptype NestedInnerLocal" } timeout { fail "(timeout) ptype NestedInnerLocal" } } From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14063 invoked by alias); 8 Mar 2004 17:29:27 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 14020 invoked from network); 8 Mar 2004 17:29:24 -0000 Received: from unknown (HELO coconut.kealia.com) (209.3.10.89) by sources.redhat.com with SMTP; 8 Mar 2004 17:29:24 -0000 Received: from coconut.kealia.com (localhost.localdomain [127.0.0.1]) by coconut.kealia.com (8.12.8/8.12.8) with ESMTP id i28HT5SH025828; Mon, 8 Mar 2004 09:29:06 -0800 Received: (from carlton@localhost) by coconut.kealia.com (8.12.8/8.12.8/Submit) id i28HT52d025826; Mon, 8 Mar 2004 09:29:05 -0800 X-Authentication-Warning: coconut.kealia.com: carlton set sender to carlton@kealia.com using -f To: gdb-patches@sources.redhat.com Cc: Elena Zannoni , Jim Blandy , Daniel Jacobowitz Subject: [rfa+6.1]: Revised patch for PR c++/1553 From: David Carlton Date: Fri, 19 Mar 2004 00:09:00 -0000 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2004-03/txt/msg00160.txt.bz2 Message-ID: <20040319000900.mOgoLZTXgGG_KZzN25racpEGWz4KFAM8B1bI3HhtExU@z> Here's a revision for my patch for PR c++/1553 that I posted a couple of weeks ago. The stuff that was in that patch hasn't changed (except for syncing it up with current sources), but this version also includes changes to determine_prefix. Specifically, it fixes a bug in that code that Daniel pointed out, and it rewrites determine_prefix to use my new determine_class_name function (so that all the class name lookup stuff is in one place) and to look at TYPE_TAG_NAME (to avoid recalculating the same name over and over again if possible). The determine_prefix stuff could be a separate patch from my earlier changes; I just wanted to get it submitted now because it's possible that there will be a hiccup in my copyright assignment. Also, it seems like a good idea to get patches into 6.1 as early as possible, to increase the amount of testing that they'll get. I couldn't come up with any test cases for the new part of the patch; it depends very much on how the compiler is generating output. :-( Tested on i686-pc-linux-gnu, DWARF-2, several different GCC versions. Ok for mainline and 6.1? David Carlton carlton@kealia.com 2004-03-08 David Carlton Fix for PR c++/1553: * dwarf2read.c (read_structure_scope): Determine type name by calling determine_class_name. (determine_class_name): New. (determine_prefix): Look at TYPE_TAG_NAME and call determine_class_name when appropriate. (determine_prefix_aux, class_name): Delete. 2004-03-05 David Carlton * gdb.cp/pr-1553.exp: New. Tests for PR c++/1553. * gdb.cp/pr-1553.cc: Ditto. * gdb.cp/local.exp (ptype NestedInnerLocal): Add comment, third pass branch. Index: dwarf2read.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2read.c,v retrieving revision 1.136 diff -u -p -r1.136 dwarf2read.c --- dwarf2read.c 5 Mar 2004 03:30:36 -0000 1.136 +++ dwarf2read.c 8 Mar 2004 17:18:57 -0000 @@ -779,12 +779,8 @@ static void read_type_die (struct die_in static char *determine_prefix (struct die_info *die, struct dwarf2_cu *); -static char *determine_prefix_aux (struct die_info *die, struct dwarf2_cu *); - static char *typename_concat (const char *prefix, const char *suffix); -static char *class_name (struct die_info *die, struct dwarf2_cu *); - static void read_typedef (struct die_info *, struct dwarf2_cu *); static void read_base_type (struct die_info *, struct dwarf2_cu *); @@ -819,6 +815,8 @@ static void dwarf2_attach_fn_fields_to_t static void read_structure_scope (struct die_info *, struct dwarf2_cu *); +static char *determine_class_name (struct die_info *die, struct dwarf2_cu *cu); + static void read_common_block (struct die_info *, struct dwarf2_cu *); static void read_namespace (struct die_info *die, struct dwarf2_cu *); @@ -3016,13 +3014,8 @@ read_structure_scope (struct die_info *d struct objfile *objfile = cu->objfile; struct type *type; struct attribute *attr; - char *name = NULL; const char *previous_prefix = processing_current_prefix; struct cleanup *back_to = NULL; - /* This says whether or not we want to try to update the structure's - name to include enclosing namespace/class information, if - any. */ - int need_to_update_name = 0; type = alloc_type (objfile); @@ -3030,41 +3023,20 @@ read_structure_scope (struct die_info *d attr = dwarf2_attr (die, DW_AT_name, cu); if (attr && DW_STRING (attr)) { - name = DW_STRING (attr); - if (cu->language == language_cplus) { - struct die_info *spec_die = die_specification (die, cu); - - if (spec_die != NULL) - { - char *specification_prefix = determine_prefix (spec_die, cu); - processing_current_prefix = specification_prefix; - back_to = make_cleanup (xfree, specification_prefix); - } - } - - if (processing_has_namespace_info) - { - /* FIXME: carlton/2003-11-10: This variable exists only for - const-correctness reasons. When I tried to change - TYPE_TAG_NAME to be a const char *, I ran into a cascade - of changes which would have forced decode_line_1 to take - a const char **. */ - char *new_prefix = obconcat (&objfile->objfile_obstack, - processing_current_prefix, - processing_current_prefix[0] == '\0' - ? "" : "::", - name); - TYPE_TAG_NAME (type) = new_prefix; + char *new_prefix = determine_class_name (die, cu); + TYPE_TAG_NAME (type) = obsavestring (new_prefix, + strlen (new_prefix), + &objfile->objfile_obstack); + back_to = make_cleanup (xfree, new_prefix); processing_current_prefix = new_prefix; } else { /* The name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ - TYPE_TAG_NAME (type) = name; - need_to_update_name = (cu->language == language_cplus); + TYPE_TAG_NAME (type) = DW_STRING (attr); } } @@ -3125,41 +3097,6 @@ read_structure_scope (struct die_info *d /* C++ member function. */ process_die (child_die, cu); dwarf2_add_member_fn (&fi, child_die, type, cu); - if (need_to_update_name) - { - /* The demangled names of member functions contain - information about enclosing namespaces/classes, - if any. */ - - /* FIXME: carlton/2003-11-10: The excessive - demangling here is a bit wasteful, as is the - memory usage for names. */ - - /* NOTE: carlton/2003-11-10: As commented in - add_partial_structure, the demangler sometimes - prints the type info in a different form from the - debug info. We could solve this by using the - demangled name to get the prefix; if doing so, - however, we'd need to be careful when reading a - class that's nested inside a template class. - That would also cause problems when trying to - determine RTTI information, since we use the - demangler to determine the appropriate class - name. */ - char *actual_class_name - = class_name_from_physname (dwarf2_linkage_name - (child_die, cu)); - if (actual_class_name != NULL - && strcmp (actual_class_name, name) != 0) - { - TYPE_TAG_NAME (type) - = obsavestring (actual_class_name, - strlen (actual_class_name), - &objfile->objfile_obstack); - } - xfree (actual_class_name); - need_to_update_name = 0; - } } else if (child_die->tag == DW_TAG_inheritance) { @@ -3241,6 +3178,62 @@ read_structure_scope (struct die_info *d do_cleanups (back_to); } +/* Determine the name of the type represented by DIE, which should be + a named C++ compound type. Return the name in question; the caller + is responsible for xfree()'ing it. */ + +static char * +determine_class_name (struct die_info *die, struct dwarf2_cu *cu) +{ + struct cleanup *back_to = NULL; + struct die_info *spec_die = die_specification (die, cu); + char *new_prefix = NULL; + + /* If this is the definition of a class that is declared by another + die, then processing_current_prefix may not be accurate; see + read_func_scope for a similar example. */ + if (spec_die != NULL) + { + char *specification_prefix = determine_prefix (spec_die, cu); + processing_current_prefix = specification_prefix; + back_to = make_cleanup (xfree, specification_prefix); + } + + /* If we don't have namespace debug info, guess the name by trying + to demangle the names of members, just like we did in + add_partial_structure. */ + if (!processing_has_namespace_info) + { + struct die_info *child; + + for (child = die->child; + child != NULL && child->tag != 0; + child = sibling_die (child)) + { + if (child->tag == DW_TAG_subprogram) + { + new_prefix = class_name_from_physname (dwarf2_linkage_name + (child, cu)); + + if (new_prefix != NULL) + break; + } + } + } + + if (new_prefix == NULL) + { + const char *name = dwarf2_name (die, cu); + new_prefix = typename_concat (processing_current_prefix, + name ? name : "<>"); + } + + if (back_to != NULL) + do_cleanups (back_to); + + return new_prefix; +} + /* Given a pointer to a die which begins an enumeration, process all the dies that define the members of the enumeration. @@ -3529,6 +3522,7 @@ read_namespace (struct die_info *die, st TYPE_TAG_NAME (type) = TYPE_NAME (type); new_symbol (die, type, cu); + die->type = type; if (is_anonymous) cp_add_using_directive (processing_current_prefix, @@ -6086,18 +6080,6 @@ read_type_die (struct die_info *die, str static char * determine_prefix (struct die_info *die, struct dwarf2_cu *cu) { - char *prefix = determine_prefix_aux (die, cu); - - return prefix ? prefix : xstrdup (""); -} - -/* Return the name of the namespace/class that DIE is defined - within, or NULL if we can't tell. The caller should xfree the - result. */ - -static char * -determine_prefix_aux (struct die_info *die, struct dwarf2_cu *cu) -{ struct die_info *parent; if (cu->language != language_cplus) @@ -6107,49 +6089,55 @@ determine_prefix_aux (struct die_info *d if (parent == NULL) { - return (processing_has_namespace_info ? xstrdup ("") : NULL); + return xstrdup (""); } else { - char *parent_prefix = determine_prefix_aux (parent, cu); - char *retval; - switch (parent->tag) { case DW_TAG_namespace: { - int dummy; - - retval = typename_concat (parent_prefix, - namespace_name (parent, &dummy, cu)); + // FIXME: carlton/2004-03-05: Should I follow extension dies + // before doing this check? + if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL) + { + return xstrdup (TYPE_TAG_NAME (parent->type)); + } + else + { + int dummy; + char *parent_prefix = determine_prefix (parent, cu); + char *retval = typename_concat (parent_prefix, + namespace_name (parent, &dummy, + cu)); + xfree (parent_prefix); + return retval; + } } break; case DW_TAG_class_type: case DW_TAG_structure_type: { - if (parent_prefix != NULL) + if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL) { - const char *parent_name = dwarf2_name (parent, cu); - - if (parent_name != NULL) - retval = typename_concat (parent_prefix, dwarf2_name (parent, cu)); - else - /* FIXME: carlton/2003-11-10: I'm not sure what the - best thing to do here is. */ - retval = typename_concat (parent_prefix, - "<>"); + return xstrdup (TYPE_TAG_NAME (parent->type)); } else - retval = class_name (parent, cu); + { + const char *old_prefix = processing_current_prefix; + char *new_prefix = determine_prefix (parent, cu); + char *retval; + + processing_current_prefix = new_prefix; + retval = determine_class_name (parent, cu); + processing_current_prefix = old_prefix; + + xfree (new_prefix); + return retval; + } } - break; default: - retval = parent_prefix; - break; + return determine_prefix (parent, cu); } - - if (retval != parent_prefix) - xfree (parent_prefix); - return retval; } } @@ -6172,28 +6160,6 @@ typename_concat (const char *prefix, con return retval; } -} - -/* Return a newly-allocated string giving the name of the class given - by DIE. */ - -static char * -class_name (struct die_info *die, struct dwarf2_cu *cu) -{ - struct die_info *child; - const char *name; - - for (child = die->child; child != NULL; child = sibling_die (child)) - { - if (child->tag == DW_TAG_subprogram) - return class_name_from_physname (dwarf2_linkage_name (child, cu)); - } - - name = dwarf2_name (die, cu); - if (name != NULL) - return xstrdup (name); - else - return xstrdup (""); } static struct type * --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ pr-1553.exp 2004-02-24 10:00:13.000000000 -0800 @@ -0,0 +1,62 @@ +# Copyright 2004 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 2 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +# Test for PR gdb/1553. + +# This file is part of the gdb testsuite. + +set ws "\[\r\n\t \]+" + +if $tracelevel then { + strace $tracelevel +} + +if { [skip_cplus_tests] } { continue } + +# +# test running programs +# +set prms_id 0 +set bug_id 0 + +set testfile "pr-1553" +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} + +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +if [get_compiler_info ${binfile} "c++"] { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + perror "couldn't run to breakpoint" + continue +} + +gdb_test "ptype c_var" "type = class A::C \{${ws}private:${ws}int a_c;${ws}\} \\*" + +gdb_test "ptype E::F" "type = class E::F \{${ws}public:${ws}int e_f;${ws}E::F & operator=\\(E::F const ?&\\);${ws}\}" + +gdb_exit +return 0 --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ pr-1553.cc 2004-02-24 09:48:02.000000000 -0800 @@ -0,0 +1,53 @@ +class A { +public: + class B; + class C; +}; + +class A::B { + int a_b; + +public: + C* get_c(int i); +}; + +class A::C +{ + int a_c; +}; + +class E { +public: + class F; +}; + +class E::F { +public: + int e_f; + + F& operator=(const F &other); +}; + +void refer_to (E::F *f) { + // Do nothing. +} + +void refer_to (A::C **ref) { + // Do nothing. But, while we're at it, force out debug info for + // A::B and E::F. + + A::B b; + E::F f; + + refer_to (&f); +} + +int main () { + A::C* c_var; + A::B* b_var; + E *e_var; + + // Keep around a reference so that GCC 3.4 doesn't optimize the variable + // away. + refer_to (&c_var); +} Index: local.exp =================================================================== RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/local.exp,v retrieving revision 1.5 diff -u -p -r1.5 local.exp --- local.exp 11 Feb 2004 14:01:25 -0000 1.5 +++ local.exp 24 Feb 2004 17:10:00 -0000 @@ -263,10 +263,20 @@ gdb_expect { # # chastain 2002-04-08 +# NOTE (2004-02-24, carlton): This test really is invalid - +# 'NestedInnerLocal' shouldn't be visible, so only the third +# expression should count as a pass. I'm leaving in the earlier +# passes, however, given the current problematic state of our local +# class support, but once we fix PR gdb/482, we should delete this +# test. + send_gdb "ptype NestedInnerLocal\n" gdb_expect { -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" } -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*NestedInnerLocal *& *operator *= *\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((void|)\\);\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" } + -re "No symbol \"NestedInnerLocal\" in current context\.\r\n$gdb_prompt $" { + pass "ptype NestedInnerLocal" + } -re ".*$gdb_prompt $" { fail "ptype NestedInnerLocal" } timeout { fail "(timeout) ptype NestedInnerLocal" } }