Bug 53288 - [C++11] Lifetime of temporary object backing pointer-to-member expression not extended
Summary: [C++11] Lifetime of temporary object backing pointer-to-member expression not...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: 13.0
Assignee: Jason Merrill
URL:
Keywords: wrong-code
Depends on:
Blocks: 106094
  Show dependency treegraph
 
Reported: 2012-05-09 03:44 UTC by Hubert Tong
Modified: 2024-07-18 08:06 UTC (History)
7 users (show)

See Also:
Host: powerpc64-unknown-linux-gnu
Target: powerpc64-unknown-linux-gnu
Build:
Known to work:
Known to fail: 4.7.0, 4.8.5, 4.9.3, 5.3.0, 6.0
Last reconfirmed: 2016-01-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Hubert Tong 2012-05-09 03:44:42 UTC
In the reference initialization,
   const B &b = A(1).b;
the initializer expression is a class prvalue.

The requirement to bind an lvalue reference to a non-volatile const type
directly to a reference-compatible class prvalue dates back to DR 391 which
PR 25950 intended to implement.

The error messages complaining about the private and deleted move constructor
indicate that direct binding was not done.


### Self-contained source (tempbind_expr_ref.cpp):> cat tempbind_expr_ref.cpp
extern "C" int printf(const char *, ...);

struct B {
   B(int data) : _data(data) {
printf("ctor B(int) body:       (this=%p,_data=%d)\n", (void *)this, _data);
   }
   ~B() {
printf("dtor for B:             (this=%p,_data=%d)\n", (void *)this, _data);
   }

   int _data;

private:
   B() = delete;
   B(const B &) = delete;
   B(B &&) = delete;
};

struct A {
   B b;
   A(int data) : b(data) {
printf("ctor A(int) body:       (this=%p,_data=%d)\n", (void *)this, b._data);
   }
   ~A() {
printf("dtor for A:             (this=%p,_data=%d)\n", (void *)this, b._data);
   }

private:
   A() = delete;
   A(const A &) = delete;
   A(A &&) = delete;
};

const B &b = A(1).b;

int main() {
    printf("main() user body begins\n");
    printf("main() user body ends\n");
}


### Compiler invocation:
g++-4.6.0 tempbind_expr_ref.cpp -std=c++0x


### Compiler output:
tempbind_expr_ref.cpp:16:4: error: 'B::B(B&&)' is private
tempbind_expr_ref.cpp:34:19: error: within this context
tempbind_expr_ref.cpp:34:19: error: use of deleted function 'B::B(B&&)'
tempbind_expr_ref.cpp:16:4: error: declared here


### g++ -v output:> g++-4.6.0 -v
Using built-in specs.
COLLECT_GCC=g++-4.6.0
COLLECT_LTO_WRAPPER=/data/gcc/libexec/gcc/powerpc64-unknown-linux-gnu/4.6.0/lto-wrapper
Target: powerpc64-unknown-linux-gnu
Configured with: ./configure --prefix=/data/gcc --program-suffix=-4.6.0 --disable-libssp --disable-libgcj --enable-version-specific-runtime-libs --with-cpu=default32 --enable-secureplt --with-long-double-128 --enable-shared --enable-__cxa_atexit --enable-threads=posix --enable-languages=c,c++,fortran --with-gmp=/usr/local
Thread model: posix
gcc version 4.6.0 (GCC)
Comment 1 Jonathan Wakely 2012-05-09 17:23:42 UTC
It compiles fine with 4.7 or trunk.

