On 3/25/25 3:37 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/14?

-- >8 --
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 is
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.  It is not
hard to fix that, but there may be other places that need this
adjustment.  :/

Hmm, this suggests to me that we should revert the 117512 patch and instead fix it in build_over_call, perhaps by forcing 'val' to be an lvalue after it's built rather than relying on 'to' being an lvalue already.

        PR c++/119383

gcc/cp/ChangeLog:

        * call.cc (extend_ref_init_temps_1): Handle *&TARGET_EXPR the same as
        TARGET_EXPR.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/temp-extend3.C: New test.
---
  gcc/cp/call.cc                            |  6 +++++
  gcc/testsuite/g++.dg/cpp0x/temp-extend3.C | 32 +++++++++++++++++++++++
  2 files changed, 38 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/temp-extend3.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index c1c8987ec8b..ed2bdc85d87 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14835,6 +14835,12 @@ extend_ref_init_temps_1 (tree decl, tree init, vec<tree, 
va_gc> **cleanups,
    for (p = &TREE_OPERAND (sub, 0);
         TREE_CODE (*p) == COMPONENT_REF || TREE_CODE (*p) == ARRAY_REF; )
      p = &TREE_OPERAND (*p, 0);
+  /* cp_build_indirect_ref_1 leaves *&TARGET_EXPR intact, handle it here.  */
+  if (INDIRECT_REF_P (*p)
+      && TREE_CODE (TREE_OPERAND (*p, 0)) == ADDR_EXPR
+      && same_type_p (TREE_TYPE (*p),
+                     TREE_TYPE (TREE_TYPE (TREE_OPERAND (*p, 0)))))
+    p = &TREE_OPERAND (TREE_OPERAND (*p, 0), 0);
    if (TREE_CODE (*p) == TARGET_EXPR)
      {
        tree subinit = NULL_TREE;
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 00000000000..3eab88d0076
--- /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 ();
+}

base-commit: 927cfea902c330092848bd7a228b714b07d08f6b

Reply via email to