OSDN Git Service

Fix for PR c++/43327
[pf3gnuchains/gcc-fork.git] / gcc / cgraph.c
index a3efdfc..0e02bae 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
@@ -86,6 +86,7 @@ The callgraph:
 #include "value-prof.h"
 #include "except.h"
 #include "diagnostic.h"
+#include "rtl.h"
 
 static void cgraph_node_remove_callers (struct cgraph_node *node);
 static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
@@ -1443,6 +1444,20 @@ cgraph_remove_node (struct cgraph_node *node)
   while (node->same_body)
     cgraph_remove_same_body_alias (node->same_body);
 
+  if (node->same_comdat_group)
+    {
+      struct cgraph_node *prev;
+      for (prev = node->same_comdat_group;
+          prev->same_comdat_group != node;
+          prev = prev->same_comdat_group)
+       ;
+      if (node->same_comdat_group == prev)
+       prev->same_comdat_group = NULL;
+      else
+       prev->same_comdat_group = node->same_comdat_group;
+      node->same_comdat_group = NULL;
+    }
+
   /* While all the clones are removed after being proceeded, the function
      itself is kept in the cgraph even after it is compiled.  Check whether
      we are done with this body and reclaim it proactively if this is the case.
@@ -2172,7 +2187,44 @@ bool
 cgraph_node_can_be_local_p (struct cgraph_node *node)
 {
   return (!node->needed
-         && (DECL_COMDAT (node->decl) || !node->local.externally_visible));
+         && ((DECL_COMDAT (node->decl) && !node->same_comdat_group)
+             || !node->local.externally_visible));
+}
+
+/* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
+   but other code such as notice_global_symbol generates rtl.  */
+void
+cgraph_make_decl_local (tree decl)
+{
+  rtx rtl, symbol;
+
+  if (TREE_CODE (decl) == VAR_DECL)
+    DECL_COMMON (decl) = 0;
+  else if (TREE_CODE (decl) == FUNCTION_DECL)
+    {
+      DECL_COMDAT (decl) = 0;
+      DECL_COMDAT_GROUP (decl) = 0;
+      DECL_WEAK (decl) = 0;
+      DECL_EXTERNAL (decl) = 0;
+    }
+  else
+    gcc_unreachable ();
+  TREE_PUBLIC (decl) = 0;
+  if (!DECL_RTL_SET_P (decl))
+    return;
+
+  /* Update rtl flags.  */
+  make_decl_rtl (decl);
+
+  rtl = DECL_RTL (decl);
+  if (!MEM_P (rtl))
+    return;
+
+  symbol = XEXP (rtl, 0);
+  if (GET_CODE (symbol) != SYMBOL_REF)
+    return;
+
+  SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
 }
 
 /* Bring NODE local.  */
@@ -2182,15 +2234,65 @@ cgraph_make_node_local (struct cgraph_node *node)
   gcc_assert (cgraph_node_can_be_local_p (node));
   if (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
     {
-      DECL_COMDAT (node->decl) = 0;
-      DECL_COMDAT_GROUP (node->decl) = 0;
-      TREE_PUBLIC (node->decl) = 0;
-      DECL_WEAK (node->decl) = 0;
-      DECL_EXTERNAL (node->decl) = 0;
+      struct cgraph_node *alias;
+      cgraph_make_decl_local (node->decl);
+
+      for (alias = node->same_body; alias; alias = alias->next)
+       cgraph_make_decl_local (alias->decl);
+
       node->local.externally_visible = false;
       node->local.local = true;
       gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL);
     }
 }
 
+/* Set TREE_NOTHROW on NODE's decl and on same_body aliases of NODE
+   if any to NOTHROW.  */
+
+void
+cgraph_set_nothrow_flag (struct cgraph_node *node, bool nothrow)
+{
+  struct cgraph_node *alias;
+  TREE_NOTHROW (node->decl) = nothrow;
+  for (alias = node->same_body; alias; alias = alias->next)
+    TREE_NOTHROW (alias->decl) = nothrow;
+}
+
+/* Set TREE_READONLY on NODE's decl and on same_body aliases of NODE
+   if any to READONLY.  */
+
+void
+cgraph_set_readonly_flag (struct cgraph_node *node, bool readonly)
+{
+  struct cgraph_node *alias;
+  TREE_READONLY (node->decl) = readonly;
+  for (alias = node->same_body; alias; alias = alias->next)
+    TREE_READONLY (alias->decl) = readonly;
+}
+
+/* Set DECL_PURE_P on NODE's decl and on same_body aliases of NODE
+   if any to PURE.  */
+
+void
+cgraph_set_pure_flag (struct cgraph_node *node, bool pure)
+{
+  struct cgraph_node *alias;
+  DECL_PURE_P (node->decl) = pure;
+  for (alias = node->same_body; alias; alias = alias->next)
+    DECL_PURE_P (alias->decl) = pure;
+}
+
+/* Set DECL_LOOPING_CONST_OR_PURE_P on NODE's decl and on
+   same_body aliases of NODE if any to LOOPING_CONST_OR_PURE.  */
+
+void
+cgraph_set_looping_const_or_pure_flag (struct cgraph_node *node,
+                                      bool looping_const_or_pure)
+{
+  struct cgraph_node *alias;
+  DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping_const_or_pure;
+  for (alias = node->same_body; alias; alias = alias->next)
+    DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping_const_or_pure;
+}
+
 #include "gt-cgraph.h"