https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118790

--- Comment #21 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #12)
> This looks like a GC bug.
> On the id_string.55 DECL_HAS_VALUE_EXPR_P bit is set and DECL_VALUE_EXPR is
> set to
> COMPONENT_REF during streaming in.
> But then
> #0  pointer_hash<tree_decl_map>::mark_deleted (e=@0x7fffea128850: 0x1) at
> ../../gcc/hash-traits.h:204
> #1  0x000000000110d844 in hash_table<tree_decl_map_cache_hasher, false,
> xcallocator>::mark_deleted (v=@0x7fffea128850: 0x1) at
> ../../gcc/hash-table.h:552
> #2  0x000000000110b81c in hash_table<tree_decl_map_cache_hasher, false,
> xcallocator>::clear_slot (this=0x7fffea12a070, slot=0x7fffea128850) at
> ../../gcc/hash-table.h:969
> #3  0x0000000001107f8c in gt_cleare_cache<tree_decl_map_cache_hasher>
> (h=0x7fffea12a070) at ../../gcc/hash-table.h:1315
> #4  0x0000000001104afe in gt_clear_caches_gt_tree_h () at ./gt-tree.h:497
> #5  0x000000000044c95a in gt_clear_caches () at ./gtype-lto.h:1926
> #6  0x0000000000771633 in ggc_mark_roots () at ../../gcc/ggc-common.cc:112
> #7  0x0000000000490cb8 in ggc_collect (mode=GGC_COLLECT_HEURISTIC) at
> ../../gcc/ggc-page.cc:2231
> #8  0x0000000000b0ce79 in execute_one_pass (pass=<opt_pass* 0x3d1db80
> "expand"(277)>) at ../../gcc/passes.cc:2751
> marks the it in the value_expr_for_decl as deleted, because is ggc_marked_p
> false on it.
> But that very same id_string.55 var is then ggc_set_mark marked because
> there is
> id_string var with *id_string.55 DECL_VALUE_EXPR later in the
> value_expr_for_decl hash table.
> 
> gt_cleare_cache does only one pass through a hash_map:
>   for (typename table::iterator iter = h->begin (); iter != h->end ();
> ++iter)
>     if (!table::is_empty (*iter) && !table::is_deleted (*iter))
>       {
>         int res = H::keep_cache_entry (*iter);
>         if (res == 0)
>           h->clear_slot (&*iter);
>         else if (res != -1)
>           H::ggc_mx (*iter);
>       }

So the issue is not that we remove id_string.55 var from the hash but
that somehow marking the id_string.55 using *id_string.55 faults then?
Why?  Is that really *X with X DECL_VALUE_EXPR being id_string.55 again
and X isn't marked before we process this hashtable?

> So, either the VAR_DECL should be reachable from something other than
> DECL_VALUE_EXPR expressions (bet it was originally in local decls of
> something), or we need to have two passes over hash_maps, in the first pass
> just H::ggc_mx (*iter) on entries where res is not 0 nor -1, and in the
> second pass clear_slot of res is 0.
> Guess that needs to be done only for hash tables where keep_cache_entry
> returns 0/1 rather than 0/-1, though no idea how to that out during
> instantiation.
> And I wonder about references from multiple cache hash maps, say
> DECL_DEBUG_EXPR refers to something which has DECL_VALUE_EXPR or vice versa.
> Wouldn't we then need to do it always in two passes for all the cache hash
> tables,
> during proper marking walk all those hash tables and just H::ggc_mx (*iter)
> when keep_cache_entry returns 1, and then once everything is marked repeat
> the walks and only do the clear_slot?

I think the VAR_DECL should be reachable from elsewhere (BLOCK_VARS ideally,
I'd like to get rid of local_decls).  IIRC I wondered at some point
whether remove_unused_locals needs to walk DECL_VALUE_EXPRs but I think
I went down an alternate place for the fix/PR I'm remembering (which now
makes it difficult to track down...).

Reply via email to