OSDN Git Service

PR middle-end/42344
[pf3gnuchains/gcc-fork.git] / gcc / lto-symtab.c
index b2fb962..79eb3e4 100644 (file)
@@ -41,6 +41,9 @@ struct GTY(()) lto_symtab_entry_def
   tree id;
   /* The symbol table entry, a DECL.  */
   tree decl;
+  /* The cgraph node if decl is a function decl.  Filled in during the
+     merging process.  */
+  struct cgraph_node *node;
   /* LTO file-data and symbol resolution for this decl.  */
   struct lto_file_decl_data * GTY((skip (""))) file_data;
   enum ld_plugin_symbol_resolution resolution;
@@ -83,7 +86,7 @@ lto_symtab_entry_eq (const void *p1, const void *p2)
 }
 
 /* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
-   to be marked for GC.  */ 
+   to be marked for GC.  */
 
 static int
 lto_symtab_entry_marked_p (const void *p)
@@ -182,57 +185,6 @@ lto_symtab_get_resolution (tree decl)
 }
 
 
-static bool maybe_merge_incomplete_and_complete_type (tree, tree);
-
-/* Try to merge an incomplete type INCOMPLETE with a complete type
-   COMPLETE of same kinds.
-   Return true if they were merged, false otherwise.  */
-
-static bool
-merge_incomplete_and_complete_type (tree incomplete, tree complete)
-{
-  /* For merging array types do some extra sanity checking.  */
-  if (TREE_CODE (incomplete) == ARRAY_TYPE
-      && !maybe_merge_incomplete_and_complete_type (TREE_TYPE (incomplete),
-                                                   TREE_TYPE (complete))
-      && !gimple_types_compatible_p (TREE_TYPE (incomplete),
-                                    TREE_TYPE (complete)))
-    return false;
-
-  /* ??? Ideally we would do this by means of a common canonical type, but
-     that's difficult as we do not have links from the canonical type
-     back to all its children.  */
-  gimple_force_type_merge (incomplete, complete);
-
-  return true;
-}
-
-/* Try to merge a maybe complete / incomplete type pair TYPE1 and TYPE2.
-   Return true if they were merged, false otherwise.  */
-
-static bool
-maybe_merge_incomplete_and_complete_type (tree type1, tree type2)
-{
-  bool res = false;
-
-  if (TREE_CODE (type1) != TREE_CODE (type2))
-    return false;
-
-  if (!COMPLETE_TYPE_P (type1) && COMPLETE_TYPE_P (type2))
-    res = merge_incomplete_and_complete_type (type1, type2);
-  else if (COMPLETE_TYPE_P (type1) && !COMPLETE_TYPE_P (type2))
-    res = merge_incomplete_and_complete_type (type2, type1);
-
-  /* Recurse on pointer targets.  */
-  if (!res
-      && POINTER_TYPE_P (type1)
-      && POINTER_TYPE_P (type2))
-    res = maybe_merge_incomplete_and_complete_type (TREE_TYPE (type1),
-                                                   TREE_TYPE (type2));
-
-  return res;
-}
-
 /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
    all edges and removing the old node.  */
 
@@ -269,6 +221,25 @@ lto_cgraph_replace_node (struct cgraph_node *node,
       cgraph_remove_edge (e);
     }
 
+  if (node->same_body)
+    {
+      struct cgraph_node *alias;
+
+      for (alias = node->same_body; alias; alias = alias->next)
+       if (DECL_ASSEMBLER_NAME_SET_P (alias->decl))
+         {
+           lto_symtab_entry_t se
+             = lto_symtab_get (DECL_ASSEMBLER_NAME (alias->decl));
+
+           for (; se; se = se->next)
+             if (se->node == node)
+               {
+                 se->node = NULL;
+                 break;
+               }
+         }
+    }
+
   /* Finally remove the replaced node.  */
   cgraph_remove_node (node);
 }
@@ -283,25 +254,18 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
   tree prevailing_decl = prevailing->decl;
   tree decl = entry->decl;
   tree prevailing_type, type;
-  struct cgraph_node *node;
 
   /* Merge decl state in both directions, we may still end up using
      the new decl.  */
   TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
   TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl);
 
-  /* Replace a cgraph node of entry with the prevailing one.  */
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && (node = cgraph_get_node (decl)) != NULL)
-    lto_cgraph_replace_node (node, cgraph_get_node (prevailing_decl));
-
   /* The linker may ask us to combine two incompatible symbols.
      Detect this case and notify the caller of required diagnostics.  */
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
-      if (!gimple_types_compatible_p (TREE_TYPE (prevailing_decl),
-                                     TREE_TYPE (decl)))
+      if (TREE_TYPE (prevailing_decl) != TREE_TYPE (decl))
        /* If we don't have a merged type yet...sigh.  The linker
           wouldn't complain if the types were mismatched, so we
           probably shouldn't either.  Just use the type from
@@ -315,32 +279,56 @@ lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
 
   /* Now we exclusively deal with VAR_DECLs.  */
 
