call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any constructor called...
authorJason Merrill <jason@redhat.com>
Sat, 26 Jun 2010 21:34:36 +0000 (17:34 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sat, 26 Jun 2010 21:34:36 +0000 (17:34 -0400)
* call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any
constructor called with a single argument that takes a reference
to the constructor's class.
(BAD_CONVERSION_RANK): New.
(compare_ics): Use it to compare bad ICSes.

From-SVN: r161443

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

index 3093f0d9c9a03d418eadd65dfc93edac5d1f8222..e9d85c30ffe19d8a077a21bd45218d8d0dc4742b 100644 (file)
@@ -1,3 +1,11 @@
+2010-06-26  Jason Merrill  <jason@redhat.com>
+
+       * call.c (add_function_candidate): Set LOOKUP_COPY_PARM for any
+       constructor called with a single argument that takes a reference
+       to the constructor's class.
+       (BAD_CONVERSION_RANK): New.
+       (compare_ics): Use it to compare bad ICSes.
+
 2010-06-25  Joseph Myers  <joseph@codesourcery.com>
 
        * lang-specs.h: Remove +e handling.
index 55089edbf1d9d8fd7416a29c481459d655441367..faaab1027f5197617120758fbf4ca94fdccf1747 100644 (file)
@@ -122,6 +122,11 @@ struct conversion {
    : (NODE)->user_conv_p ? cr_user             \
    : (NODE)->rank)
 
+#define BAD_CONVERSION_RANK(NODE)              \
+  ((NODE)->ellipsis_p ? cr_ellipsis            \
+   : (NODE)->user_conv_p ? cr_user             \
+   : (NODE)->rank)
+
 static struct obstack conversion_obstack;
 static bool conversion_obstack_initialized;
 
@@ -1386,9 +1391,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
      conversion operator).  */
   flags |= LOOKUP_NO_TEMP_BIND;
 
-  /* Temporaries are copy-initialized, except for this hack to allow
-     explicit conversion ops to the copy ctor.  See also
-     add_function_candidate.  */
+  /* Core issue 899: When [copy-]initializing a temporary to be bound
+     to the first parameter of a copy constructor (12.8) called with
+     a single argument in the context of direct-initialization,
+     explicit conversion functions are also considered.
+
+     So don't set LOOKUP_ONLYCONVERTING in that case.  */
   if (!(flags & LOOKUP_COPY_PARM))
     flags |= LOOKUP_ONLYCONVERTING;
 
@@ -1618,6 +1626,8 @@ add_function_candidate (struct z_candidate **candidates,
          tree parmtype = TREE_VALUE (parmnode);
          int lflags = flags;
 
+         parmnode = TREE_CHAIN (parmnode);
+
          /* The type of the implicit object parameter ('this') for
             overload resolution is not always the same as for the
             function itself; conversion functions are considered to
@@ -1634,13 +1644,25 @@ add_function_candidate (struct z_candidate **candidates,
              parmtype = build_pointer_type (parmtype);
            }
 
-         if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn)
-             && (len-skip == 1))
+         /* Core issue 899: When [copy-]initializing a temporary to be bound
+            to the first parameter of a copy constructor (12.8) called with
+            a single argument in the context of direct-initialization,
+            explicit conversion functions are also considered.
+
+            So set LOOKUP_COPY_PARM to let reference_binding know that
+            it's being called in that context.  We generalize the above
+            to handle move constructors and template constructors as well;
+            the standardese should soon be updated similarly.  */
+         if (ctype && i == 0 && (len-skip == 1)
+             && !(flags & LOOKUP_ONLYCONVERTING)
+             && DECL_CONSTRUCTOR_P (fn)
+             && parmtype != error_mark_node
+             && (same_type_ignoring_top_level_qualifiers_p
+                 (non_reference (parmtype), ctype)))
            {
-             /* Hack: Direct-initialize copy parm (i.e. suppress
-                LOOKUP_ONLYCONVERTING) to make explicit conversion ops
-                work.  See also reference_binding.  */
              lflags |= LOOKUP_COPY_PARM;
+             /* We allow user-defined conversions within init-lists, but
+                not for the copy constructor.  */
              if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
                lflags |= LOOKUP_NO_CONVERSION;
            }
@@ -1668,9 +1690,6 @@ add_function_candidate (struct z_candidate **candidates,
 
       if (t->bad_p)
        viable = -1;
-
-      if (parmnode)
-       parmnode = TREE_CHAIN (parmnode);
     }
 
  out:
@@ -6741,14 +6760,16 @@ compare_ics (conversion *ics1, conversion *ics2)
 
   if (rank1 == cr_bad)
     {
-      /* XXX Isn't this an extension? */
-      /* Both ICS are bad.  We try to make a decision based on what
-        would have happened if they'd been good.  */
-      if (ics1->user_conv_p > ics2->user_conv_p
-         || ics1->rank  > ics2->rank)
+      /* Both ICS are bad.  We try to make a decision based on what would
+        have happened if they'd been good.  This is not an extension,
+        we'll still give an error when we build up the call; this just
+        helps us give a more helpful error message.  */
+      rank1 = BAD_CONVERSION_RANK (ics1);
+      rank2 = BAD_CONVERSION_RANK (ics2);
+
+      if (rank1 > rank2)
        return -1;
-      else if (ics1->user_conv_p < ics2->user_conv_p
-              || ics1->rank < ics2->rank)
+      else if (rank1 < rank2)
        return 1;
 
       /* We couldn't make up our minds; try to figure it out below.  */
index 3f88e7ddf85a813216026d737f11fb50a7c6b555..ea6169e486c8d944f373afb83e5b446aaf7b5a10 100644 (file)
@@ -1,3 +1,7 @@
+2010-06-26  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/explicit5.C: New.
+
 2010-06-26  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/44393
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit5.C b/gcc/testsuite/g++.dg/cpp0x/explicit5.C
new file mode 100644 (file)
index 0000000..88a4707
--- /dev/null
@@ -0,0 +1,25 @@
+// test for extension of DR 899 to handle template ctors
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+int r = 1;
+
+struct C {
+  C() { }
+  template <class T = int> C(C&, T = 0) { r = 0; }
+};
+
+C c;
+
+struct A
+{
+  explicit operator C&() const { return c; }
+};
+
+int main()
+{
+  A a;
+  C c2 (a);
+
+  return r;
+}