Bug 106882 - passing X as 'this' argument discards qualifiers
Summary: passing X as 'this' argument discards qualifiers
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 13.0
Assignee: Marek Polacek
URL:
Keywords: rejects-valid
Depends on:
Blocks: 101165
  Show dependency treegraph
 
Reported: 2022-09-07 19:58 UTC by Marek Polacek
Modified: 2024-02-06 17:58 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-09-07 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2022-09-07 19:58:57 UTC
This should be accepted:

struct Mutt {
    operator int*() &&;
};

int* five(Mutt x) {
  return x;  // OK since C++20 because P1155
}

but is currently rejected with error: passing ‘Mutt’ as ‘this’ argument discards qualifiers [-fpermissive]

Maybe we're not checking IMPLICIT_RVALUE_P where needed.

This blocks P2266.
Comment 1 GCC Commits 2022-09-27 23:36:26 UTC
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:772d532e0ba1e4b22c2b7d576e14b34ee929c093

commit r13-2905-g772d532e0ba1e4b22c2b7d576e14b34ee929c093
Author: Marek Polacek <polacek@redhat.com>
Date:   Wed Aug 31 17:37:59 2022 -0400

    c++: Implement C++23 P2266R1, Simpler implicit move [PR101165]
    
    This patch implements https://wg21.link/p2266, which, once again,
    changes the implicit move rules.  Here's a brief summary of various
    changes in this area:
    
    r125211: Introduced moving from certain lvalues when returning them
    r171071: CWG 1148, enable move from value parameter on return
    r212099: CWG 1579, it's OK to call a converting ctor taking an rvalue
    r251035: CWG 1579, do maybe-rvalue overload resolution twice
    r11-2411: Avoid calling const copy ctor on implicit move
    r11-2412: C++20 implicit move changes, remove the fallback overload
              resolution, allow move on throw of parameters and implicit
              move of rvalue references
    
    P2266 enables the implicit move even for functions that return references.
    That is, we will now perform a move in
    
      X&& foo (X&& x) {
        return x;
      }
    
    P2266 also removes the fallback overload resolution, but this was
    resolved by r11-2412: we only do convert_for_initialization with
    LOOKUP_PREFER_RVALUE in C++17 and older.
    P2266 also says that a returned move-eligible id-expression is always an
    xvalue.  This required some further short, but nontrivial changes,
    especially when it comes to deduction, because we have to pay attention
    to whether we have auto, auto&& (which is like T&&), or decltype(auto)
    with (un)parenthesized argument.  In C++23,
    
      decltype(auto) f(int&& x) { return (x); }
      auto&& f(int x) { return x; }
    
    both should deduce to 'int&&' but
    
      decltype(auto) f(int x) { return x; }
    
    should deduce to 'int'.  A cornucopia of tests attached.  I've also
    verified that we behave like clang++.
    
    xvalue_p seemed to be broken: since the introduction of clk_implicit_rval,
    it cannot use '==' when checking for clk_rvalueref.
    
    Since this change breaks code, it's only enabled in C++23.  In
    particular, this code will not compile in C++23:
    
      int& g(int&& x) { return x; }
    
    because x is now treated as an rvalue, and you can't bind a non-const lvalue
    reference to an rvalue.
    
    This patch also fixes PR106882 (the check_return_expr changes).
    
            PR c++/101165
            PR c++/106882
    
    gcc/c-family/ChangeLog:
    
            * c-cppbuiltin.cc (c_cpp_builtins): Define __cpp_implicit_move.
    
    gcc/cp/ChangeLog:
    
            * call.cc (reference_binding): Check clk_implicit_rval in C++20 only.
            * cp-tree.h (unparenthesized_id_or_class_member_access_p): Declare.
            * pt.cc (unparenthesized_id_or_class_member_access_p): New function,
            broken out of...
            (do_auto_deduction): ...here.  Use it.  In C++23, maybe call
            treat_lvalue_as_rvalue_p.
            * tree.cc (xvalue_p): Check & clk_rvalueref, not == clk_rvalueref.
            * typeck.cc (check_return_expr): Allow implicit move for functions
            returning a reference as well, or when the return value type is not
            a scalar type.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/conversion/pr41426.C: Add dg-error for C++23.
            * g++.dg/cpp0x/elision_weak.C: Likewise.
            * g++.dg/cpp0x/move-return3.C: Only link in c++20_down.
            * g++.dg/cpp1y/decltype-auto2.C: Add dg-error for C++23.
            * g++.dg/cpp1y/lambda-generic-89419.C: Likewise.
            * g++.dg/cpp23/feat-cxx2b.C: Test __cpp_implicit_move.
            * g++.dg/gomp/pr56217.C: Only compile in c++20_down.
            * g++.dg/warn/Wno-return-local-addr.C: Add dg-error for C++23.
            * g++.dg/warn/Wreturn-local-addr.C: Adjust dg-error.
            * g++.old-deja/g++.brendan/crash55.C: Add dg-error for C++23.
            * g++.old-deja/g++.jason/temporary2.C: Likewise.
            * g++.old-deja/g++.mike/p2846b.C: Adjust.
            * g++.dg/cpp1y/decltype-auto6.C: New test.
            * g++.dg/cpp23/decltype1.C: New test.
            * g++.dg/cpp23/decltype2.C: New test.
            * g++.dg/cpp23/elision1.C: New test.
            * g++.dg/cpp23/elision2.C: New test.
            * g++.dg/cpp23/elision3.C: New test.
            * g++.dg/cpp23/elision4.C: New test.
            * g++.dg/cpp23/elision5.C: New test.
            * g++.dg/cpp23/elision6.C: New test.
            * g++.dg/cpp23/elision7.C: New test.
Comment 2 Marek Polacek 2022-09-27 23:39:58 UTC
Fixed (in C++23).