diff gcc/ipa-devirt.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/ipa-devirt.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/ipa-devirt.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,6 +1,6 @@
 /* Basic IPA utilities for type inheritance graph construction and
    devirtualization.
-   Copyright (C) 2013-2018 Free Software Foundation, Inc.
+   Copyright (C) 2013-2020 Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -150,6 +150,7 @@
   {
     return TYPE_UID (p.first) ^ TYPE_UID (p.second);
   }
+  static const bool empty_zero_p = true;
   static bool
   is_empty (type_pair p)
   {
@@ -172,9 +173,16 @@
     }
 };
 
+/* HACK alert: this is used to communicate with ipa-inline-transform that
+   thunk is being expanded and there is no need to clear the polymorphic
+   call target cache.  */
+bool thunk_expansion;
+
 static bool odr_types_equivalent_p (tree, tree, bool, bool *,
 				    hash_set<type_pair> *,
 				    location_t, location_t);
+static void warn_odr (tree t1, tree t2, tree st1, tree st2,
+		      bool warn, bool *warned, const char *reason);
 
 static bool odr_violation_reported = false;
 
@@ -209,8 +217,10 @@
   bool all_derivations_known;
   /* Did we report ODR violation here?  */
   bool odr_violated;
-  /* Set when virtual table without RTTI previaled table with.  */
+  /* Set when virtual table without RTTI prevailed table with.  */
   bool rtti_broken;
+  /* Set when the canonical type is determined using the type name.  */
+  bool tbaa_enabled;
 };
 
 /* Return TRUE if all derived types of T are known and thus
@@ -242,7 +252,7 @@
 {
   return !flag_ltrans
 	 && symtab->state >= CONSTRUCTION
-	 /* We can not always use type_all_derivations_known_p.
+	 /* We cannot always use type_all_derivations_known_p.
 	    For function local types we must assume case where
 	    the function is COMDAT and shared in between units.
 
@@ -282,29 +292,6 @@
   static inline void remove (odr_type_d *);
 };
 
-/* Has used to unify ODR types based on their associated virtual table.
-   This hash is needed to keep -fno-lto-odr-type-merging to work and contains
-   only polymorphic types.  Types with mangled names are inserted to both.  */
-
-struct odr_vtable_hasher:odr_name_hasher
-{
-  static inline hashval_t hash (const odr_type_d *);
-  static inline bool equal (const odr_type_d *, const tree_node *);
-};
-
-/* Return type that was declared with T's name so that T is an
-   qualified variant of it.  */
-
-static inline tree
-main_odr_variant (const_tree t)
-{
-  if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)
-    return TREE_TYPE (TYPE_NAME (t));
-  /* Unnamed types and non-C++ produced types can be compared by variants.  */
-  else
-    return TYPE_MAIN_VARIANT (t);
-}
-
 static bool
 can_be_name_hashed_p (tree t)
 {
@@ -316,7 +303,7 @@
 static hashval_t
 hash_odr_name (const_tree t)
 {
-  gcc_checking_assert (main_odr_variant (t) == t);
+  gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
 
   /* If not in LTO, all main variants are unique, so we can do
      pointer hash.  */
@@ -340,51 +327,6 @@
   return hash_odr_name (odr_type->type);
 }
 
-static bool
-can_be_vtable_hashed_p (tree t)
-{
-  /* vtable hashing can distinguish only main variants.  */
-  if (TYPE_MAIN_VARIANT (t) != t)
-    return false;
-  /* Anonymous namespace types are always handled by name hash.  */
-  if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
-    return false;
-  return (TREE_CODE (t) == RECORD_TYPE
-	  && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
-}
-
-/* Hash type by assembler name of its vtable.  */
-
-static hashval_t
-hash_odr_vtable (const_tree t)
-{
-  tree v = BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
-  inchash::hash hstate;
-
-  gcc_checking_assert (in_lto_p);
-  gcc_checking_assert (!type_in_anonymous_namespace_p (t));
-  gcc_checking_assert (TREE_CODE (t) == RECORD_TYPE
-		       && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t)));
-  gcc_checking_assert (main_odr_variant (t) == t);
-
-  if (TREE_CODE (v) == POINTER_PLUS_EXPR)
-    {
-      add_expr (TREE_OPERAND (v, 1), hstate);
-      v = TREE_OPERAND (TREE_OPERAND (v, 0), 0);
-    }
-
-  hstate.add_hwi (IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (v)));
-  return hstate.end ();
-}
-
-/* Return the computed hashcode for ODR_TYPE.  */
-
-inline hashval_t
-odr_vtable_hasher::hash (const odr_type_d *odr_type)
-{
-  return hash_odr_vtable (odr_type->type);
-}
-
 /* For languages with One Definition Rule, work out if
    types are the same based on their name.
 
@@ -394,24 +336,15 @@
 
    Until we start streaming mangled type names, this function works
    only for polymorphic types.
-
-   When STRICT is true, we compare types by their names for purposes of
-   ODR violation warnings.  When strict is false, we consider variants
-   equivalent, because it is all that matters for devirtualization machinery.
 */
 
 bool
-types_same_for_odr (const_tree type1, const_tree type2, bool strict)
+types_same_for_odr (const_tree type1, const_tree type2)
 {
   gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2));
 
-  type1 = main_odr_variant (type1);
-  type2 = main_odr_variant (type2);
-  if (!strict)
-    {
-      type1 = TYPE_MAIN_VARIANT (type1);
-      type2 = TYPE_MAIN_VARIANT (type2);
-    }
+  type1 = TYPE_MAIN_VARIANT (type1);
+  type2 = TYPE_MAIN_VARIANT (type2);
 
   if (type1 == type2)
     return true;
@@ -419,66 +352,18 @@
   if (!in_lto_p)
     return false;
 
-  /* Check for anonymous namespaces. Those have !TREE_PUBLIC
-     on the corresponding TYPE_STUB_DECL.  */
+  /* Anonymous namespace types are never duplicated.  */
   if ((type_with_linkage_p (type1) && type_in_anonymous_namespace_p (type1))
       || (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
     return false;
 
-
-  /* ODR name of the type is set in DECL_ASSEMBLER_NAME of its TYPE_NAME.
-
-     Ideally we should never need types without ODR names here.  It can however
-     happen in two cases:
-
-       1) for builtin types that are not streamed but rebuilt in lto/lto-lang.c
-          Here testing for equivalence is safe, since their MAIN_VARIANTs are
-          unique.
-       2) for units streamed with -fno-lto-odr-type-merging.  Here we can't
-	  establish precise ODR equivalency, but for correctness we care only
-	  about equivalency on complete polymorphic types.  For these we can
-	  compare assembler names of their virtual tables.  */
-  if ((!TYPE_NAME (type1) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type1)))
-      || (!TYPE_NAME (type2) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type2))))
-    {
-      /* See if types are obviously different (i.e. different codes
-	 or polymorphic wrt non-polymorphic).  This is not strictly correct
-	 for ODR violating programs, but we can't do better without streaming
-	 ODR names.  */
-      if (TREE_CODE (type1) != TREE_CODE (type2))
-	return false;
-      if (TREE_CODE (type1) == RECORD_TYPE
-	  && (TYPE_BINFO (type1) == NULL_TREE)
-	      != (TYPE_BINFO (type2) == NULL_TREE))
-	return false;
-      if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1)
-	  && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE)
-	     != (BINFO_VTABLE (TYPE_BINFO (type2)) == NULL_TREE))
-	return false;
-
-      /* At the moment we have no way to establish ODR equivalence at LTO
-	 other than comparing virtual table pointers of polymorphic types.
-	 Eventually we should start saving mangled names in TYPE_NAME.
-	 Then this condition will become non-trivial.  */
-
-      if (TREE_CODE (type1) == RECORD_TYPE
-	  && TYPE_BINFO (type1) && TYPE_BINFO (type2)
-	  && BINFO_VTABLE (TYPE_BINFO (type1))
-	  && BINFO_VTABLE (TYPE_BINFO (type2)))
-	{
-	  tree v1 = BINFO_VTABLE (TYPE_BINFO (type1));
-	  tree v2 = BINFO_VTABLE (TYPE_BINFO (type2));
-	  gcc_assert (TREE_CODE (v1) == POINTER_PLUS_EXPR
-		      && TREE_CODE (v2) == POINTER_PLUS_EXPR);
-	  return (operand_equal_p (TREE_OPERAND (v1, 1),
-				   TREE_OPERAND (v2, 1), 0)
-		  && DECL_ASSEMBLER_NAME
-			 (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
-		     == DECL_ASSEMBLER_NAME
-			 (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
-	}
-      gcc_unreachable ();
-    }
+  /* If both type has mangled defined check if they are same.
+     Watch for anonymous types which are all mangled as "<anon">.  */
+  if (!type_with_linkage_p (type1) || !type_with_linkage_p (type2))
+    return false;
+  if (type_in_anonymous_namespace_p (type1)
+      || type_in_anonymous_namespace_p (type2))
+    return false;
   return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1))
 	  == DECL_ASSEMBLER_NAME (TYPE_NAME (type2)));
 }
