public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called?
@ 2013-04-25  0:29 thiago at kde dot org
  2013-04-25  0:45 ` [Bug c++/57064] " thiago at kde dot org
                   ` (14 more replies)
  0 siblings, 15 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  0:29 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

             Bug #: 57064
           Summary: [clarification requested] Which overload with
                    ref-qualifier should be called?
    Classification: Unclassified
           Product: gcc
           Version: 4.8.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned@gcc.gnu.org
        ReportedBy: thiago@kde.org


I'm not sure this is a bug. I am requesting clarification on the behaviour.

>From the C++11 standard (13.3.3.2 [over.ics.rank] p 3):

struct A {
    void p() &;
    void p() &&;
};

void f()
{
    A a;
    a.p();
    A().p();
}

GCC 4.8.1 correctly calls the lvalue-ref overload first, then the rvalue
overload second.

Now suppose the following function:

void g(A &&a)
{
    a.p();
}

Which overload should GCC call? This is my request for clarification. I
couldn't find anything specific in the standard that would help explain one way
or the other.

Intuitively, it would be the rvalue overload, but gcc calls the lvalue overload
instead. Making it:

    std::move(a).p();

Does not help.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
@ 2013-04-25  0:45 ` thiago at kde dot org
  2013-04-25  0:45 ` thiago at kde dot org
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  0:45 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #1 from Thiago Macieira <thiago at kde dot org> 2013-04-25 00:45:00 UTC ---
Here's why I'm asking:

QString has members like:

    QString arg(int, [other parameters]) const;

Which are used like so:

    return QString("%1 %2 %3 %4").arg(42).arg(47).arg(-42).arg(-47);
    // returns "42 47 -42 -47"

Right now, each call creates a new temporary, which is required to do memory
allocation. I'd like to avoid the new temporaries by simply reusing the
existing ones:

    QString arg(int, [...]) const &; // returns a new copy
    QString &&arg(int, [...]) &&; // modifies this object, return *this;

When these two overloads are present, every other call will be to rvalue-ref
and the others to lvalue-ref. That is, the first call (right after the
constructor) calls arg()&&, which returns an rvalue-ref. The next call will be
to arg()&, which returns a temporary, making the third call to arg()&& again.

I can get the desired behaviour by using the overloads:

    QString arg(int, [...]) const &; // returns a new copy
    QString arg(int, [...]) &&; // returns a moved temporary via return
std::move(*this);

However, the side-effect of that is that we still have 4 temporaries too many,
albeit empty (moved-out) ones. You can see this by counting the number of calls
to the destructor:

$ ~/gcc4.8/bin/g++ -fverbose-asm -fno-exceptions -fPIE -std=c++11 -S -o -
-I$QTOBJDIR/include /tmp/test.cpp | grep -B1 call.*QStringD
        movq    %rax, %rdi      # tmp82,
        call    _ZN7QStringD1Ev@PLT     #
--
        movq    %rax, %rdi      # tmp83,
        call    _ZN7QStringD1Ev@PLT     #
--
        movq    %rax, %rdi      # tmp84,
        call    _ZN7QStringD1Ev@PLT     #
--
        movq    %rax, %rdi      # tmp85,
        call    _ZN7QStringD1Ev@PLT     #


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
  2013-04-25  0:45 ` [Bug c++/57064] " thiago at kde dot org
@ 2013-04-25  0:45 ` thiago at kde dot org
  2013-04-25  0:53 ` thiago at kde dot org
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  0:45 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #2 from Thiago Macieira <thiago at kde dot org> 2013-04-25 00:45:39 UTC ---
This was a self-compiled, pristine GCC

gcc version 4.8.1 20130420 (prerelease) (GCC) 
trunk at 198107


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
  2013-04-25  0:45 ` [Bug c++/57064] " thiago at kde dot org
  2013-04-25  0:45 ` thiago at kde dot org
@ 2013-04-25  0:53 ` thiago at kde dot org
  2013-04-25  6:19 ` glisse at gcc dot gnu.org
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  0:53 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #3 from Thiago Macieira <thiago at kde dot org> 2013-04-25 00:53:20 UTC ---
One more note. Given:

void p(A &);
void p(A &&);

void f(A &&a)
{
    p(a);
}

like the member function case, this calls p(A &). It's slightly surprising at
first glance, but is a known and documented case.

Unlike the member function case, if you do

    p(std::move(a));

it will call p(A &&).


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (2 preceding siblings ...)
  2013-04-25  0:53 ` thiago at kde dot org
