tree.c (gimple_canonical_types_compatible_p): Do not compare function attributes.
[gcc.git] / gcc / lto / lto-symtab.c
index 06392a20a6364fef758cd272701453c1d8be0b64..995c7c98c75ecebc4c31ea6b7a4171c7caf0ef14 100644 (file)
@@ -22,12 +22,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "diagnostic-core.h"
-#include "tree.h"
-#include "predict.h"
-#include "vec.h"
-#include "hashtab.h"
 #include "hash-set.h"
 #include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
+#include "wide-int.h"
+#include "inchash.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "predict.h"
 #include "tm.h"
 #include "hard-reg-set.h"
 #include "input.h"
@@ -49,6 +56,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-prop.h"
 #include "ipa-inline.h"
 #include "builtins.h"
+#include "print-tree.h"
 
 /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
    all edges and removing the old node.  */
@@ -81,6 +89,8 @@ lto_cgraph_replace_node (struct cgraph_node *node,
       gcc_assert (!prevailing_node->global.inlined_to);
       prevailing_node->mark_address_taken ();
     }
+  if (node->definition && prevailing_node->definition)
+    prevailing_node->merged = true;
 
   /* Redirect all incoming edges.  */
   compatible_p
@@ -151,55 +161,92 @@ lto_varpool_replace_node (varpool_node *vnode,
 
   if (vnode->tls_model != prevailing_node->tls_model)
     {
-      error_at (DECL_SOURCE_LOCATION (vnode->decl),
-               "%qD is defined as %s", vnode->decl, tls_model_names [vnode->tls_model]);
-      inform (DECL_SOURCE_LOCATION (prevailing_node->decl),
-             "previously defined here as %s",
-             tls_model_names [prevailing_node->tls_model]);
+      bool error = false;
+
+      /* Non-TLS and TLS never mix together.  Also emulated model is not
+        compatible with anything else.  */
+      if (prevailing_node->tls_model == TLS_MODEL_NONE
+         || prevailing_node->tls_model == TLS_MODEL_EMULATED
+         || vnode->tls_model == TLS_MODEL_NONE
+         || vnode->tls_model == TLS_MODEL_EMULATED)
+       error = true;
+      /* Linked is silently supporting transitions
+        GD -> IE, GD -> LE, LD -> LE, IE -> LE, LD -> IE.
+        Do the same transitions and error out on others.  */
+      else if ((prevailing_node->tls_model == TLS_MODEL_REAL
+               || prevailing_node->tls_model == TLS_MODEL_LOCAL_DYNAMIC)
+              && (vnode->tls_model == TLS_MODEL_INITIAL_EXEC
+                  || vnode->tls_model == TLS_MODEL_LOCAL_EXEC))
+       prevailing_node->tls_model = vnode->tls_model;
+      else if ((vnode->tls_model == TLS_MODEL_REAL
+               || vnode->tls_model == TLS_MODEL_LOCAL_DYNAMIC)
+              && (prevailing_node->tls_model == TLS_MODEL_INITIAL_EXEC
+                  || prevailing_node->tls_model == TLS_MODEL_LOCAL_EXEC))
+       ;
+      else if (prevailing_node->tls_model == TLS_MODEL_INITIAL_EXEC
+              && vnode->tls_model == TLS_MODEL_LOCAL_EXEC)
+       prevailing_node->tls_model = vnode->tls_model;
+      else if (vnode->tls_model == TLS_MODEL_INITIAL_EXEC
+              && prevailing_node->tls_model == TLS_MODEL_LOCAL_EXEC)
+       ;
+      else
+       error = true;
+      if (error)
+       {
+         error_at (DECL_SOURCE_LOCATION (vnode->decl),
+                   "%qD is defined with tls model %s", vnode->decl, tls_model_names [vnode->tls_model]);
+         inform (DECL_SOURCE_LOCATION (prevailing_node->decl),
+                 "previously defined here as %s",
+                 tls_model_names [prevailing_node->tls_model]);
+       }
     }
   /* Finally remove the replaced node.  */
   vnode->remove ();
 }
 
-/* Merge two variable or function symbol table entries PREVAILING and ENTRY.
-   Return false if the symbols are not fully compatible and a diagnostic
-   should be emitted.  */
+/* Return non-zero if we want to output waring about T1 and T2.
+   Return value is a bitmask of reasons of violation:
+   Bit 0 indicates that types are not compatible of memory layout.
+   Bot 1 indicates that types are not compatible because of C++ ODR rule.  */
 
