This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Cope with variadic initializers better (PR c++/33510)
- From: "Doug Gregor" <doug dot gregor at gmail dot com>
- To: "GCC Patches" <gcc-patches at gcc dot gnu dot org>, "Jason Merrill" <jason at redhat dot com>
- Date: Thu, 8 Nov 2007 10:54:18 -0500
- Subject: [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 ();
+}