@@ -486,22 +371,15 @@
 /* Return true if we can decide on ODR equivalency.
 
    In non-LTO it is always decide, in LTO however it depends in the type has
-   ODR info attached.
-
-   When STRICT is false, compare main variants.  */
+   ODR info attached. */
 
 bool
-types_odr_comparable (tree t1, tree t2, bool strict)
+types_odr_comparable (tree t1, tree t2)
 {
   return (!in_lto_p
-	  || (strict ? (main_odr_variant (t1) == main_odr_variant (t2)
-			&& main_odr_variant (t1))
-	      : TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
-	  || (odr_type_p (t1) && odr_type_p (t2))
-	  || (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE
-	      && TYPE_BINFO (t1) && TYPE_BINFO (t2)
-	      && polymorphic_type_binfo_p (TYPE_BINFO (t1))
-	      && polymorphic_type_binfo_p (TYPE_BINFO (t2))));
+	  || TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
+	  || (odr_type_p (TYPE_MAIN_VARIANT (t1))
+	      && odr_type_p (TYPE_MAIN_VARIANT (t2))));
 }
 
 /* Return true if T1 and T2 are ODR equivalent.  If ODR equivalency is not
@@ -542,7 +420,7 @@
 {
   do
     {
-      if (odr_type_p (t))
+      if (odr_type_p (TYPE_MAIN_VARIANT (t)))
 	return true;
       /* Function type is a tricky one. Basically we can consider it
 	 ODR derived if return type or any of the parameters is.
@@ -557,7 +435,7 @@
 	     if (TREE_TYPE (t) && odr_or_derived_type_p (TREE_TYPE (t)))
 	       return true;
 	     for (t = TYPE_ARG_TYPES (t); t; t = TREE_CHAIN (t))
-	       if (odr_or_derived_type_p (TREE_VALUE (t)))
+	       if (odr_or_derived_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (t))))
 		 return true;
 	     return false;
 	   }
@@ -577,14 +455,13 @@
 {
   tree t1 = o1->type;
 
-  gcc_checking_assert (main_odr_variant (t2) == t2);
-  gcc_checking_assert (main_odr_variant (t1) == t1);
+  gcc_checking_assert (TYPE_MAIN_VARIANT (t2) == t2);
+  gcc_checking_assert (TYPE_MAIN_VARIANT (t1) == t1);
   if (t1 == t2)
     return true;
   if (!in_lto_p)
     return false;
-  /* Check for anonymous namespaces. Those have !TREE_PUBLIC
-     on the corresponding TYPE_STUB_DECL.  */
+  /* Check for anonymous namespaces.  */
   if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
       || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
     return false;
@@ -594,31 +471,6 @@
 	  == DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
 }
 
-/* Compare types T1 and T2 and return true if they are
-   equivalent.  */
-
-inline bool
-odr_vtable_hasher::equal (const odr_type_d *o1, const tree_node *t2)
-{
-  tree t1 = o1->type;
-
-  gcc_checking_assert (main_odr_variant (t2) == t2);
-  gcc_checking_assert (main_odr_variant (t1) == t1);
-  gcc_checking_assert (in_lto_p);
-  t1 = TYPE_MAIN_VARIANT (t1);
-  t2 = TYPE_MAIN_VARIANT (t2);
-  if (t1 == t2)
-    return true;
-  tree v1 = BINFO_VTABLE (TYPE_BINFO (t1));
-  tree v2 = BINFO_VTABLE (TYPE_BINFO (t2));
-  return (operand_equal_p (TREE_OPERAND (v1, 1),
-			   TREE_OPERAND (v2, 1), 0)
-	  && DECL_ASSEMBLER_NAME
-		 (TREE_OPERAND (TREE_OPERAND (v1, 0), 0))
-	     == DECL_ASSEMBLER_NAME
-		 (TREE_OPERAND (TREE_OPERAND (v2, 0), 0)));
-}
-
 /* Free ODR type V.  */
 
 inline void
@@ -635,8 +487,6 @@
 
 typedef hash_table<odr_name_hasher> odr_hash_type;
 static odr_hash_type *odr_hash;
-typedef hash_table<odr_vtable_hasher> odr_vtable_hash_type;
-static odr_vtable_hash_type *odr_vtable_hash;
 
 /* ODR types are also stored into ODR_TYPE vector to allow consistent
    walking.  Bases appear before derived types.  Vector is garbage collected
@@ -656,6 +506,26 @@
       gcc_assert (!TYPE_BINFO (type));
 }
 
+/* Return true if type variants match.
+   This assumes that we already verified that T1 and T2 are variants of the
+   same type.  */
+
+static bool
+type_variants_equivalent_p (tree t1, tree t2)
+{
+  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+    return false;
+
+  if (comp_type_attributes (t1, t2) != 1)
+    return false;
+
+  if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)
+      && TYPE_ALIGN (t1) != TYPE_ALIGN (t2))
+    return false;
+
+  return true;
+}
+
 /* Compare T1 and T2 based on name or structure.  */
 
 static bool
@@ -667,26 +537,32 @@
   /* This can happen in incomplete types that should be handled earlier.  */
   gcc_assert (t1 && t2);
 
-  t1 = main_odr_variant (t1);
-  t2 = main_odr_variant (t2);
   if (t1 == t2)
     return true;
 
   /* Anonymous namespace types must match exactly.  */
