re PR c++/35773 (auto_ptr references don't convert)
authorJason Merrill <jason@redhat.com>
Thu, 17 Apr 2008 14:01:26 +0000 (10:01 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 17 Apr 2008 14:01:26 +0000 (10:01 -0400)
        PR c++/35773
        * cp/call.c (build_user_type_conversion_1): Represent second step of
        copy-init with an rvalue conversion.
        (convert_like_real) [ck_user]: Don't implicitly add it here.
        * g++.dg/overload/autoptr1.C: New.

From-SVN: r134398

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

index 22a7420523d62bff5c7cc2fc2dc72c1b5fd54ecd..3169ba0f366e45e7e5164def9129b99c2e577a1f 100644 (file)
@@ -1,3 +1,10 @@
+2008-04-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35773
+       * call.c (build_user_type_conversion_1): Represent second step of 
+       copy-init with an rvalue conversion.
+       (convert_like_real) [ck_user]: Don't implicitly add it here.
+
 2008-04-15  Jakub Jelinek  <jakub@redhat.com>
 
        PR c/35751
index 9835c86e3a22526bb12e6d4d5772289bbc5061ea..c072a7df77fb10f068b049feeda89382344f0fb6 100644 (file)
@@ -2634,7 +2634,22 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
                                       flags);
 
       if (cand)
-       cand->second_conv = build_identity_conv (totype, NULL_TREE);
+       {
+         cand->second_conv = build_identity_conv (totype, NULL_TREE);
+
+         /* If totype isn't a reference, and LOOKUP_NO_TEMP_BIND isn't
+            set, then this is copy-initialization.  In that case, "The
+            result of the call is then used to direct-initialize the
+            object that is the destination of the copy-initialization."
+            [dcl.init]
+
+            We represent this in the conversion sequence with an
+            rvalue conversion, which means a constructor call.  */
+         if (TREE_CODE (totype) != REFERENCE_TYPE
+             && !(convflags & LOOKUP_NO_TEMP_BIND))
+           cand->second_conv
+             = build_conv (ck_rvalue, totype, cand->second_conv);
+       }
     }
 
   if (conv_fns)
@@ -2686,6 +2701,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
                                       0,
                                       /*c_cast_p=*/false, convflags);
 
+             /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
+                copy-initialization.  In that case, "The result of the
+                call is then used to direct-initialize the object that is
+                the destination of the copy-initialization."  [dcl.init]
+
+                We represent this in the conversion sequence with an
+                rvalue conversion, which means a constructor call.  But
+                don't add a second rvalue conversion if there's already
+                one there.  Which there really shouldn't be, but it's
+                harmless since we'd add it here anyway. */
+             if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue
+                 && !(convflags & LOOKUP_NO_TEMP_BIND))
+               ics = build_conv (ck_rvalue, totype, ics);
+
              cand->second_conv = ics;
 
              if (!ics)
@@ -4425,38 +4454,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
        if (DECL_CONSTRUCTOR_P (convfn))
          expr = build_cplus_new (totype, expr);
 
-       /* The result of the call is then used to direct-initialize the object
-          that is the destination of the copy-initialization.  [dcl.init]
-
-          Note that this step is not reflected in the conversion sequence;
-          it affects the semantics when we actually perform the
-          conversion, but is not considered during overload resolution.
-
-          If the target is a class, that means call a ctor.  */
-       if (MAYBE_CLASS_TYPE_P (totype)
-           && (inner >= 0 || !lvalue_p (expr)))
-         {
-           expr = (build_temp
-                   (expr, totype,
-                    /* Core issue 84, now a DR, says that we don't
-                       allow UDCs for these args (which deliberately
-                       breaks copy-init of an auto_ptr<Base> from an
-                       auto_ptr<Derived>).  */
-                    LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION,
-                    &diagnostic_fn));
-
-           if (diagnostic_fn && (complain & tf_error))
-             {
-               if (fn)
-                 diagnostic_fn
-                   ("  initializing argument %P of %qD from result of %qD",
-                    argnum, fn, convfn);
-               else
-                diagnostic_fn
-                  ("  initializing temporary from result of %qD",  convfn);
-             }
-           expr = build_cplus_new (totype, expr);
-         }
        return expr;
       }
     case ck_identity:
@@ -4518,7 +4515,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
       flags = LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING;
       if (convs->user_conv_p)
        /* This conversion is being done in the context of a user-defined
-          conversion, so don't allow any more.  */
+          conversion (i.e. the second step of copy-initialization), so
+          don't allow any more.  */
        flags |= LOOKUP_NO_CONVERSION;
       expr = build_temp (expr, totype, flags, &diagnostic_fn);
       if (diagnostic_fn && fn)
index 4b66c95efb5e6d692c8869f70b86e60697b30c68..63650dc3a8cef94667162c789443b69acfd2a416 100644 (file)
@@ -1,3 +1,8 @@
+2008-04-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35773
+       * g++.dg/overload/autoptr1.C: New.
+
 2008-04-17  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/alignment4.adb: New test.
diff --git a/gcc/testsuite/g++.dg/overload/autoptr1.C b/gcc/testsuite/g++.dg/overload/autoptr1.C
new file mode 100644 (file)
index 0000000..fc81083
--- /dev/null
@@ -0,0 +1,29 @@
+// PR c++/35773
+
+template< typename T >
+class auto_ptr
+{
+  struct auto_ptr_ref { };
+public:
+  auto_ptr(auto_ptr&);
+  auto_ptr(auto_ptr_ref);
+
+  operator auto_ptr_ref();
+};
+
+template< typename T >
+class reference_wrapper
+{
+public:
+  reference_wrapper(T& t);
+  operator T& () const;
+};
+
+struct X { };
+
+void f(auto_ptr< X >);
+
+void g(reference_wrapper< auto_ptr< X > > r)
+{
+  f(r);
+}