OSDN Git Service

2010-04-27 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Apr 2010 10:07:47 +0000 (10:07 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 27 Apr 2010 10:07:47 +0000 (10:07 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158777 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cgraphunit.c
gcc/ipa.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/pr43812.C [new file with mode: 0644]

index e254eec..f944bf5 100644 (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.
index fcb96b2..51b4732 100644 (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)
index 3a5ef16..8295357 100644 (file)
--- 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
index 72e61c0..9c0afd6 100644 (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...
diff --git a/gcc/testsuite/g++.dg/ipa/pr43812.C b/gcc/testsuite/g++.dg/ipa/pr43812.C
new file mode 100644 (file)
index 0000000..cc46eed
--- /dev/null
@@ -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 { }