-  if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
-      || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
+  if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
+       && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
+      || (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
+	  && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
     return false;
 
   /* For ODR types be sure to compare their names.
      To support -Wno-odr-type-merging we allow one type to be non-ODR
      and other ODR even though it is a violation.  */
-  if (types_odr_comparable (t1, t2, true))
+  if (types_odr_comparable (t1, t2))
     {
-      if (!types_same_for_odr (t1, t2, true))
+      if (t1 != t2
+	  && odr_type_p (TYPE_MAIN_VARIANT (t1))
+	  && get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated)
+	return false;
+      if (!types_same_for_odr (t1, t2))
         return false;
+      if (!type_variants_equivalent_p (t1, t2))
+	return false;
       /* Limit recursion: If subtypes are ODR types and we know
 	 that they are same, be happy.  */
-      if (!odr_type_p (t1) || !get_odr_type (t1, true)->odr_violated)
+      if (odr_type_p (TYPE_MAIN_VARIANT (t1)))
         return true;
     }
 
@@ -698,15 +574,20 @@
       && (TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
     return false;
 
-  type_pair pair={t1,t2};
-  if (TYPE_UID (t1) > TYPE_UID (t2))
+  type_pair pair={TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2)};
+  if (TYPE_UID (TYPE_MAIN_VARIANT (t1)) > TYPE_UID (TYPE_MAIN_VARIANT (t2)))
     {
-      pair.first = t2;
-      pair.second = t1;
+      pair.first = TYPE_MAIN_VARIANT (t2);
+      pair.second = TYPE_MAIN_VARIANT (t1);
     }
   if (visited->add (pair))
     return true;
-  return odr_types_equivalent_p (t1, t2, false, NULL, visited, loc1, loc2);
+  if (!odr_types_equivalent_p (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2),
+			      false, NULL, visited, loc1, loc2))
+    return false;
+  if (!type_variants_equivalent_p (t1, t2))
+    return false;
+  return true;
 }
 
 /* Return true if DECL1 and DECL2 are identical methods.  Consider
@@ -782,7 +663,7 @@
       end2 = !vtable->iterate_reference (n2, ref2);
 
       /* !DECL_VIRTUAL_P means RTTI entry;
-	 We warn when RTTI is lost because non-RTTI previals; we silently
+	 We warn when RTTI is lost because non-RTTI prevails; we silently
 	 accept the other case.  */
       while (!end2
 	     && (end1
@@ -836,17 +717,16 @@
 	    {
 	      class_type->odr_violated = true;
 	      auto_diagnostic_group d;
-	      if (warning_at (DECL_SOURCE_LOCATION
-				(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
-			      OPT_Wodr,
+	      tree ctx = TYPE_NAME (DECL_CONTEXT (vtable->decl));
+	      if (warning_at (DECL_SOURCE_LOCATION (ctx), OPT_Wodr,
 			      "virtual table of type %qD violates "
-			      "one definition rule  ",
+			      "one definition rule",
 			      DECL_CONTEXT (vtable->decl)))
 		{
-		  inform (DECL_SOURCE_LOCATION
-			    (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
-			  "the conflicting type defined in another translation "
-			  "unit has virtual table of different size");
+		  ctx = TYPE_NAME (DECL_CONTEXT (prevailing->decl));
+		  inform (DECL_SOURCE_LOCATION (ctx),
+			  "the conflicting type defined in another translation"
+			  " unit has virtual table of different size");
 		}
 	    }
 	  return;
@@ -869,7 +749,7 @@
 				(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
 			      OPT_Wodr,
 			      "virtual table of type %qD violates "
-			      "one definition rule  ",
+			      "one definition rule",
 			      DECL_CONTEXT (vtable->decl)))
 		{
 		  inform (DECL_SOURCE_LOCATION
@@ -895,7 +775,7 @@
 
       class_type->odr_violated = true;
 
-      /* Complain about size mismatch.  Either we have too many virutal
+      /* Complain about size mismatch.  Either we have too many virtual
  	 functions or too many virtual table pointers.  */
       if (end1 || end2)
 	{
@@ -936,13 +816,13 @@
 	  return;
 	}
 
-      /* And in the last case we have either mistmatch in between two virtual
+      /* And in the last case we have either mismatch in between two virtual
 	 methods or two virtual table pointers.  */
       auto_diagnostic_group d;
       if (warning_at (DECL_SOURCE_LOCATION
 			(TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
 		      "virtual table of type %qD violates "
-		      "one definition rule  ",
+		      "one definition rule",
 		      DECL_CONTEXT (vtable->decl)))
 	{
 	  if (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)
@@ -978,27 +858,39 @@
    If WARN is false, do nothing. Set WARNED if warning was indeed
    output.  */
 
-void
+static void
 warn_odr (tree t1, tree t2, tree st1, tree st2,
 	  bool warn, bool *warned, const char *reason)
 {
-  tree decl2 = TYPE_NAME (t2);
+  tree decl2 = TYPE_NAME (TYPE_MAIN_VARIANT (t2));
   if (warned)
     *warned = false;
 
-  if (!warn || !TYPE_NAME(t1))
+  if (!warn || !TYPE_NAME(TYPE_MAIN_VARIANT (t1)))
     return;
 
-  /* ODR warnings are output druing LTO streaming; we must apply location
+  /* ODR warnings are output during LTO streaming; we must apply location
      cache for potential warnings to be output correctly.  */
   if (lto_location_cache::current_cache)
     lto_location_cache::current_cache->apply_location_cache ();
 
   auto_diagnostic_group d;
-  if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr,
-		   "type %qT violates the C++ One Definition Rule",
-		   t1))
-    return;
+  if (t1 != TYPE_MAIN_VARIANT (t1)
+      && TYPE_NAME (t1) != TYPE_NAME (TYPE_MAIN_VARIANT (t1)))
+    {
+      if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (TYPE_MAIN_VARIANT (t1))),
+		       OPT_Wodr, "type %qT (typedef of %qT) violates the "
+		       "C++ One Definition Rule",
+		       t1, TYPE_MAIN_VARIANT (t1)))
+	return;
+    }
+  else
+    {
+      if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (TYPE_MAIN_VARIANT (t1))),
+		       OPT_Wodr, "type %qT violates the C++ One Definition Rule",
+		       t1))
+	return;
+    }
   if (!st1 && !st2)
     ;
   /* For FIELD_DECL support also case where one of fields is
@@ -1036,7 +928,7 @@
     *warned = true;
 }
 
-/* Return ture if T1 and T2 are incompatible and we want to recusively
+/* Return true if T1 and T2 are incompatible and we want to recursively
    dive into them from warn_type_mismatch to give sensible answer.  */
 
 static bool
@@ -1057,7 +949,7 @@
    This is hard to do in general.  We basically handle the common cases.
 
    If LOC1 and LOC2 are meaningful locations, use it in the case the types
-   themselves do no thave one.*/
+   themselves do not have one.  */
 
 void
 warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
@@ -1102,28 +994,39 @@
 
   /* It is a quite common bug to reference anonymous namespace type in
      non-anonymous namespace class.  */
-  if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
-      || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
+  tree mt1 = TYPE_MAIN_VARIANT (t1);
+  tree mt2 = TYPE_MAIN_VARIANT (t2);
+  if ((type_with_linkage_p (mt1)
+       && type_in_anonymous_namespace_p (mt1))
+      || (type_with_linkage_p (mt2)
+	  && type_in_anonymous_namespace_p (mt2)))
     {
-      if (type_with_linkage_p (t1) && !type_in_anonymous_namespace_p (t1))
+      if (!type_with_linkage_p (mt1)
+	  || !type_in_anonymous_namespace_p (mt1))
 	{
 	  std::swap (t1, t2);
+	  std::swap (mt1, mt2);
 	  std::swap (loc_t1, loc_t2);
 	}
-      gcc_assert (TYPE_NAME (t1) && TYPE_NAME (t2)
-		  && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
-		  && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL);
-      /* Most of the time, the type names will match, do not be unnecesarily
+      gcc_assert (TYPE_NAME (mt1)
+		  && TREE_CODE (TYPE_NAME (mt1)) == TYPE_DECL);
+      tree n1 = TYPE_NAME (mt1);
+      tree n2 = TYPE_NAME (mt2) ? TYPE_NAME (mt2) : NULL;
+
+      if (TREE_CODE (n1) == TYPE_DECL)
+	n1 = DECL_NAME (n1);
+      if (n2 && TREE_CODE (n2) == TYPE_DECL)
+	n2 = DECL_NAME (n2);
+      /* Most of the time, the type names will match, do not be unnecessarily
          verbose.  */
-      if (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t1)))
-	  != IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t2))))
+      if (n1 != n2)
         inform (loc_t1,
-	        "type %qT defined in anonymous namespace can not match "
+	        "type %qT defined in anonymous namespace cannot match "
 	        "type %qT across the translation unit boundary",
 	        t1, t2);
       else
         inform (loc_t1,
-	        "type %qT defined in anonymous namespace can not match "
+	        "type %qT defined in anonymous namespace cannot match "
 	        "across the translation unit boundary",
 	        t1);
       if (loc_t2_useful)
