This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[rfa+6.1]: Revised patch for PR c++/1553
- From: David Carlton <carlton at kealia dot com>
- To: gdb-patches at sources dot redhat dot com
- Cc: Elena Zannoni <ezannoni at redhat dot com>, Jim Blandy <jimb at redhat dot com>, Daniel Jacobowitz <drow at mvista dot com>
- Date: Mon, 08 Mar 2004 09:29:04 -0800
- Subject: [rfa+6.1]: Revised patch for PR c++/1553
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 <carlton@kealia.com>
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 <carlton@kealia.com>
* 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 : "<<anonymous>>");
+ }
+
+ 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,
- "<<anonymous class>>");
+ 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" }
}