aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2010-04-27 12:07:47 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2010-04-27 12:07:47 +0200
commit78eaf7bf186397f1ea7ca581c1e76e543eaac9b6 (patch)
tree815344fd064a1ca431cddb228100fe10fdc26f05 /gcc/ipa.c
parent5b56d3bbcab015c4dabf4c1ef82237ac0a37c792 (diff)
downloadgcc-78eaf7bf186397f1ea7ca581c1e76e543eaac9b6.zip
gcc-78eaf7bf186397f1ea7ca581c1e76e543eaac9b6.tar.gz
gcc-78eaf7bf186397f1ea7ca581c1e76e543eaac9b6.tar.bz2
re PR middle-end/43812 (compiling .cc file with -fwhole-program results in ICE, in ipcp_iterate_stage, at ipa-cp.c:760)
2010-04-27 Martin Jambor <mjambor@suse.cz> PR middle-end/43812 * ipa.c (dissolve_same_comdat_group_list): New function. (function_and_variable_visibility): Call dissolve_same_comdat_group_list when comdat group contains external or newly local nodes. * cgraphunit.c (verify_cgraph_node): Verify that same_comdat_group lists are circular and that they contain only DECL_ONE_ONLY nodes. * testsuite/g++.dg/ipa/pr43812.C: New test. From-SVN: r158777
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r--gcc/ipa.c37
1 files changed, 29 insertions, 8 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 3a5ef16..8295357 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -355,6 +355,21 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program)
return false;
}
+/* Dissolve the same_comdat_group list in which NODE resides. */
+
+static void
+dissolve_same_comdat_group_list (struct cgraph_node *node)
+{
+ struct cgraph_node *n = node, *next;
+ do
+ {
+ next = n->same_comdat_group;
+ n->same_comdat_group = NULL;
+ n = next;
+ }
+ while (n != node);
+}
+
/* Mark visibility of all functions.
A local function is one whose calls can occur only in the current
@@ -385,17 +400,17 @@ function_and_variable_visibility (bool whole_program)
and simplifies later passes. */
if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
{
- struct cgraph_node *n = node, *next;
- do
- {
+#ifdef ENABLE_CHECKING
+ struct cgraph_node *n;
+
+ for (n = node->same_comdat_group;
+ n != node;
+ n = n->same_comdat_group)
/* If at least one of same comdat group functions is external,
all of them have to be, otherwise it is a front-end bug. */
gcc_assert (DECL_EXTERNAL (n->decl));
- next = n->same_comdat_group;
- n->same_comdat_group = NULL;
- n = next;
- }
- while (n != node);
+#endif
+ dissolve_same_comdat_group_list (node);
}
gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
|| TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
@@ -411,6 +426,12 @@ function_and_variable_visibility (bool whole_program)
{
gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
cgraph_make_decl_local (node->decl);
+ if (node->same_comdat_group)
+ /* cgraph_externally_visible_p has already checked all other nodes
+ in the group and they will all be made local. We need to
+ dissolve the group at once so that the predicate does not
+ segfault though. */
+ dissolve_same_comdat_group_list (node);
}
node->local.local = (cgraph_only_called_directly_p (node)
&& node->analyzed