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

Marek Polacek mpolacek@gcc.gnu.org
Thu Jul 23 13:32:21 GMT 2026


https://gcc.gnu.org/g:706c0877e818b1035b763863b227d4d928ade421

commit r17-2663-g706c0877e818b1035b763863b227d4d928ade421
Author: Marek Polacek <polacek@redhat.com>
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 <jason@redhat.com>

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; }


More information about the Gcc-cvs mailing list