aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraph.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2020-03-20 22:06:24 +0100
committerJan Hubicka <jh@suse.cz>2020-03-20 22:06:24 +0100
commit72b3bc895f023bf451357659cfe96c966945bdf9 (patch)
treeb50df34185a414a85416a84b69ca390fa091d954 /gcc/cgraph.c
parenta89349e664ff420f33612d47e486954de5848e49 (diff)
downloadgcc-72b3bc895f023bf451357659cfe96c966945bdf9.zip
gcc-72b3bc895f023bf451357659cfe96c966945bdf9.tar.gz
gcc-72b3bc895f023bf451357659cfe96c966945bdf9.tar.bz2
Fix verifier ICE on wrong comdat local flag [PR93347]
gcc/ChangeLog: 2020-03-20 Jan Hubicka <hubicka@ucw.cz> PR ipa/93347 * cgraph.c (symbol_table::create_edge): Update calls_comdat_local flag. (cgraph_edge::redirect_callee): Move here; likewise. (cgraph_node::remove_callees): Update calls_comdat_local flag. (cgraph_node::verify_node): Verify that calls_comdat_local flag match reality. (cgraph_node::check_calls_comdat_local_p): New member function. * cgraph.h (cgraph_node::check_calls_comdat_local_p): Declare. (cgraph_edge::redirect_callee): Move offline. * ipa-fnsummary.c (compute_fn_summary): Do not compute calls_comdat_local flag here. * ipa-inline-transform.c (inline_call): Fix updating of calls_comdat_local flag. * ipa-split.c (split_function): Use true instead of 1 to set the flag. * symtab.c (symtab_node::add_to_same_comdat_group): Update calls_comdat_local flag. gcc/testsuite/ChangeLog: 2020-03-20 Jan Hubicka <hubicka@ucw.cz> * g++.dg/torture/pr93347.C: New test.
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r--gcc/cgraph.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index b41dea1..6b780f8 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -557,7 +557,8 @@ cgraph_node::get_create (tree decl)
}
/* Mark ALIAS as an alias to DECL. DECL_NODE is cgraph node representing
- the function body is associated with (not necessarily cgraph_node (DECL). */
+ the function body is associated with
+ (not necessarily cgraph_node (DECL)). */
cgraph_node *
cgraph_node::create_alias (tree alias, tree target)
@@ -914,6 +915,10 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
else
edge->in_polymorphic_cdtor = caller->thunk.thunk_p;
+ if (callee && symtab->state != LTO_STREAMING
+ && edge->callee->comdat_local_p ())
+ edge->caller->calls_comdat_local = true;
+
return edge;
}
@@ -1341,6 +1346,34 @@ cgraph_edge::make_direct (cgraph_edge *edge, cgraph_node *callee)
return edge;
}
+/* Redirect callee of the edge to N. The function does not update underlying
+ call expression. */
+
+void
+cgraph_edge::redirect_callee (cgraph_node *n)
+{
+ bool loc = callee->comdat_local_p ();
+ /* Remove from callers list of the current callee. */
+ remove_callee ();
+
+ /* Insert to callers list of the new callee. */
+ set_callee (n);
+
+ if (!inline_failed)
+ return;
+ if (!loc && n->comdat_local_p ())
+ {
+ cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller;
+ to->calls_comdat_local = true;
+ }
+ else if (loc && !n->comdat_local_p ())
+ {
+ cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller;
+ gcc_checking_assert (to->calls_comdat_local);
+ to->calls_comdat_local = to->check_calls_comdat_local_p ();
+ }
+}
+
/* If necessary, change the function declaration in the call statement
associated with E so that it corresponds to the edge callee. Speculations
can be resolved in the process and EDGE can be removed and deallocated.
@@ -1674,6 +1707,8 @@ cgraph_node::remove_callees (void)
{
cgraph_edge *e, *f;
+ calls_comdat_local = false;
+
/* It is sufficient to remove the edges from the lists of callers of
the callees. The callee list of the node can be zapped with one
assignment. */
@@ -3369,10 +3404,18 @@ cgraph_node::verify_node (void)
error ("inline clone is forced to output");
error_found = true;
}
- if (calls_comdat_local && !same_comdat_group)
+ if (symtab->state != LTO_STREAMING)
{
- error ("calls_comdat_local is set outside of a comdat group");
- error_found = true;
+ if (calls_comdat_local && !same_comdat_group)
+ {
+ error ("calls_comdat_local is set outside of a comdat group");
+ error_found = true;
+ }
+ if (!inlined_to && calls_comdat_local != check_calls_comdat_local_p ())
+ {
+ error ("invalid calls_comdat_local flag");
+ error_found = true;
+ }
}
if (DECL_IS_MALLOC (decl)
&& !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
@@ -4044,6 +4087,19 @@ cgraph_edge::num_speculative_call_targets_p (void)
return indirect_info ? indirect_info->num_speculative_call_targets : 0;
}
+/* Check if function calls comdat local. This is used to recompute
+ calls_comdat_local flag after function transformations. */
+bool
+cgraph_node::check_calls_comdat_local_p ()
+{
+ for (cgraph_edge *e = callees; e; e = e->next_callee)
+ if (e->inline_failed
+ ? e->callee->comdat_local_p ()
+ : e->callee->check_calls_comdat_local_p ())
+ return true;
+ return false;
+}
+
/* A stashed copy of "symtab" for use by selftest::symbol_table_test.
This needs to be a global so that it can be a GC root, and thus
prevent the stashed copy from being garbage-collected if the GC runs