This is the mail archive of the gdb-patches@sourceware.org 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]

Re: RFC: handle case arising from GCC PR 47510


Tom> +	    struct die_info fake = *die;

Jan> fake.attrs are invalid now while being accessed by new_symbol.

Thanks, I forgot about that.

I fixed it by temporarily changing die->tag.

Tom> +++ b/gdb/testsuite/gdb.cp/anon-struct.cc
Jan> No copyright needed?

Fixed.

Tom> +public:
Tom> +  C() {}
Tom> +  ~C() {}

Jan> If the destructor is not present maybe_smash_one_typedef() will not
Jan> work.  And GDB crashes now due to it, that should be
Jan> sanity-protected anyway.

The class C is not the problem in this test case.  I think C just exists
to make sure that the "anonymous" struct is not a POD.

maybe_smash_one_typedef won't be called for C, because C has a name.

I don't understand about GDB crashing now due to C.

Jan> I would remove the intermediate type `S', it was there fore more
Jan> illustrative purposes.

Done.

Jan> I do not fully grok this change, it goes half way.  Why two
Jan> artificial methods are not non-unique?

My understanding is that this loop is trying to filter out artificial
methods in a case like:

    class K {
      K(int) { ... }
    };

Here, I think, the user can type "ptype K::K" and get "K::K(int)" --
which makes some kind of sense, ignoring the compiler-generated
K::K(void).  At least, that is what I think it all means.  I am not sure
this code is really correct, but this part of the patch is just avoiding
a crash.

I don't think it is possible for this loop to see two artificial
methods.

Tom

2011-02-02  Tom Tromey  <tromey@redhat.com>

	* valops.c (value_struct_elt_for_reference): Refine artificial
	type logic.  Call error if j==-1.
	* dwarf2read.c (maybe_smash_one_typedef): New function.
	(process_die) <DW_TAG_typedef>: Use maybe_smash_one_typedef.

2011-02-02  Tom Tromey  <tromey@redhat.com>

	* gdb.cp/anon-struct.cc: New file.
	* gdb.cp/anon-struct.exp: New file.

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6a98d57..61feb60 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -4621,6 +4621,40 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
   do_cleanups (back_to);
 }
 
+/* Fix up a typedef to an anonymous structure, for C++.
+   Return 1 if the smashing was done, 0 otherwise.
+
+   In C++, a typedef can give a name to an anonymous structure.  See
+   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510.
+
+   We detect this situation and smash a name into the anonymous
+   struct.  */
+
+static int
+maybe_smash_one_typedef (struct type *typedef_type, const char *base_name)
+{
+  struct type *struct_type = TYPE_TARGET_TYPE (typedef_type);
+  int i;
+
+  for (i = 0; i < TYPE_NFN_FIELDS (struct_type); ++i)
+    {
+      if (TYPE_FN_FIELDLIST_NAME (struct_type, i)
+	  && TYPE_FN_FIELDLIST_NAME (struct_type, i)[0] == '~'
+	  && strcmp (TYPE_FN_FIELDLIST_NAME (struct_type, i) + 1,
+		     base_name) == 0)
+	{
+	  /* Found a destructor with the same name as our typedef, so
+	     proceed with smashing.  */
+	  TYPE_TAG_NAME (struct_type) = TYPE_NAME (typedef_type);
+	  TYPE_NAME (struct_type) = TYPE_NAME (typedef_type);
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
 /* Process a die and its children.  */
 
 static void
@@ -4669,11 +4703,34 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
 
     case DW_TAG_base_type:
     case DW_TAG_subrange_type:
-    case DW_TAG_typedef:
       /* Add a typedef symbol for the type definition, if it has a
          DW_AT_name.  */
       new_symbol (die, read_type_die (die, cu), cu);
       break;
+
+    case DW_TAG_typedef:
+      {
+	struct type *this_type = read_type_die (die, cu);
+
+	if (cu->language == language_cplus
+	    && TYPE_CODE (TYPE_TARGET_TYPE (this_type)) == TYPE_CODE_STRUCT
+	    && TYPE_TAG_NAME (TYPE_TARGET_TYPE (this_type)) == NULL
+	    && maybe_smash_one_typedef (this_type, dwarf2_name (die, cu)))
+	  {
+	    /* Pretend this DIE is a structure, for new_symbol.  */
+	    die->tag = DW_TAG_structure_type;
+	    new_symbol (die, TYPE_TARGET_TYPE (this_type), cu);
+	    die->tag = DW_TAG_typedef;
+	  }
+	else
+	  {
+	    /* Add a typedef symbol for the type definition, if it has
+	       a DW_AT_name.  */
+	    new_symbol (die, this_type, cu);
+	  }
+      }
+      break;
+
     case DW_TAG_common_block:
       read_common_block (die, cu);
       break;
diff --git a/gdb/testsuite/gdb.cp/anon-struct.cc b/gdb/testsuite/gdb.cp/anon-struct.cc
new file mode 100644
index 0000000..d1085c9
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/anon-struct.cc
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 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 3 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, see <http://www.gnu.org/licenses/>.
+   */
+
+class C {
+public:
+  C() {}
+  ~C() {}
+};
+
+typedef struct {
+  C m;
+} t;
+
+t v;
+
+int main()
+{
+}
diff --git a/gdb/testsuite/gdb.cp/anon-struct.exp b/gdb/testsuite/gdb.cp/anon-struct.exp
new file mode 100644
index 0000000..a250d19
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/anon-struct.exp
@@ -0,0 +1,25 @@
+# Tests for anonymous union support.
+# Copyright 2011 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 3 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, see <http://www.gnu.org/licenses/>.
+
+set testfile anon-struct
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug c++}] } {
+     return -1
+}
+
+gdb_test "ptype t::t" "type = void \\(t \\* const\\)" \
+    "print type of t::t"
diff --git a/gdb/valops.c b/gdb/valops.c
index 24c2269..0287092 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -3238,25 +3238,32 @@ value_struct_elt_for_reference (struct type *domain, int offset,
 	      int ii;
 
 	      j = -1;
-	      for (ii = 0; ii < TYPE_FN_FIELDLIST_LENGTH (t, i);
-		   ++ii)
+	      for (ii = 0; ii < len; ++ii)
 		{
 		  /* Skip artificial methods.  This is necessary if,
 		     for example, the user wants to "print
 		     subclass::subclass" with only one user-defined
-		     constructor.  There is no ambiguity in this
-		     case.  */
+		     constructor.  There is no ambiguity in this case.
+		     We are careful here to allow artificial methods
+		     if they are the unique result.  */
 		  if (TYPE_FN_FIELD_ARTIFICIAL (f, ii))
-		    continue;
+		    {
+		      if (j == -1)
+			j = ii;
+		      continue;
+		    }
 
 		  /* Desired method is ambiguous if more than one
 		     method is defined.  */
-		  if (j != -1)
+		  if (j != -1 && !TYPE_FN_FIELD_ARTIFICIAL (f, j))
 		    error (_("non-unique member `%s' requires "
 			     "type instantiation"), name);
 
 		  j = ii;
 		}
+
+	      if (j == -1)
+		error (_("no matching member function"));
 	    }
 
 	  if (TYPE_FN_FIELD_STATIC_P (f, j))


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