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
This commit is contained in:
Martin Jambor 2010-04-27 12:07:47 +02:00 committed by Martin Jambor
parent 5b56d3bbca
commit 78eaf7bf18
5 changed files with 108 additions and 8 deletions

View File

@ -1,3 +1,13 @@
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.
2010-04-27 Eric Botcazou <ebotcazou@adacore.com>
* varasm.c (decode_addr_const): Handle special case of INDIRECT_REF.

View File

@ -714,6 +714,32 @@ verify_cgraph_node (struct cgraph_node *node)
error ("double linked list of clones corrupted");
error_found = true;
}
if (node->same_comdat_group)
{
struct cgraph_node *n = node->same_comdat_group;
if (!DECL_ONE_ONLY (node->decl))
{
error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
error_found = true;
}
if (n == node)
{
error ("node is alone in a comdat group");
error_found = true;
}
do
{
if (!n->same_comdat_group)
{
error ("same_comdat_group is not a circular list");
error_found = true;
break;
}
n = n->same_comdat_group;
}
while (n != node);
}
if (node->analyzed && gimple_has_body_p (node->decl)
&& !TREE_ASM_WRITTEN (node->decl)

View File

@ -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

View File

@ -1,3 +1,8 @@
2010-04-27 Martin Jambor <mjambor@suse.cz>
PR middle-end/43812
* g++.dg/ipa/pr43812.C: New test.
2010-04-27 Jan Hubicka <jh@suse.cz>
* gcc.dg/ipa/iinline-1.c (main): Rename to...

View File

@ -0,0 +1,38 @@
/* { dg-do compile } */
/* { dg-options "-O -fwhole-program -fipa-cp" } */
typedef float scoord_t;
typedef scoord_t sdist_t;
typedef sdist_t dist_t;
template<typename T> class TRay { };
typedef TRay<dist_t> Ray;
class BBox { };
class RenderContext { };
class RefCounted {
public:
void deref () const {
if (--ref_count <= 0) {
delete this;
}
}
mutable int ref_count;
};
template<class T> class Ref {
public:
~Ref () {
if (obj) obj->deref ();
}
T *obj;
};
class Material : public RefCounted { };
class Surface {
public:
virtual ~Surface () { }
class IsecInfo { };
virtual const IsecInfo *intersect (Ray &ray, RenderContext &context) const;
Ref<const Material> material;
};
class LocalSurface : public Surface {
virtual BBox bbox () const;
};
BBox LocalSurface::bbox () const { }