-  /* Handle external declarations with incomplete type or pointed-to
-     incomplete types by forcefully merging the types.
-     ???  In principle all types involved in the two decls should
-     be merged forcefully, for example without considering type or
-     field names.  */
-  prevailing_type = TREE_TYPE (prevailing_decl);
-  type = TREE_TYPE (decl);
-
-  /* If the types are structurally equivalent we can use the knowledge
-     that both bind to the same symbol to complete incomplete types
-     of external declarations or of pointer targets.
-     ???  We should apply this recursively to aggregate members here
-     and get rid of the completion in gimple_types_compatible_p.  */
-  if (DECL_EXTERNAL (prevailing_decl) || DECL_EXTERNAL (decl))
-    maybe_merge_incomplete_and_complete_type (prevailing_type, type);
-  else if (POINTER_TYPE_P (prevailing_type)
-          && POINTER_TYPE_P (type))
-    maybe_merge_incomplete_and_complete_type (TREE_TYPE (prevailing_type),
-                                             TREE_TYPE (type));
+  /* Sharing a global symbol is a strong hint that two types are
+     compatible.  We could use this information to complete
+     incomplete pointed-to types more aggressively here, ignoring
+     mismatches in both field and tag names.  It's difficult though
+     to guarantee that this does not have side-effects on merging
+     more compatible types from other translation units though.  */
 
   /* We can tolerate differences in type qualification, the
-     qualification of the prevailing definition will prevail.  */
+     qualification of the prevailing definition will prevail.
+     ???  In principle we might want to only warn for structurally
+     incompatible types here, but unless we have protective measures
+     for TBAA in place that would hide useful information.  */
   prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl));
   type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
-  if (!gimple_types_compatible_p (prevailing_type, type))
-    return false;
+
+  /* We have to register and fetch canonical types here as the global
+     fixup process didn't yet run.  */
+  prevailing_type = gimple_register_type (prevailing_type);
+  type = gimple_register_type (type);
+  if (prevailing_type != type)
+    {
+      if (COMPLETE_TYPE_P (type))
+       return false;
+
+      /* If type is incomplete then avoid warnings in the cases
+        that TBAA handles just fine.  */
+
+      if (TREE_CODE (prevailing_type) != TREE_CODE (type))
+       return false;
+
+      if (TREE_CODE (prevailing_type) == ARRAY_TYPE)
+       {
+         tree tem1 = TREE_TYPE (prevailing_type);
+         tree tem2 = TREE_TYPE (type);
+         while (TREE_CODE (tem1) == ARRAY_TYPE
+                && TREE_CODE (tem2) == ARRAY_TYPE)
+           {
+             tem1 = TREE_TYPE (tem1);
+             tem2 = TREE_TYPE (tem2);
+           }
+
+         if (TREE_CODE (tem1) != TREE_CODE (tem2))
+           return false;
+
+         if (gimple_register_type (tem1) != gimple_register_type (tem2))
+           return false;
+       }
+
+      /* Fallthru.  Compatible enough.  */
+    }
 
   /* ???  We might want to emit a warning here if type qualification
      differences were spotted.  Do not do this unconditionally though.  */
