https://gcc.gnu.org/g:4e49ae8d905d760e97d0c0310f40c7e3a0e4e9df
commit r13-9512-g4e49ae8d905d760e97d0c0310f40c7e3a0e4e9df Author: Richard Biener <rguent...@suse.de> Date: Thu Mar 6 13:48:16 2025 +0100 lto/114501 - missed free-lang-data for CONSTRUCTOR index The following makes sure to also walk CONSTRUCTOR element indexes which can be FIELD_DECLs, referencing otherwise unused types we need to clean. walk_tree only walks CONSTRUCTOR element data. PR lto/114501 * ipa-free-lang-data.cc (find_decls_types_r): Explicitly handle CONSTRUCTORs as walk_tree handling of those is incomplete. * g++.dg/pr114501_0.C: New testcase. (cherry picked from commit fdd95e1cf29137a19baed25f8c817d320dfe63e3) Diff: --- gcc/ipa-free-lang-data.cc | 14 ++++++++++++++ gcc/testsuite/g++.dg/pr114501_0.C | 20 ++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc index b87063b5900d..b12cdb01e786 100644 --- a/gcc/ipa-free-lang-data.cc +++ b/gcc/ipa-free-lang-data.cc @@ -841,6 +841,20 @@ find_decls_types_r (tree *tp, int *ws, void *data) fld_worklist_push (tem, fld); fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld); } + /* walk_tree does not visit ce->index which can be a FIELD_DECL, pulling + in otherwise unused structure fields so handle CTORs explicitly. */ + else if (TREE_CODE (t) == CONSTRUCTOR) + { + unsigned HOST_WIDE_INT idx; + constructor_elt *ce; + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++) + { + if (ce->index) + fld_worklist_push (ce->index, fld); + fld_worklist_push (ce->value, fld); + } + *ws = 0; + } if (TREE_CODE (t) != IDENTIFIER_NODE && CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED)) diff --git a/gcc/testsuite/g++.dg/pr114501_0.C b/gcc/testsuite/g++.dg/pr114501_0.C new file mode 100644 index 000000000000..0439ee5f6e23 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr114501_0.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-require-effective-target c++17 } +// { dg-require-effective-target lto } +// { dg-options "-flto" } + +typedef long unsigned int size_t; +struct basic_string_view { + typedef long unsigned int size_type; + constexpr size_type size() const { return 0; } +}; +struct array { + char _M_elems[1]; +}; +inline constexpr auto make_it() { + constexpr basic_string_view view; + array arr{}; + arr._M_elems[view.size()] = 'a'; + return arr; +} +auto bar = make_it();