@ 2013-04-25  6:19 ` glisse at gcc dot gnu.org
  2013-04-25  6:34 ` glisse at gcc dot gnu.org
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: glisse at gcc dot gnu.org @ 2013-04-25  6:19 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #4 from Marc Glisse <glisse at gcc dot gnu.org> 2013-04-25 06:19:35 UTC ---
(In reply to comment #0)
> Now suppose the following function:
> 
> void g(A &&a)
> {
>     a.p();
> }
> 
> Which overload should GCC call? This is my request for clarification. I
> couldn't find anything specific in the standard that would help explain one way
> or the other.
> 
> Intuitively, it would be the rvalue overload, but gcc calls the lvalue overload
> instead.

As you note in a further comment, a named rvalue reference acts as an lvalue.

> Making it:
> 
>     std::move(a).p();
> 
> Does not help.

It does for me...


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (3 preceding siblings ...)
  2013-04-25  6:19 ` glisse at gcc dot gnu.org
@ 2013-04-25  6:34 ` glisse at gcc dot gnu.org
  2013-04-25  6:51 ` thiago at kde dot org
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: glisse at gcc dot gnu.org @ 2013-04-25  6:34 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #5 from Marc Glisse <glisse at gcc dot gnu.org> 2013-04-25 06:34:03 UTC ---
(In reply to comment #4)
> (In reply to comment #0)
> > Making it:
> > 
> >     std::move(a).p();
> > 
> > Does not help.
> 
> It does for me...

Note that I only tested 4.9, it could be something missing in the backport.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (4 preceding siblings ...)
  2013-04-25  6:34 ` glisse at gcc dot gnu.org
@ 2013-04-25  6:51 ` thiago at kde dot org
  2013-04-25  7:13 ` thiago at kde dot org
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  6:51 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #6 from Thiago Macieira <thiago at kde dot org> 2013-04-25 06:51:33 UTC ---
void f(A &&a)
{
    std::move(a).p();
}

_Z1fO1A:
        .cfi_startproc
        jmp     _ZNR1A1pEv@PLT  #
        .cfi_endproc

Then this looks like a bug in 4.8.1.

But then are we in agreement that a.p() in that function above should call the
lvalue-ref overload? It does make the feature sligthly less useful for me. It
would require writing:

    return std::move(std::move(std::move(std::move(QString("%1 %2 %3 %4")
                                                   .arg(42))
                                          .arg(47))
                               .arg(-42))
                     .arg(-47));


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (5 preceding siblings ...)
  2013-04-25  6:51 ` thiago at kde dot org
@ 2013-04-25  7:13 ` thiago at kde dot org
  2013-04-25  7:28 ` glisse at gcc dot gnu.org
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  7:13 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #8 from Thiago Macieira <thiago at kde dot org> 2013-04-25 07:13:44 UTC ---
Hmm... this might be an effect of the same bug. Can you try this on 4.9?

struct A {
    A p() const &;
    A &&p() &&;
};

void f()
{
    A().p().p();
}

I get:
        leaq    15(%rsp), %rdi  #, tmp60
        call    _ZNO1A1pEv@PLT  #
        movq    %rax, %rdi      # D.69575,
        call    _ZNKR1A1pEv@PLT #

Is this second call supposed to be to R? If it's to O, it's exactly what I need
to make the feature useful.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (6 preceding siblings ...)
  2013-04-25  7:13 ` thiago at kde dot org
@ 2013-04-25  7:28 ` glisse at gcc dot gnu.org
  2013-04-25  7:34 ` thiago at kde dot org
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: glisse at gcc dot gnu.org @ 2013-04-25  7:28 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #9 from Marc Glisse <glisse at gcc dot gnu.org> 2013-04-25 07:28:01 UTC ---
(In reply to comment #8)
> Is this second call supposed to be to R? If it's to O, it's exactly what I need
> to make the feature useful.

It is O.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (7 preceding siblings ...)
  2013-04-25  7:28 ` glisse at gcc dot gnu.org
@ 2013-04-25  7:34 ` thiago at kde dot org
  2013-04-25 14:42 ` jason at gcc dot gnu.org
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-25  7:34 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #10 from Thiago Macieira <thiago at kde dot org> 2013-04-25 07:34:21 UTC ---
Great! That changes everything. Now I can provide a mutating arg() overload.

I'll just need some #ifdef and build magic to add the R, O overloads without
removing the <nil> overloads that already exist (binary compatibility). It
would have been nicer if the lvalue ref overload didn't get extra decoration.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (8 preceding siblings ...)
  2013-04-25  7:34 ` thiago at kde dot org
@ 2013-04-25 14:42 ` jason at gcc dot gnu.org
  2013-04-25 17:50 ` jason at gcc dot gnu.org
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: jason at gcc dot gnu.org @ 2013-04-25 14:42 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2013-04-25
         AssignedTo|unassigned at gcc dot       |jason at gcc dot gnu.org
                   |gnu.org                     |
   Target Milestone|---                         |4.8.1
     Ever Confirmed|0                           |1

--- Comment #11 from Jason Merrill <jason at gcc dot gnu.org> 2013-04-25 14:42:43 UTC ---
Yep, this is a bug in 4.8.1 that was fixed in 4.9 by my follow-on change

        * call.c (add_function_candidate): Take the address of 'this' here.
        (build_over_call): And here.
        (build_new_method_call_1, build_op_call_1): Not here.
        (build_user_type_conversion_1): Or here.
        (add_candidates): Adjust.

that I thought was too risky for the branch.  I'll fix this differently on the
branch.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (9 preceding siblings ...)
  2013-04-25 14:42 ` jason at gcc dot gnu.org
@ 2013-04-25 17:50 ` jason at gcc dot gnu.org
  2013-04-26  5:05 ` glisse at gcc dot gnu.org
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: jason at gcc dot gnu.org @ 2013-04-25 17:50 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |RESOLVED
         Resolution|                            |FIXED

--- Comment #12 from Jason Merrill <jason at gcc dot gnu.org> 2013-04-25 17:50:25 UTC ---
Fixed.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (10 preceding siblings ...)
  2013-04-25 17:50 ` jason at gcc dot gnu.org
@ 2013-04-26  5:05 ` glisse at gcc dot gnu.org
  2013-04-26  6:16 ` thiago at kde dot org
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 16+ messages in thread
From: glisse at gcc dot gnu.org @ 2013-04-26  5:05 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #13 from Marc Glisse <glisse at gcc dot gnu.org> 2013-04-26 05:05:48 UTC ---
Note for Thiago: please be aware of the risks of returning an rvalue reference,
as opposed to just a value. The following codes will fail at runtime:

Qstring const& a=QString("%1 %2 %3 %4").arg(42).arg(47).arg(-42).arg(-47);
Qstring && b=QString("%1 %2 %3 %4").arg(42).arg(47).arg(-42).arg(-47);
for(char c : QString("%1 %2 %3 %4").arg(42).arg(47).arg(-42).arg(-47))...


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (11 preceding siblings ...)
  2013-04-26  5:05 ` glisse at gcc dot gnu.org
@ 2013-04-26  6:16 ` thiago at kde dot org
  2013-04-26  8:12 ` redi at gcc dot gnu.org
  2013-04-26 13:45 ` thiago at kde dot org
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-26  6:16 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #14 from Thiago Macieira <thiago at kde dot org> 2013-04-26 06:16:04 UTC ---
Understood. The idea is that one would write:

  QString str = QString("%1 %2").arg(42).arg(43);


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (12 preceding siblings ...)
  2013-04-26  6:16 ` thiago at kde dot org
@ 2013-04-26  8:12 ` redi at gcc dot gnu.org
  2013-04-26 13:45 ` thiago at kde dot org
  14 siblings, 0 replies; 16+ messages in thread
From: redi at gcc dot gnu.org @ 2013-04-26  8:12 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #15 from Jonathan Wakely <redi at gcc dot gnu.org> 2013-04-26 08:12:36 UTC ---
That will also work if you return an rvalue, not an rvalue reference, and will
be safe against accidental misuse.


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [Bug c++/57064] [clarification requested] Which overload with ref-qualifier should be called?
  2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
                   ` (13 preceding siblings ...)
  2013-04-26  8:12 ` redi at gcc dot gnu.org
@ 2013-04-26 13:45 ` thiago at kde dot org
  14 siblings, 0 replies; 16+ messages in thread
From: thiago at kde dot org @ 2013-04-26 13:45 UTC (permalink / raw)
  To: gcc-bugs


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064

--- Comment #16 from Thiago Macieira <thiago at kde dot org> 2013-04-26 13:45:35 UTC ---
Thanks for the hint.

However, returning an rvalue, even if moved-onto, will generate code for the
destructor. It's not a matter of efficiency, just of code size.

Anyway, I'll do some benchmarks, after I figure out how to work around the
binary compatibility break imposed by having the & in the function that already
existed.


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2013-04-26 13:45 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-25  0:29 [Bug c++/57064] New: [clarification requested] Which overload with ref-qualifier should be called? thiago at kde dot org
2013-04-25  0:45 ` [Bug c++/57064] " thiago at kde dot org
2013-04-25  0:45 ` thiago at kde dot org
2013-04-25  0:53 ` thiago at kde dot org
2013-04-25  6:19 ` glisse at gcc dot gnu.org
2013-04-25  6:34 ` glisse at gcc dot gnu.org
2013-04-25  6:51 ` thiago at kde dot org
2013-04-25  7:13 ` thiago at kde dot org
2013-04-25  7:28 ` glisse at gcc dot gnu.org
2013-04-25  7:34 ` thiago at kde dot org
2013-04-25 14:42 ` jason at gcc dot gnu.org
2013-04-25 17:50 ` jason at gcc dot gnu.org
2013-04-26  5:05 ` glisse at gcc dot gnu.org
2013-04-26  6:16 ` thiago at kde dot org
2013-04-26  8:12 ` redi at gcc dot gnu.org
2013-04-26 13:45 ` thiago at kde dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).