re PR c++/46289 (ICE in build_constexpr_constructor_member_initializers, at cp/semant...
authorJason Merrill <jason@redhat.com>
Thu, 4 Nov 2010 02:15:00 +0000 (22:15 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 4 Nov 2010 02:15:00 +0000 (22:15 -0400)
PR c++/46289
* call.c (can_convert_array): New fn.
(build_aggr_conv): Use it.

From-SVN: r166296

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/initlist45.C [new file with mode: 0644]

index 7c4b08217324f6471aea2f076c03ba14c6fd8871..e384cf7991e78b4472cbc1b0b220b5f16033614a 100644 (file)
@@ -1,5 +1,9 @@
 2010-11-03  Jason Merrill  <jason@redhat.com>
 
+       PR c++/46289
+       * call.c (can_convert_array): New fn.
+       (build_aggr_conv): Use it.
+
        PR c++/46289
        * semantics.c (build_constexpr_constructor_member_initializers):
        Avoid ICE on error.
index a1c8682fe6c047013415428710e7e29b29bdccba..4507f3d37b99485b1632f51e16c9ac3aace03f19 100644 (file)
@@ -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))
index f607bebd83d04eadc8fc0465e8d2c97a58da000e..0597d4718dc48ad5d7eef1aaa44201959ecf4264 100644 (file)
@@ -1,3 +1,8 @@
+2010-11-03  Jason Merrill  <jason@redhat.com>
+
+       PR c++/46289
+       * g++.dg/cpp0x/initlist45.C: New.
+
 2010-11-03  Nicola Pero  <nicola.pero@meta-innovation.com>
 
        * objc.dg/property/dynamic-2.m: Updated for the fact that @dynamic
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist45.C b/gcc/testsuite/g++.dg/cpp0x/initlist45.C
new file mode 100644 (file)
index 0000000..0e34bc1
--- /dev/null
@@ -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}}) { }
+};