]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lto/114501 - missed free-lang-data for CONSTRUCTOR index
authorRichard Biener <rguenther@suse.de>
Thu, 6 Mar 2025 12:48:16 +0000 (13:48 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 2 Apr 2025 12:00:17 +0000 (14:00 +0200)
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)

gcc/ipa-free-lang-data.cc
gcc/testsuite/g++.dg/pr114501_0.C [new file with mode: 0644]

index b04bc5f3d89a74a841f99a3d56e2c5d4242075ff..ff87c205b1c524fec5c52b9480315e515c107aa8 100644 (file)
@@ -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 (file)
index 0000000..0439ee5
--- /dev/null
@@ -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();