@@ -1134,20 +1037,13 @@
   /* If types have mangled ODR names and they are different, it is most
      informative to output those.
      This also covers types defined in different namespaces.  */
-  if (TYPE_NAME (t1) && TYPE_NAME (t2)
-      && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
-      && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
-      && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t1))
-      && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t2))
-      && DECL_ASSEMBLER_NAME (TYPE_NAME (t1))
-	 != DECL_ASSEMBLER_NAME (TYPE_NAME (t2)))
+  const char *odr1 = get_odr_name_for_type (mt1);
+  const char *odr2 = get_odr_name_for_type (mt2);
+  if (odr1 != NULL && odr2 != NULL && odr1 != odr2)
     {
-      char *name1 = xstrdup (cplus_demangle
-	 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))),
-	  DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES));
-      char *name2 = cplus_demangle
-	 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t2))),
-	  DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES);
+      const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
+      char *name1 = xstrdup (cplus_demangle (odr1, opts));
+      char *name2 = cplus_demangle (odr2, opts);
       if (name1 && name2 && strcmp (name1, name2))
 	{
 	  inform (loc_t1,
@@ -1235,8 +1131,13 @@
       return;
     }
 
-  if (types_odr_comparable (t1, t2, true)
-      && types_same_for_odr (t1, t2, true))
+  if (types_odr_comparable (t1, t2)
+      /* We make assign integers mangled names to be able to handle
+	 signed/unsigned chars.  Accepting them here would however lead to
+	 confusing message like
+	 "type ‘const int’ itself violates the C++ One Definition Rule"  */
+      && TREE_CODE (t1) != INTEGER_TYPE
+      && types_same_for_odr (t1, t2))
     inform (loc_t1,
 	    "type %qT itself violates the C++ One Definition Rule", t1);
   /* Prevent pointless warnings like "struct aa" should match "struct aa".  */
@@ -1250,6 +1151,24 @@
     inform (loc_t2, "the incompatible type is defined here");
 }
 
+/* Return true if T should be ignored in TYPE_FIELDS for ODR comparison.  */
+
+static bool
+skip_in_fields_list_p (tree t)
+{
+  if (TREE_CODE (t) != FIELD_DECL)
+    return true;
+  /* C++ FE introduces zero sized fields depending on -std setting, see
+     PR89358.  */
+  if (DECL_SIZE (t)
+      && integer_zerop (DECL_SIZE (t))
+      && DECL_ARTIFICIAL (t)
+      && DECL_IGNORED_P (t)
+      && !DECL_NAME (t))
+    return true;
+  return false;
+}
+
 /* Compare T1 and T2, report ODR violations if WARN is true and set
    WARNED to true if anything is reported.  Return true if types match.
    If true is returned, the types are also compatible in the sense of
@@ -1265,8 +1184,6 @@
   /* Check first for the obvious case of pointer identity.  */
   if (t1 == t2)
     return true;
-  gcc_assert (!type_with_linkage_p (t1) || !type_in_anonymous_namespace_p (t1));
-  gcc_assert (!type_with_linkage_p (t2) || !type_in_anonymous_namespace_p (t2));
 
   /* Can't be the same type if the types don't have the same code.  */
   if (TREE_CODE (t1) != TREE_CODE (t2))
@@ -1276,32 +1193,18 @@
       return false;
     }
 
-  if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
+  if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
+       && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
+      || (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
+	  && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
     {
-      warn_odr (t1, t2, NULL, NULL, warn, warned,
-	        G_("a type with different qualifiers is defined in another "
-		   "translation unit"));
-      return false;
-    }
-
-  if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
-      || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
-    {
-      /* We can not trip this when comparing ODR types, only when trying to
+      /* We cannot trip this when comparing ODR types, only when trying to
 	 match different ODR derivations from different declarations.
 	 So WARN should be always false.  */
       gcc_assert (!warn);
       return false;
     }
 
-  if (comp_type_attributes (t1, t2) != 1)
-    {
-      warn_odr (t1, t2, NULL, NULL, warn, warned,
-	        G_("a type with different attributes "
-		   "is defined in another translation unit"));
-      return false;
-    }
-
   if (TREE_CODE (t1) == ENUMERAL_TYPE
       && TYPE_VALUES (t1) && TYPE_VALUES (t2))
     {
@@ -1316,9 +1219,7 @@
 			   " is defined in another translation unit"));
 	      return false;
 	    }
-	  if (TREE_VALUE (v1) != TREE_VALUE (v2)
-	      && !operand_equal_p (DECL_INITIAL (TREE_VALUE (v1)),
-				   DECL_INITIAL (TREE_VALUE (v2)), 0))
+	  if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2), 0))
 	    {
 	      warn_odr (t1, t2, NULL, NULL, warn, warned,
 			G_("an enum with different values is defined"
@@ -1436,7 +1337,7 @@
 	/* For an incomplete external array, the type domain can be
 	   NULL_TREE.  Check this condition also.  */
 	if (i1 == NULL_TREE || i2 == NULL_TREE)
-	  return true;
+          return type_variants_equivalent_p (t1, t2);
 
 	tree min1 = TYPE_MIN_VALUE (i1);
 	tree min2 = TYPE_MIN_VALUE (i2);
@@ -1472,7 +1373,7 @@
 
       if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)
 	  || !prototype_p (t1) || !prototype_p (t2))
-	return true;
+        return type_variants_equivalent_p (t1, t2);
       else
 	{
 	  tree parms1, parms2;
@@ -1482,8 +1383,8 @@
 	       parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
 	    {
 	      if (!odr_subtypes_equivalent_p
-		     (TREE_VALUE (parms1), TREE_VALUE (parms2), visited,
-		      loc1, loc2))
+		     (TREE_VALUE (parms1), TREE_VALUE (parms2),
+		      visited, loc1, loc2))
 		{
 		  warn_odr (t1, t2, NULL, NULL, warn, warned,
 			    G_("has different parameters in another "
@@ -1503,7 +1404,7 @@
 	      return false;
 	    }
 
-	  return true;
+          return type_variants_equivalent_p (t1, t2);
 	}
 
     case RECORD_TYPE:
@@ -1534,9 +1435,9 @@
 		 f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
 	      {
 		/* Skip non-fields.  */
-		while (f1 && TREE_CODE (f1) != FIELD_DECL)
+		while (f1 && skip_in_fields_list_p (f1))
 		  f1 = TREE_CHAIN (f1);
-		while (f2 && TREE_CODE (f2) != FIELD_DECL)
+		while (f2 && skip_in_fields_list_p (f2))
 		  f2 = TREE_CHAIN (f2);
 		if (!f1 || !f2)
 		  break;
@@ -1563,8 +1464,8 @@
 		    return false;
 		  }
 		if (!odr_subtypes_equivalent_p (TREE_TYPE (f1),
-						TREE_TYPE (f2), visited,
-						loc1, loc2))
+						TREE_TYPE (f2),
+						visited, loc1, loc2))
 		  {
 		    /* Do not warn about artificial fields and just go into
  		       generic field mismatch warning.  */
@@ -1592,7 +1493,8 @@
 		if (DECL_BIT_FIELD (f1) != DECL_BIT_FIELD (f2))
 		  {
 		    warn_odr (t1, t2, f1, f2, warn, warned,
-			      G_("one field is bitfield while other is not"));
+			      G_("one field is a bitfield while the other "
+				 "is not"));
 		    return false;
 		  }
 		else
@@ -1641,18 +1543,32 @@
 		   "is defined in another translation unit"));
       return false;
     }