@@ -383,15 +371,15 @@ lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
 static bool
 lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
 {
-  struct cgraph_node *node;
-
-  if (!TREE_STATIC (e->decl))
+  /* The C++ frontend ends up neither setting TREE_STATIC nor
+     DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
+     So do not reject !TREE_STATIC here but only DECL_EXTERNAL.  */
+  if (DECL_EXTERNAL (e->decl))
     return false;
 
   /* For functions we need a non-discarded body.  */
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
-    return ((node = cgraph_get_node (e->decl))
-           && node->analyzed);
+    return (e->node && e->node->analyzed);
 
   /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
@@ -410,16 +398,25 @@ lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
 static void
 lto_symtab_resolve_symbols (void **slot)
 {
-  lto_symtab_entry_t e = (lto_symtab_entry_t) *slot;
+  lto_symtab_entry_t e;
   lto_symtab_entry_t prevailing = NULL;
 
-  /* If the chain is already resolved there is nothing to do.  */
+  /* Always set e->node so that edges are updated to reflect decl merging. */
+  for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
+    {
+      if (TREE_CODE (e->decl) == FUNCTION_DECL)
+       e->node = cgraph_get_node (e->decl);
+    }
+
+  e = (lto_symtab_entry_t) *slot;
+
+  /* If the chain is already resolved there is nothing else to do.  */
   if (e->resolution != LDPR_UNKNOWN)
     return;
 
   /* Find the single non-replaceable prevailing symbol and
      diagnose ODR violations.  */
-  for (; e; e = e->next)
+  for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
     {
       if (!lto_symtab_resolve_can_prevail_p (e))
        {
@@ -505,8 +502,7 @@ lto_symtab_merge_decls_2 (void **slot)
   /* Diagnose all mismatched re-declarations.  */
   for (i = 0; VEC_iterate (tree, mismatches, i, decl); ++i)
     {
-      if (!gimple_types_compatible_p (TREE_TYPE (prevailing->decl),
-                                     TREE_TYPE (decl)))
+      if (TREE_TYPE (prevailing->decl) != TREE_TYPE (decl))
        diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
                                   "type of %qD does not match original "
                                   "declaration", decl);
@@ -560,7 +556,7 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
       prevailing = (lto_symtab_entry_t) *slot;
       /* For functions choose one with a cgraph node.  */
       if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
-       while (!cgraph_get_node (prevailing->decl)
+       while (!prevailing->node
               && prevailing->next)
          prevailing = prevailing->next;
       /* We do not stream varpool nodes, so the first decl has to
@@ -629,7 +625,8 @@ lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
   lto_symtab_merge_decls_2 (slot);
 
   /* Drop all but the prevailing decl from the symtab.  */
-  prevailing->next = NULL;
+  if (TREE_CODE (prevailing->decl) != FUNCTION_DECL)
+    prevailing->next = NULL;
 
   return 1;
 }
@@ -643,6 +640,55 @@ lto_symtab_merge_decls (void)
   htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
 }
 
+/* Helper to process the decl chain for the symbol table entry *SLOT.  */
+
+static int
+lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+  lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
+
+  if (!prevailing->next)
+    return 1;
+
+  gcc_assert (TREE_CODE (prevailing->decl) == FUNCTION_DECL);
+
+  /* Replace the cgraph node of each entry with the prevailing one.  */
+  for (e = prevailing->next; e; e = e->next)
+    {
+      if (e->node != NULL)
+       {
+         if (e->node->decl != e->decl && e->node->same_body)
+           {
+             struct cgraph_node *alias;
+
+             for (alias = e->node->same_body; alias; alias = alias->next)
+               if (alias->decl == e->decl)
+                 break;
+             if (alias)
+               {
+                 cgraph_remove_same_body_alias (alias);
+                 continue;
+               }
+           }
+         lto_cgraph_replace_node (e->node, prevailing->node);
+       }
+    }
+
+  /* Drop all but the prevailing decl from the symtab.  */
+  prevailing->next = NULL;
+
+  return 1;
+}
+
+/* Merge cgraph nodes according to the symbol merging done by
+   lto_symtab_merge_decls.  */
+
+void
+lto_symtab_merge_cgraph_nodes (void)
+{
+  lto_symtab_maybe_init_hash_table ();
+  htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
+}
 
 /* Given the decl DECL, return the prevailing decl with the same name. */
 
@@ -670,53 +716,4 @@ lto_symtab_prevailing_decl (tree decl)
   return ret->decl;
 }
 
-/* Remove any storage used to store resolution of DECL.  */
-
-void
-lto_symtab_clear_resolution (tree decl)
-{
-  struct lto_symtab_entry_def temp;
-  lto_symtab_entry_t head;
-  void **slot;
-
-  if (!TREE_PUBLIC (decl))
-    return;
-
-  /* LTO FIXME: There should be no DECL_ABSTRACT in the middle end. */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT (decl))
-    return;
-
-  gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
-
-  lto_symtab_maybe_init_hash_table ();
-  temp.id = DECL_ASSEMBLER_NAME (decl);
-  slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
-  if (!*slot)
-    return;
-
-  head = (lto_symtab_entry_t) *slot;
-  if (head->decl == decl)
-    {
-      if (head->next)
-       {
-         *slot = head->next;
-         head->next = NULL;
-       }
-      else
-       htab_remove_elt (lto_symtab_identifiers, &temp);
-    }
-  else
-    {
-      lto_symtab_entry_t e;
-      while (head->next && head->next->decl != decl)
-       head = head->next;
-      if (head->next)
-       {
-         e = head->next;
-         head->next = e->next;
-         e->next = NULL;
-       }
-    }
-}
-
 #include "gt-lto-symtab.h"