[gcc r17-2663] c++: constant not recomputed when ADDR_EXPR changed [PR126215]

Marek Polacek via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:706c0877e818b1035b763863b227d4d928ade421

commit r17-2663-g706c0877e818b1035b763863b227d4d928ade421
Author: Marek Polacek <[email protected]>
Date:   Wed Jul 22 17:28:03 2026 -0400

    c++: constant not recomputed when ADDR_EXPR changed [PR126215]
    
    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.
    
    Reviewed-by: Jason Merrill <[email protected]>

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 868925012e58..fe2c417bed7a 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 000000000000..a7f29e56a5d1
--- /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; }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.