From fd25a1d05fff30417b7821a77c0d034abc129baa Mon Sep 17 00:00:00 2001 From: jason Date: Thu, 17 Apr 2008 14:01:26 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@134398 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/call.c | 66 ++++++++++++++++---------------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/overload/autoptr1.C | 29 ++++++++++++++ 4 files changed, 73 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/autoptr1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 22a7420523d..3169ba0f366 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2008-04-17 Jason Merrill + + 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 PR c/35751 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 9835c86e3a2..c072a7df77f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 from an - auto_ptr). */ - 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4b66c95efb5..63650dc3a8c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-04-17 Jason Merrill + + PR c++/35773 + * g++.dg/overload/autoptr1.C: New. + 2008-04-17 Eric Botcazou * 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 index 00000000000..fc81083500e --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/autoptr1.C @@ -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); +} -- 2.11.4.GIT