[C++ Patch] PR 58448

Paolo Carlini paolo.carlini@oracle.com
Wed Sep 18 00:03:00 GMT 2013


Hi,

this ICE is caused by error_mark_node as TREE_TYPE of a TYPE_DECL, which 
leads to a crash at the beginning of the TYPE_DECL case of tsubst_decl.

I tried various approaches - for example turning all error_operand_p (t) 
== true arguments passes to tsubst into error_mark_nodes also works - 
but I think I have a weak preference for the solution below, because 
conceptually matches the section of grokdeclarator beginning with:

   /* If this is declaring a typedef name, return a TYPE_DECL.  */
   if (typedef_p && decl_context != TYPENAME)

which seems rather special in terms of producing such TYPE_DECLs in case 
of errors (it does that for error recovery reasons, I suppose: just 
returning error_mark_node leads to worse diagnostic for eg, 
parse/error32.C).

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////
-------------- next part --------------
/cp
2013-09-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/58448
	* pt.c (tsubst_decl, [TYPE_DECL]): Check TREE_TYPE (t) for
	error_mark_node.

/testsuite
2013-09-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/58448
	* g++.dg/template/crash117.C: New.
-------------- next part --------------
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 202668)
+++ cp/pt.c	(working copy)
@@ -10741,19 +10741,23 @@ tsubst_decl (tree t, tree args, tsubst_flags_t com
 	tree type = NULL_TREE;
 	bool local_p;
 
-	if (TREE_CODE (t) == TYPE_DECL
-	    && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
+	if (TREE_CODE (t) == TYPE_DECL)
 	  {
-	    /* If this is the canonical decl, we don't have to
-	       mess with instantiations, and often we can't (for
-	       typename, template type parms and such).  Note that
-	       TYPE_NAME is not correct for the above test if
-	       we've copied the type for a typedef.  */
-	    type = tsubst (TREE_TYPE (t), args, complain, in_decl);
-	    if (type == error_mark_node)
+	    if (TREE_TYPE (t) == error_mark_node)
 	      RETURN (error_mark_node);
-	    r = TYPE_NAME (type);
-	    break;
+	    else if (t == TYPE_MAIN_DECL (TREE_TYPE (t)))
+	      {
+		/* If this is the canonical decl, we don't have to
+		   mess with instantiations, and often we can't (for
+		   typename, template type parms and such).  Note that
+		   TYPE_NAME is not correct for the above test if
+		   we've copied the type for a typedef.  */
+		type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+		if (type == error_mark_node)
+		  RETURN (error_mark_node);
+		r = TYPE_NAME (type);
+		break;
+	      }
 	  }
 
 	/* Check to see if we already have the specialization we
Index: testsuite/g++.dg/template/crash117.C
===================================================================
--- testsuite/g++.dg/template/crash117.C	(revision 0)
+++ testsuite/g++.dg/template/crash117.C	(working copy)
@@ -0,0 +1,6 @@
+// PR c++/58448
+
+class SmallVector; struct Types4;
+template <typename, typename, typename, typename> struct Types {
+  typedef Types4<>::Constructable // { dg-error "template|typedef|expected" }
+} Types<SmallVector, SmallVector, SmallVector, SmallVector>:: > // { dg-error "expected" }


More information about the Gcc-patches mailing list