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