This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/46289 (ICE on invalid mem-init-list in constexpr ctor)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 03 Nov 2010 22:02:22 -0400
- Subject: Re: C++ PATCH for c++/46289 (ICE on invalid mem-init-list in constexpr ctor)
- References: <4CD1B18A.6070000@redhat.com>
On 11/03/2010 03:01 PM, Jason Merrill wrote:
The testcase in the PR ought to be valid, but even on an invalid
initializer we shouldn't ICE. This patch just fixes the ICE.
And this patch fixes the error.
Tested x86_64-pc-linux-gnu, applied to trunk.
commit 806ad75a68d2a2ecede77d1857cc1404d395e6a6
Author: Jason Merrill <jason@redhat.com>
Date: Wed Nov 3 18:28:18 2010 -0400
PR c++/46289
* call.c (can_convert_array): New fn.
(build_aggr_conv): Use it.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a1c8682..4507f3d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -639,6 +639,29 @@ build_list_conv (tree type, tree ctor, int flags)
return t;
}
+/* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list,
+ is a valid aggregate initializer for array type ATYPE. */
+
+static bool
+can_convert_array (tree atype, tree ctor, int flags)
+{
+ unsigned i;
+ tree elttype = TREE_TYPE (atype);
+ for (i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
+ {
+ tree val = CONSTRUCTOR_ELT (ctor, i)->value;
+ bool ok;
+ if (TREE_CODE (elttype) == ARRAY_TYPE
+ && TREE_CODE (val) == CONSTRUCTOR)
+ ok = can_convert_array (elttype, val, flags);
+ else
+ ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags);
+ if (!ok)
+ return false;
+ }
+ return true;
+}
+
/* Represent a conversion from CTOR, a braced-init-list, to TYPE, an
aggregate class, if such a conversion is possible. */
@@ -652,24 +675,31 @@ build_aggr_conv (tree type, tree ctor, int flags)
for (; field; field = next_initializable_field (DECL_CHAIN (field)))
{
+ tree ftype = TREE_TYPE (field);
+ tree val;
+ bool ok;
+
if (i < CONSTRUCTOR_NELTS (ctor))
- {
- constructor_elt *ce = CONSTRUCTOR_ELT (ctor, i);
- if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (ce->value),
- ce->value, flags))
- return NULL;
- ++i;
- if (TREE_CODE (type) == UNION_TYPE)
- break;
- }
+ val = CONSTRUCTOR_ELT (ctor, i)->value;
else
{
if (empty_ctor == NULL_TREE)
empty_ctor = build_constructor (init_list_type_node, NULL);
- if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (empty_ctor),
- empty_ctor, flags))
- return NULL;
+ val = empty_ctor;
}
+ ++i;
+
+ if (TREE_CODE (ftype) == ARRAY_TYPE
+ && TREE_CODE (val) == CONSTRUCTOR)
+ ok = can_convert_array (ftype, val, flags);
+ else
+ ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags);
+
+ if (!ok)
+ return NULL;
+
+ if (TREE_CODE (type) == UNION_TYPE)
+ break;
}
if (i < CONSTRUCTOR_NELTS (ctor))
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist45.C b/gcc/testsuite/g++.dg/cpp0x/initlist45.C
new file mode 100644
index 0000000..0e34bc1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist45.C
@@ -0,0 +1,13 @@
+// PR c++/46289
+// { dg-options -std=c++0x }
+
+struct A
+{
+ int i[2];
+};
+
+struct B
+{
+ A a;
+ B(): a({{1,2}}) { }
+};