]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree: Fix up the DECL_VALUE_EXPR GC marking [PR118790]
authorJakub Jelinek <jakub@redhat.com>
Fri, 14 Feb 2025 11:01:13 +0000 (12:01 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 14 Feb 2025 11:01:13 +0000 (12:01 +0100)
The ggc_set_mark call in gt_value_expr_mark_2 is actually wrong, that
just marks the VAR_DECL itself, but doesn't mark the subtrees of it (type
etc.).  So, I think we need to test gcc_marked_p for whether it is marked
or not, if not marked walk the DECL_VALUE_EXPR and then gt_ggc_mx mark
the VAR_DECL that was determined not marked and needs to be marked now.
One option would be to call gt_ggc_mx (t) right after the DECL_VALUE_EXPR
walking, but I'm a little bit worried that the subtree marking could mark
other VAR_DECLs (e.g. seen from DECL_SIZE or TREE_TYPE and the like) and
if they would be DECL_HAS_VALUE_EXPR_P we might not walk their
DECL_VALUE_EXPR anymore later.
So, the patch defers the gt_ggc_mx calls until we've walked all the
DECL_VALUE_EXPRs directly or indirectly connected to already marked
VAR_DECLs.

2025-02-14  Jakub Jelinek  <jakub@redhat.com>

PR debug/118790
* tree.cc (struct gt_value_expr_mark_data): New type.
(gt_value_expr_mark_2): Don't call ggc_set_mark, instead check
ggc_marked_p.  Treat data as gt_value_expr_mark_data * with pset
in it rather than address of the pset itself and push to be marked
VAR_DECLs into to_mark vec.
(gt_value_expr_mark_1): Change argument from hash_set<tree> *
to gt_value_expr_mark_data * and find pset in it.
(gt_value_expr_mark): Pass to traverse_noresize address of
gt_value_expr_mark_data object rather than hash_table<tree> and
for all entries in the to_mark vector after the traversal call
gt_ggc_mx.

gcc/tree.cc

index 4319f8d41e6866c91889af869abc0e484a029cd9..0743ed71c789abcc85c1f381e0584d2b7402126b 100644 (file)
@@ -211,6 +211,11 @@ struct cl_option_hasher : ggc_cache_ptr_hash<tree_node>
 
 static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
 
+struct gt_value_expr_mark_data {
+  hash_set<tree> pset;
+  auto_vec<tree, 16> to_mark;
+};
+
 /* Callback called through walk_tree_1 to discover DECL_HAS_VALUE_EXPR_P
    VAR_DECLs which weren't marked yet, in that case marks them and
    walks their DECL_VALUE_EXPR expressions.  */
@@ -219,11 +224,12 @@ static tree
 gt_value_expr_mark_2 (tree *tp, int *, void *data)
 {
   tree t = *tp;
-  if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t) && !ggc_set_mark (t))
+  if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t) && !ggc_marked_p (t))
     {
       tree dve = DECL_VALUE_EXPR (t);
-      walk_tree_1 (&dve, gt_value_expr_mark_2, data,
-                  (hash_set<tree> *) data, NULL);
+      gt_value_expr_mark_data *d = (gt_value_expr_mark_data *) data;
+      walk_tree_1 (&dve, gt_value_expr_mark_2, data, &d->pset, NULL);
+      d->to_mark.safe_push (t);
     }
   return NULL_TREE;
 }
@@ -232,10 +238,10 @@ gt_value_expr_mark_2 (tree *tp, int *, void *data)
    value_expr_for_decl hash table.  */
 
 int
-gt_value_expr_mark_1 (tree_decl_map **e, hash_set<tree> *pset)
+gt_value_expr_mark_1 (tree_decl_map **e, gt_value_expr_mark_data *data)
 {
   if (ggc_marked_p ((*e)->base.from))
-    walk_tree_1 (&(*e)->to, gt_value_expr_mark_2, pset, pset, NULL);
+    walk_tree_1 (&(*e)->to, gt_value_expr_mark_2, data, &data->pset, NULL);
   return 1;
 }
 
@@ -255,8 +261,11 @@ gt_value_expr_mark (hash_table<tree_decl_map_cache_hasher> *h)
   if (!h)
     return;
 
-  hash_set<tree> pset;
-  h->traverse_noresize<hash_set<tree> *, gt_value_expr_mark_1> (&pset);
+  gt_value_expr_mark_data data;
+  h->traverse_noresize<gt_value_expr_mark_data *,
+                      gt_value_expr_mark_1> (&data);
+  for (auto v : data.to_mark)
+    gt_ggc_mx (v);
 }
 
 /* General tree->tree mapping  structure for use in hash tables.  */