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] Cope with variadic initializers better (PR c++/33510)


This patch fixes PR c++/33510, a rejects-valid where we incorrectly
deduce the size of an array from an initializer containing parameter
expansions. For example:

  template<int... N>
  void foo()
  {
    int[] array = {N...};
  }

We were deducing the type of array as int[1], which causes problems
when we try to instantiate foo.

The fix is, simply, *not* to deduce the size of the array because the
size is value-dependent anyway. The attached patch implements this
fix.

In an ideal world, I'd want to deduce the appropriate size expression
(in this case, sizeof...(T)). It doesn't actually change how GCC would
compile these programs now, but it gives a more precise IR. However,
doing so would mean rewriting cp_complete_array_type to deal with
parameter packs, essentially duplicating all of the work that's now
being done in the C-based complete_array_type.

Only the simple patch is attached, and tested i686-pc-linux-gnu. Okay
for mainline?

  - Doug

2007-11-08  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/33510
	* decl.c (cp_complete_array_type): If any of the initializer
	elements are pack expansions, don't compute the array size yet.

2007-11-08  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/33510
	* g++.dg/cpp0x/variadic-init.C: New.
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 129996)
+++ cp/decl.c	(working copy)
@@ -4331,7 +4331,7 @@ maybe_deduce_size_from_array_init (tree 
 	  HOST_WIDE_INT i;
 	  for (i = 0; 
 	       VEC_iterate (constructor_elt, v, i, ce);
-	       ++i)
+	       ++i) 
 	    if (!check_array_designated_initializer (ce))
 	      failure = 1;
 	}
@@ -6110,6 +6110,9 @@ cp_complete_array_type (tree *ptype, tre
 
   if (initial_value)
     {
+      unsigned HOST_WIDE_INT i;
+      tree value;
+
       /* An array of character type can be initialized from a
 	 brace-enclosed string constant.
 
@@ -6126,6 +6129,18 @@ cp_complete_array_type (tree *ptype, tre
 	      && VEC_length (constructor_elt, v) == 1)
 	    initial_value = value;
 	}
+
+      /* If any of the elements are parameter packs, we can't actually
+	 complete this type now because the array size is dependent.  */
+      if (TREE_CODE (initial_value) == CONSTRUCTOR)
+	{
+	  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (initial_value), 
+				      i, value)
+	    {
+	      if (PACK_EXPANSION_P (value))
+		return 0;
+	    }
+	}
     }
 
   failure = complete_array_type (ptype, initial_value, do_default);
Index: testsuite/g++.dg/cpp0x/variadic-init.C
===================================================================
--- testsuite/g++.dg/cpp0x/variadic-init.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/variadic-init.C	(revision 0)
@@ -0,0 +1,56 @@
+// { dg-do run }
+// { dg-options "-std=gnu++0x" }
+
+// PR c++/33510
+#define SIZE_FROM_CTOR
+extern "C" void abort ();
+
+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;
+  }
+};
+
+template<typename... M> struct R
+{
+  template<typename... N> static int *foo ()
+  {
+#ifdef SIZE_FROM_CTOR
+    static int x[] = { (sizeof(M) + sizeof(N))..., -1 };
+#else
+    static int x[1 + sizeof... N] = { (sizeof(M) + sizeof(N))..., -1 };
+#endif
+    return x;
+  }
+};
+
+int *bar ()
+{
+  return S<0, 1, 2>::foo<0, 1, 2> ();
+}
+
+int *baz ()
+{
+  return R<char, short, int>::foo<float, double, long> ();
+}
+
+
+int main ()
+{
+  int *p = bar ();
+  if (p[0] != 0 || p[1] != 2 || p[2] != 4 || p[3] != -1)
+    abort ();
+}

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