[RFA] Fix PR c++/17059

Message ID 1403648396-28742-1-git-send-email-keiths@redhat.com
State New, archived
Headers

Commit Message

Keith Seitz June 24, 2014, 10:19 p.m. UTC
  This patch fixes PR c++/17059.

When inspect_type sees a typedef, it attempts to call type_print
to printout the target type's name.

when type_print calls c_type_print_base, this function simply "prints"
out TYPE_NAME ("do we want to print it as 'struct foo' or as 'bar'? Pick
the latter, because C++ folk tend to expect thngs like 'class5 *foo'
rather than 'struct class5 *foo'."). Since TYPE_NAME is the same as the
typedef name (in this case), we get the same name, which
print_name_maybe_canonical tries to do typedef substitution on. As a
result, an infinite recursion occurs.

This patch adds logic to inspect_type to recognize this situation and
bail typedef substitution if the typedef and its target type have the
same name.

ChangeLog
2014-06-24  Keith Seitz  <keiths@redhat.com>

	PR c++/17059
	* cp-support.c (inspect_type): When a typedef's target type
	has the same name as the typedef, do not attempt to do
	any substitutions.

testsuite/ChangeLog
2014-06-24  Keith Seitz  <keiths@redhat.com>

	PR c++/17059
	* gdb.cp/breakpoint.cc: Include stddef.h.
	(opaque_struct): New typedef.
	(C1::method_with_opaque): New method.
	* gdb.cp/breakpoint.exp: Add test to set a breakpoint on
	C1::method_with_opaque (opaque_struct *).
---
 gdb/cp-support.c                    | 13 ++++++++++---
 gdb/testsuite/gdb.cp/breakpoint.cc  |  8 ++++++++
 gdb/testsuite/gdb.cp/breakpoint.exp |  2 ++
 3 files changed, 20 insertions(+), 3 deletions(-)
  

Patch

diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index a8ea6fc..f6d1b90 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -214,9 +214,16 @@  inspect_type (struct demangle_parse_info *info,
 
 	  /* If the symbol is a namespace and its type name is no different
 	     than the name we looked up, this symbol is not a namespace
-	     alias and does not need to be substituted.  */
-	  if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE
-	      && strcmp (TYPE_NAME (type), name) == 0)
+	     alias and does not need to be substituted.
+
+	     Also, do not attempt to substitute a type that resolves
+	     to the same name ("typedef struct foo foo;") since that
+	     will cause type_print to try to canonicalize_no_typedefs
+	     again.  */
+	  if ((TYPE_CODE (otype) == TYPE_CODE_NAMESPACE
+	       && strcmp (TYPE_NAME (type), name) == 0)
+	      || (TYPE_TAG_NAME (type) != NULL
+		  && strcmp (TYPE_TAG_NAME (type), name) == 0))
 	    return 0;
 
 	  is_anon = (TYPE_TAG_NAME (type) == NULL
diff --git a/gdb/testsuite/gdb.cp/breakpoint.cc b/gdb/testsuite/gdb.cp/breakpoint.cc
index e2873ea..31d8cfa 100644
--- a/gdb/testsuite/gdb.cp/breakpoint.cc
+++ b/gdb/testsuite/gdb.cp/breakpoint.cc
@@ -17,8 +17,12 @@ 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include <stddef.h>
+
 int g = 0;
 
+typedef struct opaque_struct opaque_struct;
+
 class C1 {
 public:
   C1(int i) : i_(i) {}
@@ -37,6 +41,9 @@  public:
       }
   }
 
+  void
+  method_with_opaque (opaque_struct *p) {}
+
   class Nested {
   public:
     int
@@ -61,6 +68,7 @@  int main ()
   c2.bar ();
   c3.foo ();
   c3.bar ();
+  c3.method_with_opaque (NULL);
 
   return 0;
 }
diff --git a/gdb/testsuite/gdb.cp/breakpoint.exp b/gdb/testsuite/gdb.cp/breakpoint.exp
index 7daaade..36dc4d2 100644
--- a/gdb/testsuite/gdb.cp/breakpoint.exp
+++ b/gdb/testsuite/gdb.cp/breakpoint.exp
@@ -56,6 +56,8 @@  gdb_test "print i_" "\\\$1 = 3" "check the member variable"
 gdb_test "continue" ".*Breakpoint.*C1::bar.*" "continue to breakpoint"
 gdb_test "print i_" "\\\$2 = 3" "check the member variable"
 
+# PR c++/17059
+gdb_breakpoint "C1::method_with_opaque (opaque_struct *)" message
 
 gdb_exit
 return 0