aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2025-03-25 13:36:24 -0400
committerMarek Polacek <polacek@redhat.com>2025-04-01 08:36:49 -0400
commite9803f10c9f376f6d091e7ef3ad6e1c92e7c8e8c (patch)
tree6d7806246e420b305b1ab1b0e3719a06e590f55c /gcc/testsuite
parent182d891e13c78187f5e4f76512e03297fea0e56a (diff)
downloadgcc-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.C32
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 ();
+}