diff options
author | Marek Polacek <polacek@redhat.com> | 2025-03-25 13:36:24 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2025-04-01 08:36:49 -0400 |
commit | e9803f10c9f376f6d091e7ef3ad6e1c92e7c8e8c (patch) | |
tree | 6d7806246e420b305b1ab1b0e3719a06e590f55c /gcc/testsuite | |
parent | 182d891e13c78187f5e4f76512e03297fea0e56a (diff) | |
download | gcc-e9803f10c9f376f6d091e7ef3ad6e1c92e7c8e8c.zip gcc-e9803f10c9f376f6d091e7ef3ad6e1c92e7c8e8c.tar.gz gcc-e9803f10c9f376f6d091e7ef3ad6e1c92e7c8e8c.tar.bz2 |
c++: fix missing lifetime extension [PR119383]
Since r15-8011 cp_build_indirect_ref_1 won't do the *&TARGET_EXPR ->
TARGET_EXPR folding not to change its value category. That fix seems
correct but it made us stop extending the lifetime in this testcase,
causing a wrong-code issue -- extend_ref_init_temps_1 did not see
through the extra *& because it doesn't use a tree walk.
This patch reverts r15-8011 and instead handles the problem in
build_over_call by calling force_lvalue in the is_really_empty_class
case as well as in the general case.
PR c++/119383
gcc/cp/ChangeLog:
* call.cc (build_over_call): Use force_lvalue to ensure op= returns
an lvalue.
* cp-tree.h (force_lvalue): Declare.
* cvt.cc (force_lvalue): New.
* typeck.cc (cp_build_indirect_ref_1): Revert r15-8011.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/temp-extend3.C: New test.
Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/temp-extend3.C | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-extend3.C b/gcc/testsuite/g++.dg/cpp0x/temp-extend3.C new file mode 100644 index 0000000..3eab88d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/temp-extend3.C @@ -0,0 +1,32 @@ +// PR c++/119383 +// { dg-do run { target c++11 } } + +int g; + +struct base { + virtual base *clone() const = 0; + ~base() { } +}; + +struct impl : virtual base { + base *clone() const { return new impl; } // #1 + impl() { ++g; } + ~impl() { --g; } +}; + +const base * +make_a_clone () +{ + const base &base = impl{}; // #2 + return base.clone(); +} + +int +main () +{ + make_a_clone (); + // impl::impl() is called twice (#1 and #2), impl::~impl() once, + // at the end of make_a_clone. + if (g != 1) + __builtin_abort (); +} |