-  if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)
-      && TYPE_ALIGN (t1) != TYPE_ALIGN (t2))
+
+  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)
+      && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
     {
       warn_odr (t1, t2, NULL, NULL, warn, warned,
-		G_("a type with different alignment "
-		   "is defined in another translation unit"));
+		G_("one type needs to be constructed while other not"));
+      gcc_checking_assert (RECORD_OR_UNION_TYPE_P (t1));
       return false;
     }
+  /* There is no really good user facing warning for this.
+     Either the original reason for modes being different is lost during
+     streaming or we should catch earlier warnings.  We however must detect
+     the mismatch to avoid type verifier from cmplaining on mismatched
+     types between type and canonical type. See PR91576.  */
+  if (TYPE_MODE (t1) != TYPE_MODE (t2)
+      && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
+    {
+      warn_odr (t1, t2, NULL, NULL, warn, warned,
+		G_("memory layout mismatch"));
+      return false;
+    }
+
   gcc_assert (!TYPE_SIZE_UNIT (t1) || !TYPE_SIZE_UNIT (t2)
 	      || operand_equal_p (TYPE_SIZE_UNIT (t1),
 				  TYPE_SIZE_UNIT (t2), 0));
-  return true;
+  return type_variants_equivalent_p (t1, t2);
 }
 
 /* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule.  */
@@ -1701,7 +1617,8 @@
   else if (!COMPLETE_TYPE_P (val->type) && COMPLETE_TYPE_P (type))
     {
       prevail = true;
-      build_bases = TYPE_BINFO (type);
+      if (TREE_CODE (type) == RECORD_TYPE)
+        build_bases = TYPE_BINFO (type);
     }
   else if (COMPLETE_TYPE_P (val->type) && !COMPLETE_TYPE_P (type))
     ;
@@ -1723,12 +1640,11 @@
 
   val->types_set->add (type);
 
-  /* If we now have a mangled name, be sure to record it to val->type
-     so ODR hash can work.  */
-
-  if (can_be_name_hashed_p (type) && !can_be_name_hashed_p (val->type))
-    SET_DECL_ASSEMBLER_NAME (TYPE_NAME (val->type),
-			     DECL_ASSEMBLER_NAME (TYPE_NAME (type)));
+  if (!odr_hash)
+    return false;
+
+  gcc_checking_assert (can_be_name_hashed_p (type)
+		       && can_be_name_hashed_p (val->type));
 
   bool merge = true;
   bool base_mismatch = false;
@@ -1866,7 +1782,12 @@
      before we can pass them to odr_types_equivalent_p (PR lto/83121).  */
   if (lto_location_cache::current_cache)
     lto_location_cache::current_cache->apply_location_cache ();
-  if (!odr_types_equivalent_p (val->type, type,
+  /* As a special case we stream mangles names of integer types so we can see
+     if they are believed to be same even though they have different
+     representation.  Avoid bogus warning on mismatches in these.  */
+  if (TREE_CODE (type) != INTEGER_TYPE
+      && TREE_CODE (val->type) != INTEGER_TYPE
+      && !odr_types_equivalent_p (val->type, type,
 			       !flag_ltrans && !val->odr_violated && !warned,
 			       &warned, &visited,
 			       DECL_SOURCE_LOCATION (TYPE_NAME (val->type)),
@@ -1971,6 +1892,30 @@
   return build_bases;
 }
 
+/* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
+
+tree
+obj_type_ref_class (const_tree ref)
+{
+  gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
+  ref = TREE_TYPE (ref);
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  ref = TREE_TYPE (ref);
+  /* We look for type THIS points to.  ObjC also builds
+     OBJ_TYPE_REF with non-method calls, Their first parameter
+     ID however also corresponds to class type. */
+  gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
+		       || TREE_CODE (ref) == FUNCTION_TYPE);
+  ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  tree ret = TREE_TYPE (ref);
+  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))
+    ret = TYPE_CANONICAL (ret);
+  else
+    ret = get_odr_type (ret)->type;
+  return ret;
+}
+
 /* Get ODR type hash entry for TYPE.  If INSERT is true, create
    possibly new entry.  */
 
@@ -1978,76 +1923,33 @@
 get_odr_type (tree type, bool insert)
 {
   odr_type_d **slot = NULL;
-  odr_type_d **vtable_slot = NULL;
   odr_type val = NULL;
   hashval_t hash;
   bool build_bases = false;
   bool insert_to_odr_array = false;
   int base_id = -1;
 
-  type = main_odr_variant (type);
-
-  gcc_checking_assert (can_be_name_hashed_p (type)
-		       || can_be_vtable_hashed_p (type));
-
-  /* Lookup entry, first try name hash, fallback to vtable hash.  */
-  if (can_be_name_hashed_p (type))
-    {
-      hash = hash_odr_name (type);
-      slot = odr_hash->find_slot_with_hash (type, hash,
-					    insert ? INSERT : NO_INSERT);
-    }
-  if ((!slot || !*slot) && in_lto_p && can_be_vtable_hashed_p (type))
-    {
-      hash = hash_odr_vtable (type);
-      vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
-					           insert ? INSERT : NO_INSERT);
-    }
-
-  if (!slot && !vtable_slot)
+  type = TYPE_MAIN_VARIANT (type);
+  if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
+    type = TYPE_CANONICAL (type);
+
+  gcc_checking_assert (can_be_name_hashed_p (type));
+
+  hash = hash_odr_name (type);
+  slot = odr_hash->find_slot_with_hash (type, hash,
+					insert ? INSERT : NO_INSERT);
+
+  if (!slot)
     return NULL;
 
   /* See if we already have entry for type.  */
