I finally found the recent discussion I mentioned earlier:

http://lists.isocpp.org/core/2018/06/4562.php

which hasn't made it into the issues list yet.

This discussion seems to suggest that the standard is likely to change
to allow this example and 87109, so fixing G++ to reject them may not
be what we want to do right now.


On Fri, Sep 7, 2018 at 4:30 AM, Marek Polacek <pola...@redhat.com> wrote:
> Another case where we weren't respecting the [class.copy.elision]/3 rule that
> "if the type of the first parameter of the selected constructor is not an
> rvalue reference to the object's type (possibly cv-qualified), overload
> resolution is performed again, considering the object as an lvalue." In this
> case the types differ because of the derived-to-base conversion.  As a result,
> we chose the wrong ctor.
>
> It seems that if we set rvaluedness_matches_p for ck_base, build_over_call
> then correctly returns error_mark_node for such ctor, because if sees that
> the CONVERSION_RANK is unsuitable.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2018-09-06  Marek Polacek  <pola...@redhat.com>
>
>         PR c++/87150 - wrong ctor with maybe-rvalue semantics.
>         * call.c (struct conversion): Update commentary.
>         (standard_conversion): Set rvaluedness_matches_p if 
> LOOKUP_PREFER_RVALUE
>         for ck_base.
>
>         * g++.dg/cpp0x/move-return2.C: New test.
>
> diff --git gcc/cp/call.c gcc/cp/call.c
> index 942b2c204be..03b4c5ab224 100644
> --- gcc/cp/call.c
> +++ gcc/cp/call.c
> @@ -102,10 +102,10 @@ struct conversion {
>    BOOL_BITFIELD base_p : 1;
>    /* If KIND is ck_ref_bind, true when either an lvalue reference is
>       being bound to an lvalue expression or an rvalue reference is
> -     being bound to an rvalue expression.  If KIND is ck_rvalue,
> +     being bound to an rvalue expression.  If KIND is ck_rvalue or ck_base,
>       true when we are treating an lvalue as an rvalue (12.8p33).  If
> -     KIND is ck_base, always false.  If ck_identity, we will be
> -     binding a reference directly or decaying to a pointer.  */
> +     ck_identity, we will be binding a reference directly or decaying to
> +     a pointer.  */
>    BOOL_BITFIELD rvaluedness_matches_p: 1;
>    BOOL_BITFIELD check_narrowing: 1;
>    /* Whether check_narrowing should only check TREE_CONSTANTs; used
> @@ -1425,6 +1425,9 @@ standard_conversion (tree to, tree from, tree expr, 
> bool c_cast_p,
>          type.  A temporary object is created to hold the result of
>          the conversion unless we're binding directly to a reference.  */
>        conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND);
> +      if (flags & LOOKUP_PREFER_RVALUE)
> +       /* Tell convert_like_real to set LOOKUP_PREFER_RVALUE.  */
> +       conv->rvaluedness_matches_p = true;
>      }
>    else
>      return NULL;
> diff --git gcc/testsuite/g++.dg/cpp0x/move-return2.C 
> gcc/testsuite/g++.dg/cpp0x/move-return2.C
> index e69de29bb2d..681e9ecaca1 100644
> --- gcc/testsuite/g++.dg/cpp0x/move-return2.C
> +++ gcc/testsuite/g++.dg/cpp0x/move-return2.C
> @@ -0,0 +1,11 @@
> +// PR c++/87150
> +// { dg-do compile { target c++11 } }
> +
> +struct S1 { S1(S1 &&); };
> +struct S2 : S1 {};
> +
> +S1
> +f (S2 s)
> +{
> +  return s; // { dg-error "use of deleted function" }
> +}

Reply via email to