diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e254eec84977b392854d2f3c3efb78ac00914d71..f944bf5920a7e1eafbc97eef0962a8ec177d74e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index fcb96b2044c1c965a3373b3d18b5e9459ccc8299..51b4732b45ad4135ccdbb580e85bfbf487d36f10 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -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) diff --git a/gcc/ipa.c b/gcc/ipa.c index 3a5ef16d2bea372a06eb8c1056b18fa35070964c..8295357cc0e50c06d478f170ddcb12e622621427 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 72e61c0e348f57337a6695cadcecd09adaa9f3be..9c0afd60faac78cb26acb12ba30de4d6d907f7f0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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... diff --git a/gcc/testsuite/g++.dg/ipa/pr43812.C b/gcc/testsuite/g++.dg/ipa/pr43812.C new file mode 100644 index 0000000000000000000000000000000000000000..cc46eed6501dc6f09f20680f62a01725fbe9d106 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr43812.C @@ -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 { }