I think this is a dup of an existing bug Jason fixed, possibly one he reported himself, about elements of rvalue arrays.
Comment 2 Hubert Tong 2012-06-07 21:36:54 UTC
(In reply to comment #1)
> It compiles fine with 4.7 or trunk.
> 
> I think this is a dup of an existing bug Jason fixed, possibly one he reported
> himself, about elements of rvalue arrays.

Confirmed that the above works as expected under 4.7.

However, replacing:
const B &b = A(1).b;

with:
const B &b = A(1).*(&A::b);

produces an executable whose output indicates that the lifetime of the temporary is not being extended:

ctor B(int) body:       (this=0xffe9f7d8,_data=1)
ctor A(int) body:       (this=0xffe9f7d8,_data=1)
dtor for A:             (this=0xffe9f7d8,_data=1)
dtor for B:             (this=0xffe9f7d8,_data=1)
main() user body begins
main() user body ends

### g++ -v output:> g++-4.7.0 -v
Using built-in specs.
COLLECT_GCC=g++-4.7.0
COLLECT_LTO_WRAPPER=/data/gcc/libexec/gcc/powerpc64-unknown-linux-gnu/4.7.0/lto-wrapper
Target: powerpc64-unknown-linux-gnu
Configured with: ../gcc-4.7.0/configure --prefix=/data/gcc --program-suffix=-4.7.0 --disable-libssp --disable-libgcj --enable-version-specific-runtime-libs --with-cpu=default32 --enable-secureplt --with-long-double-128 --enable-shared --enable-__cxa_atexit --enable-threads=posix --enable-languages=c,c++,fortran --with-mpfr=/usr/local/ --with-mpc=/usr/local/ --with-gmp=/usr/local/
Thread model: posix
gcc version 4.7.0 (GCC)
Comment 3 Martin Sebor 2016-01-20 00:25:04 UTC
Confirmed with the modified test case as indicated in comment #2 on trunk, 5.3.0, 4.9.3, and 4.8.5.  It doesn't look like it has ever been handled correctly.  The same on x86_64.
Comment 4 Egor 2022-06-09 18:00:20 UTC
Still happens on 12.1 and trunk.
Comment 5 GCC Commits 2023-01-23 00:36:31 UTC
The trunk branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:208c6678c25bd9a11e6c5911a4c123cb6b7f3d6e

commit r13-5283-g208c6678c25bd9a11e6c5911a4c123cb6b7f3d6e
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Dec 20 16:27:43 2022 -0500

    c++: lifetime extension with .* expression [PR53288]
    
    This PR points out a case where we are not extending the lifetime of a
    temporary when the subobject is denoted by a pointer-to-member operation.
    These rules were clarified in C++20 by CWG1299.
    
    There are other cases that also need to be handled under CWG1299, but are
    not fixed by this patch.
    
            PR c++/53288
            DR 1299
    
    gcc/cp/ChangeLog:
    
            * call.cc (extend_ref_init_temps_1): Handle ptrmem expression.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/init/lifetime4.C: New test.
Comment 6 Jason Merrill 2023-08-11 20:36:10 UTC
Fixed for GCC 13.
Comment 7 GCC Commits 2024-07-18 08:06:50 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:e217e7dbdc1040e7ee160796e9ca1ef12a0dd1cb

commit r15-2136-ge217e7dbdc1040e7ee160796e9ca1ef12a0dd1cb
Author: Sam James <sam@gentoo.org>
Date:   Thu Jul 18 10:00:17 2024 +0200

    testsuite: Add dg-do run to more tests
    
    All of these are for wrong-code bugs.  Confirmed to be used before but
    with no execution.
    
    2024-07-18  Sam James  <sam@gentoo.org>
    
            PR c++/53288
            PR c++/57437
            PR c/65345
            PR libstdc++/88101
            PR tree-optimization/96369
            PR tree-optimization/102124
            PR tree-optimization/108692
            * c-c++-common/pr96369.c: Add dg-do run directive.
            * gcc.dg/torture/pr102124.c: Ditto.
            * gcc.dg/pr108692.c: Ditto.
            * gcc.dg/atomic/pr65345-4.c: Ditto.
            * g++.dg/cpp0x/lambda/lambda-return1.C: Ditto.
            * g++.dg/init/lifetime4.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-1.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-2.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-3.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-4.C: Ditto.
            * g++.dg/torture/builtin-clear-padding-5.C: Ditto.