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 to overload resolution of aggregate initialization with c++0x initializer-list


Someone in the C++ committee pointed out an odd error message to me, which turned out to be that build_aggr_conv wasn't modeling aggregate initialization well enough. Fixed thus.

Tested x86_64-pc-linux-gnu, applying to trunk as it only affects c++0x code.
commit cc3bfe5b31b7cad9bb4e45c18d5fbc70810fd161
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Apr 1 01:28:15 2010 -0400

    	* decl.c (next_initializable_field): No longer static.
    	* cp-tree.h: Declare it.
    	* call.c (build_aggr_conv): Fail if there are more initializers
    	than initializable fields.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index edec6ea..5a32b3b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -626,23 +626,27 @@ build_aggr_conv (tree type, tree ctor, int flags)
 {
   unsigned HOST_WIDE_INT i = 0;
   conversion *c;
-  tree field = TYPE_FIELDS (type);
+  tree field = next_initializable_field (TYPE_FIELDS (type));
 
-  for (; field; field = TREE_CHAIN (field), ++i)
+  for (; field; field = next_initializable_field (TREE_CHAIN (field)))
     {
-      if (TREE_CODE (field) != FIELD_DECL)
-	continue;
       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;
 	}
       else if (build_value_init (TREE_TYPE (field)) == error_mark_node)
 	return NULL;
     }
 
+  if (i < CONSTRUCTOR_NELTS (ctor))
+    return NULL;
+
   c = alloc_conversion (ck_aggr);
   c->type = type;
   c->rank = cr_exact;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fb67965..6334673 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4727,6 +4727,7 @@ extern bool cp_missing_noreturn_ok_p		(tree);
 extern void initialize_artificial_var		(tree, tree);
 extern tree check_var_type			(tree, tree);
 extern tree reshape_init (tree, tree);
+extern tree next_initializable_field (tree);
 
 extern bool defer_mark_used_calls;
 extern GTY(()) VEC(tree, gc) *deferred_mark_used_calls;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e38abda..a308d64 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -104,7 +104,6 @@ static tree build_cp_library_fn (tree, enum tree_code, tree);
 static void store_parm_decls (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
-static tree next_initializable_field (tree);
 
 /* The following symbols are subsumed in the cp_global_trees array, and
    listed here individually for documentation purposes.
@@ -4723,7 +4722,7 @@ static tree reshape_init_r (tree, reshape_iter *, bool);
    initialized.  If there are no more such fields, the return value
    will be NULL.  */
 
-static tree
+tree
 next_initializable_field (tree field)
 {
   while (field
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist12.C b/gcc/testsuite/g++.dg/cpp0x/initlist12.C
index 31d34c4..f344c78 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist12.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist12.C
@@ -1,20 +1,21 @@
 // PR c++/38698
 // { dg-options "-std=c++0x" }
+// { dg-prune-output "note" }
 
 struct A
 {
   int i;
 };
 
-A a({1,2});			// { dg-error "too many initializers" }
+A a({1,2});			// { dg-error "no match" }
 
 union U
 {
   int i,j;
 };
 
-U u({1,2});			// { dg-error "too many initializers" }
+U u({1,2});			// { dg-error "no match" }
 
 union V {};
 
-V v({1});			// { dg-error "too many initializers" }
+V v({1});			// { dg-error "no match" }

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