-  if ((slot && *slot) || (vtable_slot && *vtable_slot))
+  if (*slot)
     {
-      if (slot && *slot)
-	{
-	  val = *slot;
-	  if (flag_checking
-	      && in_lto_p && can_be_vtable_hashed_p (type))
-	    {
-	      hash = hash_odr_vtable (type);
-	      vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash,
-						                  NO_INSERT);
-	      gcc_assert (!vtable_slot || *vtable_slot == *slot);
-	      vtable_slot = NULL;
-	    }
-	}
-      else if (*vtable_slot)
-	val = *vtable_slot;
-
-      if (val->type != type
+      val = *slot;
+
+      if (val->type != type && insert
 	  && (!val->types_set || !val->types_set->add (type)))
-	{
-	  gcc_assert (insert);
-	  /* We have type duplicate, but it may introduce vtable name or
- 	     mangled name; be sure to keep hashes in sync.  */
-	  if (in_lto_p && can_be_vtable_hashed_p (type)
-	      && (!vtable_slot || !*vtable_slot))
-	    {
-	      if (!vtable_slot)
-		{
-		  hash = hash_odr_vtable (type);
-		  vtable_slot = odr_vtable_hash->find_slot_with_hash
-			     (type, hash, INSERT);
-		  gcc_checking_assert (!*vtable_slot || *vtable_slot == val);
-		}
-	      *vtable_slot = val;
-	    }
-	  if (slot && !*slot)
-	    *slot = val;
-	  build_bases = add_type_duplicate (val, type);
-	}
+	build_bases = add_type_duplicate (val, type);
     }
   else
     {
@@ -2061,10 +1963,7 @@
 	val->anonymous_namespace = 0;
       build_bases = COMPLETE_TYPE_P (val->type);
       insert_to_odr_array = true;
-      if (slot)
-        *slot = val;
-      if (vtable_slot)
-	*vtable_slot = val;
+      *slot = val;
     }
 
   if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
@@ -2079,7 +1978,7 @@
       val->all_derivations_known = type_all_derivations_known_p (type);
       for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++)
 	/* For now record only polymorphic types. other are
-	   pointless for devirtualization and we can not precisely
+	   pointless for devirtualization and we cannot precisely
 	   determine ODR equivalency of these during LTO.  */
 	if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo, i)))
 	  {
@@ -2111,27 +2010,104 @@
   return val;
 }
 
-/* Add TYPE od ODR type hash.  */
+/* Return type that in ODR type hash prevailed TYPE.  Be careful and punt
+   on ODR violations.  */
+
+tree
+prevailing_odr_type (tree type)
+{
+  odr_type t = get_odr_type (type, false);
+  if (!t || t->odr_violated)
+    return type;
+  return t->type;
+}
+
+/* Set tbaa_enabled flag for TYPE.  */
+
+void
+enable_odr_based_tbaa (tree type)
+{
+  odr_type t = get_odr_type (type, true);
+  t->tbaa_enabled = true;
+}
+
+/* True if canonical type of TYPE is determined using ODR name.  */
+
+bool
+odr_based_tbaa_p (const_tree type)
+{
+  if (!RECORD_OR_UNION_TYPE_P (type))
+    return false;
+  odr_type t = get_odr_type (const_cast <tree> (type), false);
+  if (!t || !t->tbaa_enabled)
+    return false;
+  return true;
+}
+
+/* Set TYPE_CANONICAL of type and all its variants and duplicates
+   to CANONICAL.  */
+
+void
+set_type_canonical_for_odr_type (tree type, tree canonical)
+{
+  odr_type t = get_odr_type (type, false);
+  unsigned int i;
+  tree tt;
+
+  for (tree t2 = t->type; t2; t2 = TYPE_NEXT_VARIANT (t2))
+    TYPE_CANONICAL (t2) = canonical;
+  if (t->types)
+    FOR_EACH_VEC_ELT (*t->types, i, tt)
+      for (tree t2 = tt; t2; t2 = TYPE_NEXT_VARIANT (t2))
+        TYPE_CANONICAL (t2) = canonical;
+}
+
+/* Return true if we reported some ODR violation on TYPE.  */
+
+bool
+odr_type_violation_reported_p (tree type)
+{
+  return get_odr_type (type, false)->odr_violated;
+}
+
+/* Add TYPE of ODR type hash.  */
 
 void
 register_odr_type (tree type)
 {
   if (!odr_hash)
+    odr_hash = new odr_hash_type (23);
+  if (type == TYPE_MAIN_VARIANT (type))
     {
-      odr_hash = new odr_hash_type (23);
-      if (in_lto_p)
-        odr_vtable_hash = new odr_vtable_hash_type (23);
+      /* To get ODR warnings right, first register all sub-types.  */
+      if (RECORD_OR_UNION_TYPE_P (type)
+	  && COMPLETE_TYPE_P (type))
+	{
+	  /* Limit recursion on types which are already registered.  */
+	  odr_type ot = get_odr_type (type, false);
+	  if (ot
+	      && (ot->type == type
+		  || (ot->types_set
+		      && ot->types_set->contains (type))))
+	    return;
+	  for (tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
+	    if (TREE_CODE (f) == FIELD_DECL)
+	      {
+		tree subtype = TREE_TYPE (f);
+
+		while (TREE_CODE (subtype) == ARRAY_TYPE)
+		  subtype = TREE_TYPE (subtype);
+		if (type_with_linkage_p (TYPE_MAIN_VARIANT (subtype)))
+		  register_odr_type (TYPE_MAIN_VARIANT (subtype));
+	      }
+	   if (TYPE_BINFO (type))
+	     for (unsigned int i = 0;
+	          i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
+	       register_odr_type (BINFO_TYPE (BINFO_BASE_BINFO
+						 (TYPE_BINFO (type), i)));
+	}
+      get_odr_type (type, true);
     }
-  /* Arrange things to be nicer and insert main variants first.
-     ??? fundamental prerecorded types do not have mangled names; this
-     makes it possible that non-ODR type is main_odr_variant of ODR type.
-     Things may get smoother if LTO FE set mangled name of those types same
-     way as C++ FE does.  */
-  if (odr_type_p (main_odr_variant (TYPE_MAIN_VARIANT (type)))
-      && odr_type_p (TYPE_MAIN_VARIANT (type)))
-    get_odr_type (TYPE_MAIN_VARIANT (type), true);
-  if (TYPE_MAIN_VARIANT (type) != type && odr_type_p (main_odr_variant (type)))
-    get_odr_type (type, true);
 }
 
 /* Return true if type is known to have no derivations.  */
@@ -2158,9 +2134,6 @@
   fprintf (f, "%s\n", t->all_derivations_known ? " (derivations known)":"");
   if (TYPE_NAME (t->type))
     {
-      /*fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "",
-	       DECL_SOURCE_FILE (TYPE_NAME (t->type)),
-	       DECL_SOURCE_LINE (TYPE_NAME (t->type)));*/
       if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type)))
         fprintf (f, "%*s mangled name: %s\n", indent * 2, "",
 		 IDENTIFIER_POINTER
@@ -2188,6 +2161,7 @@
 dump_type_inheritance_graph (FILE *f)
 {
   unsigned int i;
+  unsigned int num_all_types = 0, num_types = 0, num_duplicates = 0;
   if (!odr_types_ptr)
     return;
   fprintf (f, "\n\nType inheritance graph:\n");
@@ -2198,26 +2172,88 @@
     }
   for (i = 0; i < odr_types.length (); i++)
     {
-      if (odr_types[i] && odr_types[i]->types && odr_types[i]->types->length ())
+      if (!odr_types[i])
+	continue;
+
+      num_all_types++;
+      if (!odr_types[i]->types || !odr_types[i]->types->length ())
+	continue;
+
+      /* To aid ODR warnings we also mangle integer constants but do
+	 not consider duplicates there.  */
+      if (TREE_CODE (odr_types[i]->type) == INTEGER_TYPE)
+	continue;
+
+      /* It is normal to have one duplicate and one normal variant.  */
+      if (odr_types[i]->types->length () == 1
+	  && COMPLETE_TYPE_P (odr_types[i]->type)
+	  && !COMPLETE_TYPE_P ((*odr_types[i]->types)[0]))
+	continue;
+
+      num_types ++;
+
+      unsigned int j;
+      fprintf (f, "Duplicate tree types for odr type %i\n", i);
+      print_node (f, "", odr_types[i]->type, 0);
+      print_node (f, "", TYPE_NAME (odr_types[i]->type), 0);
+      putc ('\n',f);
+      for (j = 0; j < odr_types[i]->types->length (); j++)
 	{
-	  unsigned int j;
-	  fprintf (f, "Duplicate tree types for odr type %i\n", i);
-	  print_node (f, "", odr_types[i]->type, 0);
-	  for (j = 0; j < odr_types[i]->types->length (); j++)
+	  tree t;
+	  num_duplicates ++;
+	  fprintf (f, "duplicate #%i\n", j);
+	  print_node (f, "", (*odr_types[i]->types)[j], 0);
+	  t = (*odr_types[i]->types)[j];
+	  while (TYPE_P (t) && TYPE_CONTEXT (t))
 	    {
-	      tree t;
-	      fprintf (f, "duplicate #%i\n", j);
-	      print_node (f, "", (*odr_types[i]->types)[j], 0);
-	      t = (*odr_types[i]->types)[j];
-	      while (TYPE_P (t) && TYPE_CONTEXT (t))
-		{
-		  t = TYPE_CONTEXT (t);
-	          print_node (f, "", t, 0);
-		}
-	      putc ('\n',f);
+	      t = TYPE_CONTEXT (t);
+	      print_node (f, "", t, 0);
 	    }
+	  print_node (f, "", TYPE_NAME ((*odr_types[i]->types)[j]), 0);
+	  putc ('\n',f);
 	}
     }
+  fprintf (f, "Out of %i types there are %i types with duplicates; "
+	   "%i duplicates overall\n", num_all_types, num_types, num_duplicates);
+}
+
+/* Save some WPA->ltrans streaming by freeing stuff needed only for good
+   ODR warnings.
+   We free TYPE_VALUES of enums and also make TYPE_DECLs to not point back
+   to the type (which is needed to keep them in the same SCC and preserve
+   location information to output warnings) and subsequently we make all
+   TYPE_DECLS of same assembler name equivalent.  */
+
+static void
+free_odr_warning_data ()
+{
+  static bool odr_data_freed = false;
+
+  if (odr_data_freed || !flag_wpa || !odr_types_ptr)
+    return;
+
+  odr_data_freed = true;
+
+  for (unsigned int i = 0; i < odr_types.length (); i++)
+    if (odr_types[i])
+      {
+	tree t = odr_types[i]->type;
+
+	if (TREE_CODE (t) == ENUMERAL_TYPE)
+	  TYPE_VALUES (t) = NULL;
+	TREE_TYPE (TYPE_NAME (t)) = void_type_node;
+
+	if (odr_types[i]->types)
+          for (unsigned int j = 0; j < odr_types[i]->types->length (); j++)
+	    {
+	      tree td = (*odr_types[i]->types)[j];
+
+	      if (TREE_CODE (td) == ENUMERAL_TYPE)
+	        TYPE_VALUES (td) = NULL;
+	      TYPE_NAME (td) = TYPE_NAME (t);
+	    }
+      }
+  odr_data_freed = true;
 }
 
 /* Initialize IPA devirt and build inheritance tree graph.  */
