OSDN Git Service

Move flag_plugin_added out of invoke_plugin_callbacks.
[pf3gnuchains/gcc-fork.git] / gcc / cp / optimize.c
index 9210a80..bad63f5 100644 (file)
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "input.h"
 #include "integrate.h"
 #include "toplev.h"
-#include "varray.h"
 #include "params.h"
 #include "hashtab.h"
 #include "target.h"
@@ -104,6 +103,21 @@ clone_body (tree clone, tree fn, void *arg_map)
 
   stmts = DECL_SAVED_TREE (fn);
   walk_tree (&stmts, copy_tree_body_r, &id, NULL);
+
+  /* Also remap the initializer of any static variables so that they (in
+     particular, any label addresses) correspond to the base variant rather
+     than the abstract one.  */
+  if (DECL_NAME (clone) == base_dtor_identifier
+      || DECL_NAME (clone) == base_ctor_identifier)
+    {
+      tree decls = DECL_STRUCT_FUNCTION (fn)->local_decls;
+      for (; decls; decls = TREE_CHAIN (decls))
+       {
+         tree decl = TREE_VALUE (decls);
+         walk_tree (&DECL_INITIAL (decl), copy_tree_body_r, &id, NULL);
+       }
+    }
+
   append_to_statement_list_force (stmts, &DECL_SAVED_TREE (clone));
 }
 
@@ -195,6 +209,7 @@ maybe_clone_body (tree fn)
   bool first = true;
   bool in_charge_parm_used;
   int idx;
+  bool need_alias = false;
 
   /* We only clone constructors and destructors.  */
   if (!DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (fn)
@@ -223,6 +238,11 @@ maybe_clone_body (tree fn)
     else
       gcc_unreachable ();
 
+  /* Remember if we can't have multiple clones for some reason.  We need to
+     check this before we remap local static initializers in clone_body.  */
+  if (!tree_versionable_function_p (fn))
+    need_alias = true;
+
   /* We know that any clones immediately follow FN in the TYPE_METHODS
      list.  */
   push_to_top_level ();
@@ -292,12 +312,7 @@ maybe_clone_body (tree fn)
          && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
          && (!DECL_ONE_ONLY (fns[0])
              || (HAVE_COMDAT_GROUP
-                 && DECL_WEAK (fns[0])
-                 /* Don't optimize synthetized virtual dtors, because then
-                    the deleting and other dtors are emitted when needed
-                    and so it is not certain we would emit both
-                    deleting and complete/base dtors in the comdat group.  */
-                 && (fns[2] == NULL || !DECL_ARTIFICIAL (fn))))
+                 && DECL_WEAK (fns[0])))
          && cgraph_same_body_alias (clone, fns[0]))
        {
          alias = true;
@@ -319,6 +334,17 @@ maybe_clone_body (tree fn)
        /* No need to populate body.  */ ;
       else
        {
+         /* If we can't have multiple copies of FN (say, because there's a
+            static local initialized with the address of a label), we need
+            to use an alias for the complete variant.  */
+         if (idx == 1 && need_alias)
+           {
+             if (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_set)
+               sorry (DECL_STRUCT_FUNCTION (fn)->cannot_be_copied_reason, fn);
+             else
+               sorry ("making multiple clones of %qD", fn);
+           }
+
           /* Remap the parameters.  */
           decl_map = pointer_map_create ();
           for (parmno = 0,
@@ -396,9 +422,18 @@ maybe_clone_body (tree fn)
     {
       DECL_COMDAT_GROUP (fns[1]) = comdat_group;
       if (fns[2])
-       /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
-          virtual, it goes into the same comdat group as well.  */
-       DECL_COMDAT_GROUP (fns[2]) = comdat_group;
+       {
+         struct cgraph_node *base_dtor_node, *deleting_dtor_node;
+         /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
+            virtual, it goes into the same comdat group as well.  */
+         DECL_COMDAT_GROUP (fns[2]) = comdat_group;
+         base_dtor_node = cgraph_node (fns[0]);
+         deleting_dtor_node = cgraph_node (fns[2]);
+         gcc_assert (base_dtor_node->same_comdat_group == NULL);
+         gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
+         base_dtor_node->same_comdat_group = deleting_dtor_node;
+         deleting_dtor_node->same_comdat_group = base_dtor_node;
+       }
     }
 
   /* We don't need to process the original function any further.  */