[gcc r16-9376] 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:6a2c181f0f75cc4085b6e004973cc74c3922298c

commit r16-9376-g6a2c181f0f75cc4085b6e004973cc74c3922298c
Author: Marek Polacek <[email protected]>
Date:   Thu Jul 23 10:58:16 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.  So I'm afraid we have to
    recompute the flags unconditionally.  It may be a bit slower, but it's
    correct.
    
            PR c++/126215
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (replace_decl_r): Recompute the flags
            unconditionally.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1z/constexpr-nsdmi1.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>

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

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 34863d325267..9e783607a698 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3772,16 +3772,9 @@ replace_decl_r (tree *tp, int *walk_subtrees, void *data)
   if (TREE_CODE (*tp) == ADDR_EXPR)
     {
       d->pset->add (*tp);
-      auto save_changed = d->changed;
-      d->changed = false;
       cp_walk_tree (&TREE_OPERAND (*tp, 0), replace_decl_r, d, nullptr);
-      if (d->changed)
-	{
-	  cxx_mark_addressable (*tp);
-	  recompute_tree_invariant_for_addr_expr (*tp);
-	}
-      else
-	d->changed = save_changed;
+      cxx_mark_addressable (*tp);
+      recompute_tree_invariant_for_addr_expr (*tp);
       *walk_subtrees = 0;
     }
   else if (*tp == d->decl)
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.