@@ -2230,12 +2266,13 @@
   dump_flags_t flags;
 
   if (odr_hash)
-    return;
+    {
+      free_odr_warning_data ();
+      return;
+    }
   timevar_push (TV_IPA_INHERITANCE);
   inheritance_dump_file = dump_begin (TDI_inheritance, &flags);
   odr_hash = new odr_hash_type (23);
-  if (in_lto_p)
-    odr_vtable_hash = new odr_vtable_hash_type (23);
 
   /* We reconstruct the graph starting of types of all methods seen in the
      unit.  */
@@ -2275,6 +2312,7 @@
       dump_type_inheritance_graph (inheritance_dump_file);
       dump_end (TDI_inheritance, inheritance_dump_file);
     }
+  free_odr_warning_data ();
   timevar_pop (TV_IPA_INHERITANCE);
 }
 
@@ -2332,7 +2370,7 @@
 
 /* If TARGET has associated node, record it in the NODES array.
    CAN_REFER specify if program can refer to the target directly.
-   if TARGET is unknown (NULL) or it can not be inserted (for example because
+   if TARGET is unknown (NULL) or it cannot be inserted (for example because
    its body was already removed and there is no way to refer to it), clear
    COMPLETEP.  */
 
@@ -2404,7 +2442,7 @@
 	       || target_node->definition)
 	   && target_node->real_symbol_p ())
     {
-      gcc_assert (!target_node->global.inlined_to);
+      gcc_assert (!target_node->inlined_to);
       gcc_assert (target_node->real_symbol_p ());
       /* When sanitizing, do not assume that __cxa_pure_virtual is not called
 	 by valid program.  */
@@ -2433,7 +2471,7 @@
   else if (!completep)
     ;
   /* We have definition of __cxa_pure_virtual that is not accessible (it is
-     optimized out or partitioned to other unit) so we can not add it.  When
+     optimized out or partitioned to other unit) so we cannot add it.  When
      not sanitizing, there is nothing to do.
      Otherwise declare the list incomplete.  */
   else if (pure_virtual)
@@ -2616,14 +2654,16 @@
    polymorphic calls in the program, so we memoize all the previous
    queries and avoid duplicated work.  */
 
-struct polymorphic_call_target_d
+class polymorphic_call_target_d
 {
+public:
   HOST_WIDE_INT otr_token;
   ipa_polymorphic_call_context context;
   odr_type type;
   vec <cgraph_node *> targets;
   tree decl_warning;
   int type_warning;
+  unsigned int n_odr_types;
   bool complete;
   bool speculative;
 };
@@ -2649,6 +2689,7 @@
   hstate.add_hwi (odr_query->type->id);
   hstate.merge_hash (TYPE_UID (odr_query->context.outer_type));
   hstate.add_hwi (odr_query->context.offset);
+  hstate.add_hwi (odr_query->n_odr_types);
 
   if (odr_query->context.speculative_outer_type)
     {
@@ -2679,7 +2720,9 @@
 	      == t2->context.maybe_in_construction
 	  && t1->context.maybe_derived_type == t2->context.maybe_derived_type
 	  && (t1->context.speculative_maybe_derived_type
-	      == t2->context.speculative_maybe_derived_type));
+	      == t2->context.speculative_maybe_derived_type)
+	  /* Adding new type may affect outcome of target search.  */
+	  && t1->n_odr_types == t2->n_odr_types);
 }
 
 /* Remove entry in polymorphic call target cache hash.  */
@@ -2721,10 +2764,7 @@
   if (!odr_hash)
     return;
   delete odr_hash;
-  if (in_lto_p)
-    delete odr_vtable_hash;
   odr_hash = NULL;
-  odr_vtable_hash = NULL;
   odr_types_ptr = NULL;
   free_polymorphic_call_targets_hash ();
 }
@@ -2735,6 +2775,7 @@
 devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
 {
   if (cached_polymorphic_call_targets
+      && !thunk_expansion
       && cached_polymorphic_call_targets->contains (n))
     free_polymorphic_call_targets_hash ();
 }
