Patchwork C++ PATCH for C++0x aggregate list-initialization and overloading

login
register
mail settings
Submitter Jason Merrill
Date June 15, 2010, 7:17 p.m.
Message ID <4C17D1C2.8080902@redhat.com>
Download mbox | patch
Permalink /patch/55781/
State New
Headers show

Comments

Jason Merrill - June 15, 2010, 7:17 p.m.
We were previously treating an aggregate list-initialization as 
indistinguishable from any other user-defined conversion sequence.  This 
isn't quite right; if both conversions involve the same aggregate 
initialization, we should continue and compare the second standard 
conversions sequence like we do for two user-defined conversion 
sequences involving the same conversion function.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 5d28b12b0210dcef6db35d4d63f0a366a8c343c4
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 15 12:08:47 2010 -0400

    	* call.c (is_subseq): Handle ck_aggr, ck_list.
    	(compare_ics): Treat an aggregate or ambiguous conversion to the
    	same type as involving the same function.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f46fbf7..9ce1c53 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6578,6 +6578,8 @@  is_subseq (conversion *ics1, conversion *ics2)
 
       if (ics2->kind == ck_user
 	  || ics2->kind == ck_ambig
+	  || ics2->kind == ck_aggr
+	  || ics2->kind == ck_list
 	  || ics2->kind == ck_identity)
 	/* At this point, ICS1 cannot be a proper subsequence of
 	   ICS2.  We can get a USER_CONV when we are comparing the
@@ -6762,13 +6764,25 @@  compare_ics (conversion *ics1, conversion *ics2)
 
       for (t1 = ics1; t1->kind != ck_user; t1 = t1->u.next)
 	if (t1->kind == ck_ambig || t1->kind == ck_aggr)
-	  return 0;
+	  break;
       for (t2 = ics2; t2->kind != ck_user; t2 = t2->u.next)
 	if (t2->kind == ck_ambig || t2->kind == ck_aggr)
-	  return 0;
+	  break;
 
-      if (t1->cand->fn != t2->cand->fn)
+      if (t1->kind != t2->kind)
 	return 0;
+      else if (t1->kind == ck_user)
+	{
+	  if (t1->cand->fn != t2->cand->fn)
+	    return 0;
+	}
+      else
+	{
+	  /* For ambiguous or aggregate conversions, use the target type as
+	     a proxy for the conversion function.  */
+	  if (!same_type_ignoring_top_level_qualifiers_p (t1->type, t2->type))
+	    return 0;
+	}
 
       /* We can just fall through here, after setting up
 	 FROM_TYPE1 and FROM_TYPE2.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist39.C b/gcc/testsuite/g++.dg/cpp0x/initlist39.C
new file mode 100644
index 0000000..a6dd1ec
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist39.C
@@ -0,0 +1,15 @@ 
+// { dg-options -std=c++0x }
+
+struct A { int i; };
+
+void f (const A &);
+void f (A &&);
+
+void g (A, int);
+void g (A, double);
+
+int main()
+{
+  f ( { 1 } );
+  g ( { 1 }, 1 );
+}