This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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]

[C++ PATCH] Fix 3 ICEs on invalid with variadic templates (PR c++/33496)


Hi!

The following patch cures 3 different places where we can
die with tree checking ICE.  tsubst_pack_expansion can return
error_mark_node for multiple reasons, so assuming it returned
TREE_VEC is a wrong assumption.
Tested on x86_64-linux, ok for trunk?

Other calls to tsubst_pack_expansion which don't handle
error_mark_node still IMHO need investigation:
1) tsubst_exception_specification
template<int M, int N> struct pair
{
  int i, j;
  pair() : i(M), j(N) {}
};

template<int... M> struct S
{
  template<int... N> static int foo() throw (pair <M, N>...)
  {
    return 1;
  }
};

int bar ()
{
  return S<0, 1, 2>::foo<0, 1> ();
}
   ICEs, but I'm not 100% sure what to do there, tsubst_pack_expansion
   doesn't return there a TREE_VEC, but TYPE_PACK_EXPANSION (guess I'll
   file a new PR to track this)
2) regenerate_decl_from_template
   Not sure how to create a testcase for it.
3) tsubst_initializer_list
   Second call to tsubst_pack_expansion.  No testcase either.

Additionally, how should [] arrays be sized in presence of
packs?  Following compiles only without -DSIZE_FROM_CTOR
template<int M, int N> struct pair
{
  int i, j;
  pair () : i (M), j (N) {}
};

template<int... M> struct S
{
  template<int... N> static int *foo ()
  {
#ifdef SIZE_FROM_CTOR
    static int x[] = { (M + N)..., -1 };
#else
    static int x[1 + sizeof... N] = { (M + N)..., -1 };
#endif
    return x;
  }
};

int *bar ()
{
  return S<0, 1, 2>::foo<0, 1, 2> ();
}
Should I file a PR?  Is the upcoming C++ standard going to have
something similar as ISO C99 designated initializers?  If yes, how
would that play together with variadic templates?

2007-09-20  Jakub Jelinek  <jakub@redhat.com>

	PR c++/33496
	* pt.c (tsubst_copy) <case SIZEOF_EXPR>: Handle error_mark_node
	returned from tsubst_pack_expansion.
	(tsubst_copy_and_build) <case SIZEOF_EXPR>: Likewise.
	(tsubst_copy_and_build) <case CONSTRUCTOR>: Likewise.

	* g++.dg/cpp0x/variadic76.C: New test.
	* g++.dg/cpp0x/variadic77.C: New test.
	* g++.dg/cpp0x/variadic78.C: New test.

--- gcc/cp/pt.c.jj	2007-09-19 12:23:29.000000000 +0200
+++ gcc/cp/pt.c	2007-09-20 13:37:32.000000000 +0200
@@ -9586,6 +9586,8 @@ tsubst_copy (tree t, tree args, tsubst_f
           /* We only want to compute the number of arguments.  */
           tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
                                                 complain, in_decl);
+	  if (expanded == error_mark_node)
+	    return error_mark_node;
           return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
         }
       /* Fall through */
@@ -10586,6 +10588,8 @@ tsubst_copy_and_build (tree t,
           /* We only want to compute the number of arguments.  */
           tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
                                                 complain, in_decl);
+	  if (expanded == error_mark_node)
+	    return error_mark_node;
           return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
         }
       /* Fall through */
@@ -10978,7 +10982,9 @@ tsubst_copy_and_build (tree t,
                 ce->value = tsubst_pack_expansion (ce->value, args, complain,
                                                   in_decl);
 
-                if (TREE_VEC_LENGTH (ce->value) == 1)
+		if (ce->value == error_mark_node)
+		  ;
+		else if (TREE_VEC_LENGTH (ce->value) == 1)
                   /* Just move the argument into place.  */
                   ce->value = TREE_VEC_ELT (ce->value, 0);
                 else
--- gcc/testsuite/g++.dg/cpp0x/variadic76.C.jj	2007-09-20 13:48:44.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic76.C	2007-09-20 13:44:17.000000000 +0200
@@ -0,0 +1,13 @@
+// PR c++/33496
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+template<int... N> int foo ()
+{
+  return sizeof... N ();	// { dg-error "cannot be used as a function" }
+}
+
+int bar ()
+{
+  return foo<0> ();
+}
--- gcc/testsuite/g++.dg/cpp0x/variadic77.C.jj	2007-09-20 13:48:49.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic77.C	2007-09-20 13:44:32.000000000 +0200
@@ -0,0 +1,22 @@
+// PR c++/33496
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+template<int M, int N> struct pair
+{
+  int i, j;
+  pair () : i (M), j (N) {}
+};
+
+template<int... M> struct S
+{
+  template<int... N> static int foo ()
+  {
+    return sizeof... (pair<M, N>);	// { dg-error "mismatched argument pack lengths" }
+  }
+};
+
+int bar ()
+{
+  return S<0, 1, 2>::foo<0, 1> ();
+}
--- gcc/testsuite/g++.dg/cpp0x/variadic78.C.jj	2007-09-20 13:48:53.000000000 +0200
+++ gcc/testsuite/g++.dg/cpp0x/variadic78.C	2007-09-20 13:44:48.000000000 +0200
@@ -0,0 +1,23 @@
+// PR c++/33496
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+template<int M, int N> struct pair
+{
+  int i, j;
+  pair () : i (M), j (N) {}
+};
+
+template<int... M> struct S
+{
+  template<int... N> static int *foo ()
+  {
+    static int x[] = { (M + N)... };	// { dg-error "mismatched argument pack lengths" }
+    return x;
+  }
+};
+
+int *bar ()
+{
+  return S<0, 1, 2>::foo<0, 1> ();
+}

	Jakub


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