-static bool
-lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
+static int
+warn_type_compatibility_p (tree prevailing_type, tree type)
 {
-  tree prevailing_decl = prevailing->decl;
-  tree decl = entry->decl;
-  tree prevailing_type, type;
-
-  if (prevailing_decl == decl)
-    return true;
-
-  /* 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);
-
-  /* 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)
+  int lev = 0;
+  /* C++ provide a robust way to check for type compatibility via the ODR
+     rule.  */
+  if (odr_or_derived_type_p (prevailing_type) && odr_type_p (type)
+      && !odr_types_equivalent_p (prevailing_type, type))
+    lev = 2;
+
+  /* Function types needs special care, because types_compatible_p never
+     thinks prototype is compatible to non-prototype.  */
+  if ((TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+      && TREE_CODE (type) == TREE_CODE (prevailing_type))
     {
-      if (!types_compatible_p (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
-          whichever decl appears to be associated with the
-          definition.  If for some odd reason neither decl is, the
-          older one wins.  */
-       (void) 0;
-
-      return true;
+      lev |= warn_type_compatibility_p (TREE_TYPE (prevailing_type),
+                                       TREE_TYPE (type));
+      if (TREE_CODE (type) == METHOD_TYPE)
+       lev |= warn_type_compatibility_p (TYPE_METHOD_BASETYPE (prevailing_type),
+                                         TYPE_METHOD_BASETYPE (type));
+      if (prototype_p (prevailing_type) && prototype_p (type)
+         && TYPE_ARG_TYPES (prevailing_type) != TYPE_ARG_TYPES (type))
+       {
+         tree parm1, parm2;
+         for (parm1 = TYPE_ARG_TYPES (prevailing_type),
+              parm2 = TYPE_ARG_TYPES (type);
+              parm1 && parm2;
+              parm1 = TREE_CHAIN (prevailing_type),
+              parm2 = TREE_CHAIN (type))
+           lev |= warn_type_compatibility_p (TREE_VALUE (parm1),
+                                             TREE_VALUE (parm2));
+         if (parm1 || parm2)
+           lev = 3;
+       }
+      if (comp_type_attributes (prevailing_type, type) == 0)
+       lev = 3;
+      return lev;
     }
-
-  /* Now we exclusively deal with VAR_DECLs.  */
-
   /* 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
@@ -212,19 +259,22 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
      ???  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));
+  prevailing_type = TYPE_MAIN_VARIANT (prevailing_type);
+  type = TYPE_MAIN_VARIANT (type);
 
   if (!types_compatible_p (prevailing_type, type))
     {
-      if (COMPLETE_TYPE_P (type))
-       return false;
+      if (TREE_CODE (prevailing_type) == FUNCTION_TYPE
+         || TREE_CODE (type) == METHOD_TYPE)
+       return 1 | lev;
+      if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (prevailing_type))
+       return 1 | lev;
 
       /* 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;
+       return 1 | lev;
 
       if (TREE_CODE (prevailing_type) == ARRAY_TYPE)
        {
@@ -238,10 +288,10 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
            }
 
          if (TREE_CODE (tem1) != TREE_CODE (tem2))
-           return false;
+           return 1 | lev;
 
          if (!types_compatible_p (tem1, tem2))
-           return false;
+           return 1 | lev;
        }
 
       /* Fallthru.  Compatible enough.  */
@@ -250,6 +300,43 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
   /* ???  We might want to emit a warning here if type qualification
      differences were spotted.  Do not do this unconditionally though.  */
 
+  return lev;
+}
+
+/* Merge two variable or function symbol table entries PREVAILING and ENTRY.
+   Return false if the symbols are not fully compatible and a diagnostic
+   should be emitted.  */
+
+static bool
+lto_symtab_merge (symtab_node *prevailing, symtab_node *entry)
+{
+  tree prevailing_decl = prevailing->decl;
+  tree decl = entry->decl;
+
+  if (prevailing_decl == decl)
+    return true;
+
+  /* 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);
+
+  /* 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 (warn_type_compatibility_p (TREE_TYPE (prevailing_decl),
+                                    TREE_TYPE (decl)))
+       return false;
+
+      return true;
+    }
+
+  if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl),
+                                TREE_TYPE (decl)))
+    return false;
+
   /* There is no point in comparing too many details of the decls here.
      The type compatibility checks or the completing of types has properly
      dealt with most issues.  */
@@ -342,7 +429,7 @@ lto_symtab_resolve_symbols (symtab_node *first)
            && (e->resolution == LDPR_PREVAILING_DEF_IRONLY
                || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
                || e->resolution == LDPR_PREVAILING_DEF))
-         fatal_error ("multiple prevailing defs for %qE",
+         fatal_error (input_location, "multiple prevailing defs for %qE",
                       DECL_NAME (prevailing->decl));
       return prevailing;
     }
@@ -431,7 +518,8 @@ lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
     if (TREE_PUBLIC (e->decl))
       {
        if (!lto_symtab_merge (prevailing, e)
-           && !diagnosed_p)
+           && !diagnosed_p
+           && !DECL_ARTIFICIAL (e->decl))
          mismatches.safe_push (e->decl);
       }
   if (mismatches.is_empty ())
@@ -440,24 +528,39 @@ lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p)
   /* Diagnose all mismatched re-declarations.  */
   FOR_EACH_VEC_ELT (mismatches, i, decl)
     {
-      if (!types_compatible_p (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);
-
+      int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl),
+                                            TREE_TYPE (decl));
+      if (level)
+       {
+         bool diag = false;
+         if (level > 1)
+           diag = warning_at (DECL_SOURCE_LOCATION (decl),
+                              OPT_Wodr,
+                              "%qD violates the C++ One Definition Rule ",
+                              decl);
+         if (!diag && (level & 1))
+           diag = warning_at (DECL_SOURCE_LOCATION (decl),
+                              OPT_Wlto_type_mismatch,
+                              "type of %qD does not match original "
+                              "declaration", decl);
+         if (diag)
+           warn_types_mismatch (TREE_TYPE (prevailing->decl),
+                                TREE_TYPE (decl));
+         diagnosed_p |= diag;
+       }
       else if ((DECL_USER_ALIGN (prevailing->decl)
                && DECL_USER_ALIGN (decl))
               && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
        {
-         diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
+         diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl),
+                                    OPT_Wlto_type_mismatch,
                                     "alignment of %qD is bigger than "
                                     "original declaration", decl);
        }
     }
   if (diagnosed_p)
     inform (DECL_SOURCE_LOCATION (prevailing->decl),
-           "previously declared here");
+           "%qD was previously declared here", prevailing->decl);
 
   mismatches.release ();
 }