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.

///////////////////////
/cp
2013-09-17  Paolo Carlini  <paolo.carl...@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.carl...@oracle.com>

        PR c++/58448
        * g++.dg/template/crash117.C: New.
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" }

Reply via email to