@@ -2938,8 +2979,9 @@
 
 /* Information about type and decl warnings.  */
 
-struct final_warning_record
+class final_warning_record
 {
+public:
   /* If needed grow type_warnings vector and initialize new decl_warn_count
      to have dyn_count set to profile_count::zero ().  */
   void grow_type_warnings (unsigned newlen);
@@ -2961,14 +3003,14 @@
     }
 }
 
-struct final_warning_record *final_warning_records;
+class final_warning_record *final_warning_records;
 
 /* Return vector containing possible targets of polymorphic call of type
    OTR_TYPE calling method OTR_TOKEN within type of OTR_OUTER_TYPE and OFFSET.
    If INCLUDE_BASES is true, walk also base types of OUTER_TYPES containing
    OTR_TYPE and include their virtual method.  This is useful for types
    possibly in construction or destruction where the virtual table may
-   temporarily change to one of base types.  INCLUDE_DERIVER_TYPES make
+   temporarily change to one of base types.  INCLUDE_DERIVED_TYPES make
    us to walk the inheritance graph for all derivations.
 
    If COMPLETEP is non-NULL, store true if the list is complete. 
@@ -3085,6 +3127,7 @@
   key.otr_token = otr_token;
   key.speculative = speculative;
   key.context = context;
+  key.n_odr_types = odr_types.length ();
   slot = polymorphic_call_target_hash->find_slot (&key, INSERT);
   if (cache_token)
    *cache_token = (void *)*slot;
@@ -3301,6 +3344,7 @@
 
   (*slot)->targets = nodes;
   (*slot)->complete = complete;
+  (*slot)->n_odr_types = odr_types.length ();
   if (completep)
     *completep = complete;
 
@@ -3319,7 +3363,7 @@
 /* Dump target list TARGETS into FILE.  */
 
 static void
-dump_targets (FILE *f, vec <cgraph_node *> targets)
+dump_targets (FILE *f, vec <cgraph_node *> targets, bool verbose)
 {
   unsigned int i;
 
@@ -3328,14 +3372,20 @@
       char *name = NULL;
       if (in_lto_p)
 	name = cplus_demangle_v3 (targets[i]->asm_name (), 0);
-      fprintf (f, " %s/%i", name ? name : targets[i]->name (),
-	       targets[i]->order);
+      fprintf (f, " %s", name ? name : targets[i]->dump_name ());
       if (in_lto_p)
 	free (name);
       if (!targets[i]->definition)
 	fprintf (f, " (no definition%s)",
 		 DECL_DECLARED_INLINE_P (targets[i]->decl)
 		 ? " inline" : "");
+      /* With many targets for every call polymorphic dumps are going to
+	 be quadratic in size.  */
+      if (i > 10 && !verbose)
+	{
+	  fprintf (f, " ... and %i more targets\n", targets.length () - i);
+	  return;
+	}
     }
   fprintf (f, "\n");
 }
@@ -3346,7 +3396,8 @@
 dump_possible_polymorphic_call_targets (FILE *f,
 					tree otr_type,
 					HOST_WIDE_INT otr_token,
-					const ipa_polymorphic_call_context &ctx)
+					const ipa_polymorphic_call_context &ctx,
+					bool verbose)
 {
   vec <cgraph_node *> targets;
   bool final;
@@ -3371,7 +3422,7 @@
 	   ctx.maybe_derived_type ? " (derived types included)" : "",
 	   ctx.speculative_maybe_derived_type ? " (speculative derived types included)" : "");
   len = targets.length ();
-  dump_targets (f, targets);
+  dump_targets (f, targets, verbose);
 
   targets = possible_polymorphic_call_targets (otr_type, otr_token,
 					       ctx,
@@ -3379,7 +3430,7 @@
   if (targets.length () != len)
     {
       fprintf (f, "  Speculative targets:");
-      dump_targets (f, targets);
+      dump_targets (f, targets, verbose);
     }
   /* Ugly: during callgraph construction the target cache may get populated
      before all targets are found.  While this is harmless (because all local
@@ -3403,12 +3454,10 @@
 {
   vec <cgraph_node *> targets;
   unsigned int i;
-  enum built_in_function fcode;
   bool final;
 
-  if (TREE_CODE (TREE_TYPE (n->decl)) == FUNCTION_TYPE
-      && ((fcode = DECL_FUNCTION_CODE (n->decl)) == BUILT_IN_UNREACHABLE
-          || fcode == BUILT_IN_TRAP))
+  if (fndecl_built_in_p (n->decl, BUILT_IN_UNREACHABLE)
+      || fndecl_built_in_p (n->decl, BUILT_IN_TRAP))
     return true;
 
   if (is_cxa_pure_virtual_p (n->decl))
@@ -3503,7 +3552,7 @@
 /* Compare type warning records P1 and P2 and choose one with larger count;
    helper for qsort.  */
 
-int
+static int
 type_warning_cmp (const void *p1, const void *p2)
 {
   const odr_type_warn_count *t1 = (const odr_type_warn_count *)p1;
@@ -3519,7 +3568,7 @@
 /* Compare decl warning records P1 and P2 and choose one with larger count;
    helper for qsort.  */
 
-int
+static int
 decl_warning_cmp (const void *p1, const void *p2)
 {
   const decl_warn_count *t1 = *(const decl_warn_count * const *)p1;
@@ -3633,7 +3682,7 @@
 
 	    if (dump_file)
 	      dump_possible_polymorphic_call_targets 
-		(dump_file, e);
+		(dump_file, e, (dump_flags & TDF_DETAILS));
 
 	    npolymorphic++;
 
@@ -3645,7 +3694,7 @@
 	       itself.
 
 	       This may need to be revisited once we add further ways to use
-	       the may edges, but it is a resonable thing to do right now.  */
+	       the may edges, but it is a reasonable thing to do right now.  */
 
 	    if ((e->indirect_info->param_index == -1
 		|| (!opt_for_fn (n->decl, flag_devirtualize_speculatively)
@@ -3656,7 +3705,7 @@
 		ndropped++;
 	        if (dump_file)
 		  fprintf (dump_file, "Dropping polymorphic call info;"
-			   " it can not be used by ipa-prop\n");
+			   " it cannot be used by ipa-prop\n");
 	      }
 
 	    if (!opt_for_fn (n->decl, flag_devirtualize_speculatively))
@@ -3708,11 +3757,8 @@
  	       with the speculation.  */
 	    if (e->speculative)
 	      {
-		struct cgraph_edge *e2;
-		struct ipa_ref *ref;
-		e->speculative_call_info (e2, e, ref);
-		if (e2->callee->ultimate_alias_target ()
-		    == likely_target->ultimate_alias_target ())
+		bool found = e->speculative_call_for_target (likely_target);
+		if (found)
 		  {
 		    fprintf (dump_file, "We agree with speculation\n\n");
 		    nok++;
@@ -3954,4 +4000,20 @@
   return new pass_ipa_devirt (ctxt);
 }
 
+/* Print ODR name of a TYPE if available.
+   Use demangler when option DEMANGLE is used.  */
+
+DEBUG_FUNCTION void
+debug_tree_odr_name (tree type, bool demangle)
+{
+  const char *odr = get_odr_name_for_type (type);
+  if (demangle)
+    {
+      const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
+      odr = cplus_demangle (odr, opts);
+    }
+
+  fprintf (stderr, "%s\n", odr);
+}
+
 #include "gt-ipa-devirt.h"