This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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" }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]