On Wed, Jul 22, 2026 at 04:34:46PM -0400, Jason Merrill wrote:
> On 7/21/26 4:06 PM, Marek Polacek wrote:
> > On Mon, Jul 20, 2026 at 04:34:57PM -0400, Jason Merrill wrote:
> > > On 7/20/26 1:00 PM, Marek Polacek wrote:
> > > > On Tue, Jul 14, 2026 at 11:35:04PM -0400, Jason Merrill wrote:
> > > > > On 7/14/26 7:06 PM, Marek Polacek wrote:
> > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
> > > > > > 
> > > > > > -- >8 --
> > > > > > Like in PR110822, the attached test produces an ICE in 
> > > > > > verify_address:
> > > > > > 
> > > > > >          error: constant not recomputed when 'ADDR_EXPR' changed
> > > > > > 
> > > > > > since r10-7718, but it wasn't fixed by r15-7762.  The reason is that
> > > > > > here we have:
> > > > > > 
> > > > > >      {.D.3013={.D.3006={.a={.ptr=&<retval>.D.3013.D.3006.a}},
> > > > > >                .D.3007={.b={.ptr=&<retval>.D.3013.D.3007.b}}}}
> > > > > > 
> > > > > > and we replace '<retval>' with 'names', but we only call
> > > > > > recompute_tree_invariant_expr for the first ADDR_EXPR, not the 
> > > > > > latter.
> > > > > > For the second ADDR_EXPR d->changed will be false: the first 
> > > > > > replacement
> > > > > > changed the shared tree <retval>.D.3013.  So I'm afraid we have to
> > > > > > recompute the flags unconditionally.  It may be a bit slower, but 
> > > > > > it's
> > > > > > correct.
> > > > > 
> > > > > OK for 16.
> > > > > 
> > > > > But how do we end up with this sharing?  It looks like
> > > > > replace_placeholders_r properly does unshare_expr.
> > > > 
> > > > There are no PLACEHOLDER_EXPR so the unshare_expr in 
> > > > replace_placeholders_r
> > > > won't take place.
> > > 
> > > Surely there's a PLACEHOLDER_EXPR created and replaced at some point for
> > > changing the 'this' in the DMI for bug::ptr to the two addresses above? If
> > > not, how does it happen?
> > 
> > True, once we're done with check_return_expr, we do have an expression
> > with PLACEHOLDER_EXPRs:
> > 
> >    TARGET_EXPR <D.3018, {.D.3013={.D.3006={.a={.ptr=&<PLACEHOLDER_EXPR 
> > struct bug>}}, .D.3007={.b={.ptr=&<PLACEHOLDER_EXPR struct bug>}}}}>
> > 
> > but they are replaced in cxx_eval_constant_expression/PLACEHOLDER_EXPR
> > when we call maybe_constant_value on the ctor containing them.
> 
> So maybe we should unshare then, perhaps in the return at the end of
> lookup_placeholder?

If you prefer that to always recomputing the flags, this works too.
So far dg.exp passed.

-- >8 --
Like in PR110822, the attached test produces an ICE in verify_address:

      error: constant not recomputed when 'ADDR_EXPR' changed

since r10-7718, but it wasn't fixed by r15-7762.  The reason is that
here we have:

  {.D.3013={.D.3006={.a={.ptr=&<retval>.D.3013.D.3006.a}},
            .D.3007={.b={.ptr=&<retval>.D.3013.D.3007.b}}}}

and we replace '<retval>' with 'names', but we only call
recompute_tree_invariant_expr for the first ADDR_EXPR, not the latter.
For the second ADDR_EXPR d->changed will be false: the first replacement
changed the shared tree <retval>.D.3013.  In replace_placeholders_r we
unshare_expr when replacing a PLACEHOLDER_EXPR, but we also replace
PLACEHOLDER_EXPRs in lookup_placeholder which didn't have this
unsharing.

        PR c++/126215

gcc/cp/ChangeLog:

        * constexpr.cc (lookup_placeholder): Do unshare_expr.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp1z/constexpr-nsdmi1.C: New test.
---
 gcc/cp/constexpr.cc                           |  3 ++-
 gcc/testsuite/g++.dg/cpp1z/constexpr-nsdmi1.C | 13 +++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-nsdmi1.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 868925012e5..fe2c417bed7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9012,7 +9012,8 @@ lookup_placeholder (const constexpr_ctx *ctx, value_cat 
lval, tree type)
        ob = NULL_TREE;
     }
 
-  return ob;
+  /* Like in replace_placeholders_r.  */
+  return unshare_expr (ob);
 }
 
 /* Complain about an attempt to evaluate inline assembly.  If FUNDEF_P is
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-nsdmi1.C 
b/gcc/testsuite/g++.dg/cpp1z/constexpr-nsdmi1.C
new file mode 100644
index 00000000000..a7f29e56a5d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-nsdmi1.C
@@ -0,0 +1,13 @@
+// PR c++/126215
+// { dg-do compile { target c++17 } }
+
+struct bug{ bug *ptr = this; };
+
+struct base0 { bug a; };
+struct base1 { bug b; };
+struct tuple_: base0, base1 {};
+struct tuple : tuple_ {};
+
+constexpr tuple gen() { return {}; }
+constexpr tuple names = gen();
+int main() { bug *x = names.b.ptr; }

base-commit: 7ec7871b363162d154266d2b052a3690ee4c6aa8
-- 
2.55.0

Reply via email to