Index: testsuite/g++.dg/lto/pr65475c_1.C
===================================================================
--- testsuite/g++.dg/lto/pr65475c_1.C	(revision 0)
+++ testsuite/g++.dg/lto/pr65475c_1.C	(revision 0)
@@ -0,0 +1,234 @@
+namespace std
+{
+  template < class _CharT > struct char_traits;
+  typedef long streamsize;
+  template < typename _CharT, typename _Traits =
+    char_traits < _CharT > >class basic_ostream;
+  template < typename _CharT, typename _Traits =
+    char_traits < _CharT > >class Trans_NS___cxx11_basic_ostringstream;
+  template < typename _CharT, typename _Traits =
+    char_traits < _CharT > >class istreambuf_iterator;
+  template < typename _CharT, typename _Traits =
+    char_traits < _CharT > >class ostreambuf_iterator;
+}
+namespace std
+{
+  template < typename _CharT, typename _InIter =
+    istreambuf_iterator < _CharT > >class num_get;
+  template < typename _CharT, typename _OutIter =
+    ostreambuf_iterator < _CharT > >class num_put;
+  struct iterator
+  {
+  };
+}
+typedef int _Atomic_word;
+namespace std
+{
+  class locale
+  {
+  public:class facet;
+    class _Impl;
+      template < typename _Facet > locale ( const locale & __other,
+					    _Facet * __f );
+  private:  _Impl * _M_impl;
+  };
+  class locale::facet
+  {
+    mutable _Atomic_word _M_refcount;
+  protected:  explicit facet ( void ) throw (  );
+      virtual ~ facet (  );
+  };
+  enum _Ios_Fmtflags
+  {
+    _S_boolalpha = 1 << 0, _S_dec, _S_fixed = 1 << 2, _S_hex =
+      1 << 3, _S_internal = 1 << 4, _S_left = 1 << 5, _S_oct =
+      1 << 6, _S_right = 1 << 7, _S_scientific = 1 << 8, _S_showbase =
+      1 << 9, _S_showpoint = 1 << 10, _S_showpos = 1 << 11, _S_skipws =
+      1 << 12, _S_unitbuf = 1 << 13, _S_uppercase = 1 << 14, _S_adjustfield =
+      _S_left | _S_right | _S_internal, _S_basefield =
+      _S_dec | _S_oct | _S_hex, _S_floatfield =
+      _S_scientific | _S_fixed, _S_ios_fmtflags_end = 1 << 16
+  };
+  enum _Ios_Openmode
+  {
+    _S_out
+  };
+  enum _Ios_Iostate
+  {
+    _S_goodbit, _S_badbit, _S_eofbit, _S_failbit =
+      1 << 2, _S_ios_iostate_end = 1 << 16
+  };
+  class ios_base
+  {
+  public:typedef _Ios_Fmtflags fmtflags;
+    typedef _Ios_Iostate iostate;
+  protected:  streamsize _M_precision;
+    streamsize _M_width;
+    fmtflags _M_flags;
+    iostate _M_exception;
+    iostate _M_streambuf_state;
+    struct _Callback_list;
+    _Callback_list *_M_callbacks;
+    struct _Words
+    {
+      void *_M_pword;
+      long _M_iword;
+    };
+    _Words _M_word_zero;
+    enum
+    {
+      _S_local_word_size = 8
+    };
+    _Words _M_local_word[_S_local_word_size];
+    int _M_word_size;
+    _Words *_M_word;
+    locale _M_ios_locale;
+      virtual ~ ios_base (  );
+  };
+  template < typename _CharT, typename _Traits > class basic_streambuf;
+template < typename _CharT, typename _Traits > class ostreambuf_iterator:public
+    iterator
+  {
+    typedef basic_ostream < wchar_t, _Traits > ostream_type;
+  };
+  class __ctype_abstract_base:public locale::facet
+  {
+  };
+template < typename _CharT > class ctype:public __ctype_abstract_base
+  {
+  };
+  class Trans_NS___cxx11_numpunct:public locale::facet
+  {
+  };
+template < typename _CharT, typename _InIter > class num_get:public locale::
+    facet
+  {
+  };
+template < typename _CharT, typename _OutIter > class num_put:public locale::
+    facet
+  {
+  public:typedef int char_type;
+    typedef std::ostreambuf_iterator < wchar_t,
+      std::char_traits < wchar_t > >iter_type;
+  };
+template < typename _CharT, typename _Traits > class basic_ios:public
+    ios_base
+  {
+  public:typedef wchar_t char_type;
+    typedef num_get < wchar_t, istreambuf_iterator < wchar_t,
+      _Traits > >__num_get_type;
+  protected:basic_ostream < wchar_t, _Traits > *_M_tie;
+    mutable char_type _M_fill;
+    mutable bool _M_fill_init;
+    basic_streambuf < wchar_t, _Traits > *_M_streambuf;
+    const ctype < wchar_t > *_M_ctype;
+    const num_put < wchar_t, ostreambuf_iterator < wchar_t,
+      _Traits > >*_M_num_put;
+    const __num_get_type *_M_num_get;
+  };
+template < typename _CharT, typename _Traits > class basic_ostream:virtual public basic_ios < wchar_t,
+    _Traits
+    >
+  {
+  };
+}
+typedef enum
+{
+  posix
+}
+value_type;
+static const unsigned int wchar_t_facet = 1 << 1;
+class shared_ptr
+{
+};
+namespace std 
+{
+template < typename _CharT, typename _Traits > class Trans_NS___cxx11_basic_ostringstream:public basic_ostream < wchar_t,
+    _Traits
+    >
+  {
+  public:explicit Trans_NS___cxx11_basic_ostringstream ( void );
+  };
+}
+class base_num_format:public
+  std::num_put <
+  wchar_t >
+{
+public:typedef typename
+    std::num_put <
+    wchar_t >::iter_type
+    iter_type;
+  typedef wchar_t
+    char_type;
+  base_num_format ( unsigned long refs = 0 );
+  iter_type
+    do_put_out;
+  std::ios_base &
+    do_put_ios;
+  char_type
+    do_put_fill;
+  unsigned long long
+    do_put_val;
+  virtual iter_type
+  do_put ( void ) const
+  {
+    return
+    do_real_put ( do_put_out, do_put_ios, do_put_fill, do_put_val );
+  }
+private:template <
+    typename
+    ValueType >
+    iter_type
+  do_real_put ( iter_type out, std::ios_base & ios, char_type fill,
+		ValueType val ) const
+  {
+    switch ( 0 )
+      case posix:
+      {
+	typedef
+	  std::Trans_NS___cxx11_basic_ostringstream <
+	  char_type >
+	  sstream_type;
+	sstream_type
+	  ss;
+      }
+  }
+};
+class
+  base_num_parse:
+  public
+  std::num_get <
+  wchar_t >
+{
+private:};
+class
+  num_format:
+  public
+  base_num_format
+{
+public:typedef wchar_t
+    iter_type;
+  num_format ( shared_ptr lc, unsigned long refs = 0 )
+  {
+  }
+};
+class
+  num_punct_posix:
+  public
+  std::Trans_NS___cxx11_numpunct
+{
+};
+template < typename CharType >
+  std::locale create_formatting_impl ( std::locale const &in, shared_ptr lc )
+{
+  std::locale tmp = std::locale ( tmp, new num_format ( lc ) );
+}
+shared_ptr create_formatting_lc;
+unsigned int create_formatting_type;
+void
+create_formatting ( std::locale const &in )
+{
+  switch ( create_formatting_type )
+    case wchar_t_facet:
+    create_formatting_impl < wchar_t > ( in, create_formatting_lc );
+}
Index: testsuite/g++.dg/lto/pr65475b_0.C
===================================================================
--- testsuite/g++.dg/lto/pr65475b_0.C	(revision 0)
+++ testsuite/g++.dg/lto/pr65475b_0.C	(revision 0)
@@ -0,0 +1,9 @@
+/* { dg-lto-do link } */
+/* { dg-options "-O2  -Wno-odr" } */
+/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */
+namespace std {
+class exception {};
+class runtime_error : exception {
+  virtual char m_fn1();
+} a;
+}
Index: testsuite/g++.dg/lto/pr65475b_1.C
===================================================================
--- testsuite/g++.dg/lto/pr65475b_1.C	(revision 0)
+++ testsuite/g++.dg/lto/pr65475b_1.C	(revision 0)
@@ -0,0 +1,7 @@
+namespace std {
+class exception {
+  virtual char m_fn1();
+};
+class runtime_error : exception {
+} b;
+}
Index: testsuite/g++.dg/lto/pr65475c_0.C
===================================================================
--- testsuite/g++.dg/lto/pr65475c_0.C	(revision 0)
+++ testsuite/g++.dg/lto/pr65475c_0.C	(revision 0)
@@ -0,0 +1,156 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options "-O2  -w" } */
+/* { dg-extra-ld-options { -O2 -Wno-odr -r -nostdlib } } */
+namespace std
+{
+template < class > struct char_traits;
+typedef long streamsize;
+template < typename, typename > class basic_streambuf;
+template < typename > class A;
+template < typename, typename > class basic_ostream;
+template < typename _CharT, typename =
+           char_traits < _CharT > >class istreambuf_iterator;
+template < typename _CharT, typename =
+           char_traits < _CharT > >class ostreambuf_iterator;
+template < typename > class ctype;
+template < typename _CharT, typename =
+           istreambuf_iterator < _CharT > >class num_get;
+template < typename _CharT, typename =
+           ostreambuf_iterator < _CharT > >class num_put;
+}
+typedef int _Atomic_word;
+namespace std
+{
+class locale
+{
+    class facet;
+    class _Impl;
+    _Impl *_M_impl;
+};
+class locale::facet
+{
+    _Atomic_word _M_refcount;
+protected:
+    virtual ~ facet ();
+};
+enum _Ios_Fmtflags
+{   _S_boolalpha = 1, _S_dec, _S_fixed = 1 << 2, _S_hex =
+        1 << 3, _S_internal = 1 << 4, _S_left = 1 << 5, _S_oct =
+            1 << 6, _S_right = 1 << 7, _S_scientific = 1 << 8, _S_showbase =
+                1 << 9, _S_showpoint = 1 << 10, _S_showpos = 1 << 11, _S_skipws =
+                    1 << 12, _S_unitbuf = 1 << 13, _S_uppercase = 1 << 14, _S_adjustfield =
+                        _S_left | _S_right | _S_internal, _S_basefield =
+                            _S_dec | _S_oct | _S_hex, _S_floatfield =
+                                _S_scientific | _S_fixed, _S_ios_fmtflags_end = 1 << 16
+};
+enum _Ios_Iostate
+{   _S_goodbit, _S_badbit, _S_eofbit, _S_failbit =
+        1 << 2, _S_ios_iostate_end = 1 << 16
+};
+class ios_base
+{
+    typedef _Ios_Fmtflags fmtflags;
+    typedef _Ios_Iostate iostate;
+    streamsize _M_precision;
+    streamsize _M_width;
+    fmtflags _M_flags;
+    iostate _M_exception;
+    iostate _M_streambuf_state;
+    struct _Callback_list;
+    _Callback_list *_M_callbacks;
+    struct _Words
+    {
+        void *_M_pword;
+        long _M_iword;
+    } _M_word_zero;
+    enum
+    { _S_local_word_size = 8 };
+    _Words _M_local_word[_S_local_word_size];
+    int _M_word_size;
+    _Words *_M_word;
+    locale _M_ios_locale;
+    virtual ~ ios_base ();
+};
+template < typename, typename > class istreambuf_iterator
+{
+    typedef A < char_traits < wchar_t > >istream_type;
+};
+template < typename, typename > class ostreambuf_iterator
+{
+    typedef basic_ostream < wchar_t, char_traits < wchar_t > >ostream_type;
+};
+template < typename, typename > class num_get:locale::facet
+{
+public:
+    typedef istreambuf_iterator < wchar_t > iter_type;
+};
+template < typename, typename > class num_put:locale::facet
+{
+public:
+    typedef ostreambuf_iterator < wchar_t > iter_type;
+};
+template < typename, typename > class basic_ios:ios_base
+{
+    typedef wchar_t char_type;
+    basic_ostream < wchar_t, char_traits < wchar_t > >*_M_tie;
+    char_type _M_fill;
+    bool _M_fill_init;
+    basic_streambuf < wchar_t, char_traits < wchar_t > >*_M_streambuf;
+    ctype < wchar_t > *_M_ctype;
+    num_put < wchar_t > *_M_num_put;
+    num_get < wchar_t > *_M_num_get;
+};
+template < typename, typename > class basic_ostream:virtual basic_ios < wchar_t,
+    char_traits < wchar_t >
+    >
+{
+    typedef basic_ios __ios_type;
+};
+template < typename > class A:basic_ios < wchar_t, int >
+{
+};
+class B:A < char_traits < wchar_t > >, basic_ostream < wchar_t,
+    char_traits < wchar_t > >
+{
+};
+}
+
+class C:
+    std::num_put <
+    wchar_t >
+{
+public:
+    C (int);
+    iter_type
+    do_put_out;
+};
+class
+    D:
+    std::num_get <
+    wchar_t >
+{
+public:
+    D (int);
+    iter_type
+    do_get_in;
+};
+template < typename > void
+install_formatting_facets (std::locale, int p2)
+{
+    (C (p2));
+}
+
+template < typename > void
+install_parsing_facets (std::locale, int p2)
+{
+    (D (p2));
+}
+
+std::locale a;
+int b;
+void
+create_formatting ()
+{
+    install_formatting_facets < wchar_t > (a, b);
+    install_parsing_facets < wchar_t > (a, b);
+}
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 221572)
+++ ipa-devirt.c	(working copy)
@@ -166,6 +166,7 @@ along with GCC; see the file COPYING3.
 #include "gimple-pretty-print.h"
 #include "stor-layout.h"
 #include "intl.h"
+#include "demangle.h"
 
 /* Hash based set of pairs of types.  */
 typedef struct
@@ -239,6 +240,8 @@ struct GTY(()) odr_type_d
   bool all_derivations_known;
   /* Did we report ODR violation here?  */
   bool odr_violated;
+  /* Set when virtual table without RTTI previaled table with.  */
+  bool rtti_broken;
 };
 
 /* Return TRUE if all derived types of T are known and thus
@@ -673,8 +676,6 @@ odr_subtypes_equivalent_p (tree t1, tree
     return false;
   if ((TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
     return false;
-  if (TYPE_NAME (t1) && DECL_NAME (TYPE_NAME (t1)) != DECL_NAME (TYPE_NAME (t2)))
-    return false;
 
   type_pair pair={t1,t2};
   if (TYPE_UID (t1) > TYPE_UID (t2))
@@ -694,6 +695,7 @@ void
 compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
 {
   int n1, n2;
+
   if (DECL_VIRTUAL_P (prevailing->decl) != DECL_VIRTUAL_P (vtable->decl))
     {
       odr_violation_reported = true;
@@ -715,6 +717,17 @@ compare_virtual_tables (varpool_node *pr
     }
   if (!prevailing->definition || !vtable->definition)
     return;
+
+  /* If we do not stream ODR type info, do not bother to do useful compare.  */
+  if (!TYPE_BINFO (DECL_CONTEXT (vtable->decl))
+      || !polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (vtable->decl))))
+    return;
+
+  odr_type class_type = get_odr_type (DECL_CONTEXT (vtable->decl), true);
+
+  if (class_type->odr_violated)
+    return;
+
   for (n1 = 0, n2 = 0; true; n1++, n2++)
     {
       struct ipa_ref *ref1, *ref2;
@@ -730,13 +743,16 @@ compare_virtual_tables (varpool_node *pr
 	     && (end1
 	         || (DECL_ASSEMBLER_NAME (ref1->referred->decl)
 		     != DECL_ASSEMBLER_NAME (ref2->referred->decl)
-	             && DECL_VIRTUAL_P (ref1->referred->decl)))
-	     && !DECL_VIRTUAL_P (ref2->referred->decl))
+	             && TREE_CODE (ref1->referred->decl) == FUNCTION_DECL))
+	     && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
 	{
-	  if (warning_at (DECL_SOURCE_LOCATION
-			    (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
-			  "virtual table of type %qD contains RTTI information",
-			  DECL_CONTEXT (vtable->decl)))
+	  if (!class_type->rtti_broken
+	      && warning_at (DECL_SOURCE_LOCATION
+			      (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+			     OPT_Wodr,
+			     "virtual table of type %qD contains RTTI "
+			     "information",
+			     DECL_CONTEXT (vtable->decl)))
 	    {
 	      inform (DECL_SOURCE_LOCATION
 			(TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
@@ -745,6 +761,7 @@ compare_virtual_tables (varpool_node *pr
 	      inform (DECL_SOURCE_LOCATION
 			(TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
 		      "RTTI will not work on this type");
+	      class_type->rtti_broken = true;
 	    }
 	  n2++;
           end2 = !vtable->iterate_reference (n2, ref2);
@@ -753,11 +770,11 @@ compare_virtual_tables (varpool_node *pr
 	     && (end2
 	         || (DECL_ASSEMBLER_NAME (ref2->referred->decl)
 		     != DECL_ASSEMBLER_NAME (ref1->referred->decl)
-	             && DECL_VIRTUAL_P (ref2->referred->decl)))
-	     && !DECL_VIRTUAL_P (ref1->referred->decl))
+	             && TREE_CODE (ref2->referred->decl) == FUNCTION_DECL))
+	     && TREE_CODE (ref1->referred->decl) != FUNCTION_DECL)
 	{
 	  n1++;
-          end1 = !vtable->iterate_reference (n1, ref1);
+          end1 = !prevailing->iterate_reference (n1, ref1);
 	}
 
       /* Finished?  */
@@ -770,8 +787,10 @@ compare_virtual_tables (varpool_node *pr
 	     is not output too often.  */
 	  if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl))
 	    {
+	      class_type->odr_violated = true;
 	      if (warning_at (DECL_SOURCE_LOCATION
-				(TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+				(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+			      OPT_Wodr,
 			      "virtual table of type %qD violates "
 			      "one definition rule  ",
 			      DECL_CONTEXT (vtable->decl)))
@@ -791,13 +810,16 @@ compare_virtual_tables (varpool_node *pr
 	      == DECL_ASSEMBLER_NAME (ref2->referred->decl))
 	    continue;
 
+	  class_type->odr_violated = true;
+
 	  /* If the loops above stopped on non-virtual pointer, we have
 	     mismatch in RTTI information mangling.  */
-	  if (!DECL_VIRTUAL_P (ref1->referred->decl)
-	      && !DECL_VIRTUAL_P (ref2->referred->decl))
+	  if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL
+	      && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
 	    {
 	      if (warning_at (DECL_SOURCE_LOCATION
-				(TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+				(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+			      OPT_Wodr,
 			      "virtual table of type %qD violates "
 			      "one definition rule  ",
 			      DECL_CONTEXT (vtable->decl)))
@@ -813,12 +835,6 @@ compare_virtual_tables (varpool_node *pr
 	     or virtual method.  If one points to virtual table and other to
 	     method we can complain the same way as if one table was shorter
 	     than other pointing out the extra method.  */
-	  gcc_assert (DECL_VIRTUAL_P (ref1->referred->decl)
-		      && (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL
-		          || TREE_CODE (ref1->referred->decl) == VAR_DECL));
-	  gcc_assert (DECL_VIRTUAL_P (ref2->referred->decl)
-		      && (TREE_CODE (ref2->referred->decl) == FUNCTION_DECL
-		          || TREE_CODE (ref2->referred->decl) == VAR_DECL));
 	  if (TREE_CODE (ref1->referred->decl)
 	      != TREE_CODE (ref2->referred->decl))
 	    {
@@ -829,6 +845,8 @@ compare_virtual_tables (varpool_node *pr
 	    }
 	}
 
+      class_type->odr_violated = true;
+
       /* Complain about size mismatch.  Either we have too many virutal
  	 functions or too many virtual table pointers.  */
       if (end1 || end2)
@@ -841,7 +859,8 @@ compare_virtual_tables (varpool_node *pr
 	      ref1 = ref2;
 	    }
 	  if (warning_at (DECL_SOURCE_LOCATION
-			    (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+			    (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+			  OPT_Wodr,
 			  "virtual table of type %qD violates "
 			  "one definition rule",
 			  DECL_CONTEXT (vtable->decl)))
@@ -871,7 +890,7 @@ compare_virtual_tables (varpool_node *pr
       /* And in the last case we have either mistmatch in between two virtual
 	 methods or two virtual table pointers.  */
       if (warning_at (DECL_SOURCE_LOCATION
-			(TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+			(TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
 		      "virtual table of type %qD violates "
 		      "one definition rule  ",
 		      DECL_CONTEXT (vtable->decl)))
@@ -914,8 +933,9 @@ warn_odr (tree t1, tree t2, tree st1, tr
   if (warned)
     *warned = false;
 
-  if (!warn)
+  if (!warn || !TYPE_NAME(t1))
     return;
+
   if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr,
 		   "type %qT violates one definition rule",
 		   t1))
@@ -964,7 +984,132 @@ warn_odr (tree t1, tree t2, tree st1, tr
 void
 warn_types_mismatch (tree t1, tree t2)
 {
+  /* If types have names and they are different, it is most informative to
+     output those.  */
+  if (TYPE_NAME (t1) && TYPE_NAME (t2)
+      && 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)))
+    {
+      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);
+      if (name1 && name2 && strcmp (name1, name2))
+	{
+	  inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)),
+		  "type name %<%s%> should match type name %<%s%>",
+		  name1, name2);
+	  inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)),
+		  "the incompatible type is defined here");
+	  free (name1);
+	  return;
+	}
+      free (name1);
+    }
+  /* It is a quite common bug to reference anonymous namespace type in
+     non-anonymous namespace class.  */
+  if (type_in_anonymous_namespace_p (t1)
+      || type_in_anonymous_namespace_p (t2))
+    {
+      if (!type_in_anonymous_namespace_p (t1))
+	{
+	  tree tmp = t1;;
+	  t1 = t2;
+	  t2 = tmp;
+	}
+      if (TYPE_NAME (t1) && TYPE_NAME (t2))
+	{
+	  inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)),
+		  "type %qT defined in anonymous namespace can not match "
+		  "type %qT",
+		  t1, t2);
+	  inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)),
+		  "the incompatible type defined in anonymous namespace in "
+		  "another translation unit");
+	}
+      else
+	inform (UNKNOWN_LOCATION,
+		"types in anonymous namespace does not match across "
+		"translation unit boundary");
+      return;
+    }
+  /* A tricky case are component types.  Often they appear the same in source
+     code and the mismatch is dragged in by type they are build from.
+     Look for those differences in subtypes and try to be informative.  In other
+     cases just output nothing because the source code is probably different
+     and in this case we already output a all necessary info.  */
   if (!TYPE_NAME (t1) || !TYPE_NAME (t2))
+    {
+      if (TREE_CODE (t1) == TREE_CODE (t2))
+	{
+	  hash_set<type_pair,pair_traits> visited;
+	  if (TREE_CODE (t1) == ARRAY_TYPE
+	      && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
+	    {
+	      tree i1 = TYPE_DOMAIN (t1);
+	      tree i2 = TYPE_DOMAIN (t2);
+	
+	      if (i1 && i2
+		  && TYPE_MAX_VALUE (i1)
+		  && TYPE_MAX_VALUE (i2)
+		  && !operand_equal_p (TYPE_MAX_VALUE (i1),
+				       TYPE_MAX_VALUE (i2), 0))
+		{
+		  inform (UNKNOWN_LOCATION,
+			  "array types have different bounds");
+		  return;
+		}
+	    }
+	  if ((POINTER_TYPE_P (t1) || TREE_CODE (t1) == ARRAY_TYPE)
+	      && !odr_subtypes_equivalent_p (TREE_TYPE (t1),
+					     TREE_TYPE (t2),
+					     &visited))
+	    warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2));
+	  else if (TREE_CODE (t1) == METHOD_TYPE
+		   || TREE_CODE (t1) == FUNCTION_TYPE)
+	    {
+	      tree parms1, parms2;
+	      int count = 1;
+
+	      if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
+					      &visited))
+		{
+		  inform (UNKNOWN_LOCATION, "return value type mismatch");
+		  warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2));
+		  return;
+		}
+	      for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
+		   parms1 && parms2;
+		   parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2),
+		   count++)
+		{
+		  if (!odr_subtypes_equivalent_p
+		      (TREE_VALUE (parms1), TREE_VALUE (parms2), &visited))
+		    {
+		      inform (UNKNOWN_LOCATION,
+			      "type mismatch in parameter %i", count);
+		      warn_types_mismatch (TREE_VALUE (parms1),
+					   TREE_VALUE (parms2));
+		      return;
+		    }
+		}
+	      if (parms1 || parms2)
+		{
+		  inform (UNKNOWN_LOCATION,
+			  "types have different parameter counts");
+		  return;
+		}
+	    }
+	}
+      return;
+    }
+  /* This should not happen but if it does, the warning would not be helpful.
+     TODO: turn it into assert next stage1.  */
+  if (TYPE_NAME (t1) == TYPE_NAME (t2))
     return;
   /* In Firefox it is a common bug to have same types but in
      different namespaces.  Be a bit more informative on
@@ -979,12 +1124,19 @@ warn_types_mismatch (tree t1, tree t2)
 	    "type %qT should match type %qT but is defined "
 	    "in different namespace  ",
 	    t1, t2);
+  else if (types_odr_comparable (t1, t2, true)
+	   && types_same_for_odr (t1, t2, true))
+    inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)),
+	    "type %qT should match type %qT that itself violate "
+	    "one definition rule",
+	    t1, t2);
   else
     inform (DECL_SOURCE_LOCATION (TYPE_NAME (t1)),
 	    "type %qT should match type %qT",
 	    t1, t2);
-  inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)),
-	  "the incompatible type is defined here");
+  if (DECL_SOURCE_LOCATION (TYPE_NAME (t2)) > BUILTINS_LOCATION)
+    inform (DECL_SOURCE_LOCATION (TYPE_NAME (t2)),
+	    "the incompatible type is defined here");
 }
 
 /* Compare T1 and T2, report ODR violations if WARN is true and set
@@ -1232,6 +1384,20 @@ odr_types_equivalent_p (tree t1, tree t2
 	/* For aggregate types, all the fields must be the same.  */
 	if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
 	  {
+	    if (TYPE_BINFO (t1) && TYPE_BINFO (t2)
+	        && polymorphic_type_binfo_p (TYPE_BINFO (t1))
+		   != polymorphic_type_binfo_p (TYPE_BINFO (t2)))
+	      {
+		if (polymorphic_type_binfo_p (TYPE_BINFO (t1)))
+		  warn_odr (t1, t2, NULL, NULL, warn, warned,
+			    G_("a type defined in another translation unit "
+			       "is not polymorphic"));
+		else
+		  warn_odr (t1, t2, NULL, NULL, warn, warned,
+			    G_("a type defined in another translation unit "
+			       "is polymorphic"));
+		return false;
+	      }
 	    for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
 		 f1 || f2;
 		 f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
@@ -1303,8 +1469,8 @@ odr_types_equivalent_p (tree t1, tree t2
 		  warn_odr (t1, t2, NULL, NULL, warn, warned,
 			    G_("a type with different virtual table pointers"
 			       " is defined in another translation unit"));
-		if ((f1 && DECL_ARTIFICIAL (f1))
-		    || (f2 && DECL_ARTIFICIAL (f2)))
+		else if ((f1 && DECL_ARTIFICIAL (f1))
+		         || (f2 && DECL_ARTIFICIAL (f2)))
 		  warn_odr (t1, t2, NULL, NULL, warn, warned,
 			    G_("a type with different bases is defined "
 			       "in another translation unit"));
@@ -1408,6 +1574,7 @@ add_type_duplicate (odr_type val, tree t
 {
   bool build_bases = false;
   bool prevail = false;
+  bool odr_must_violate = false;
 
   if (!val->types_set)
     val->types_set = new hash_set<tree>;
@@ -1469,27 +1636,7 @@ add_type_duplicate (odr_type val, tree t
   gcc_assert (in_lto_p);
   vec_safe_push (val->types, type);
 
-  /* First we compare memory layout.  */
-  if (!odr_types_equivalent_p (val->type, type,
-			       !flag_ltrans && !val->odr_violated,
-			       &warned, &visited))
-    {
-      merge = false;
-      odr_violation_reported = true;
-      val->odr_violated = true;
-      if (symtab->dump_file)
-	{
-	  fprintf (symtab->dump_file, "ODR violation\n");
-
-	  print_node (symtab->dump_file, "", val->type, 0);
-	  putc ('\n',symtab->dump_file);
-	  print_node (symtab->dump_file, "", type, 0);
-	  putc ('\n',symtab->dump_file);
-	}
-    }
-
-  /* Next sanity check that bases are the same.  If not, we will end
-     up producing wrong answers.  */
+  /* If both are class types, compare the bases.  */
   if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type)
       && TREE_CODE (val->type) == RECORD_TYPE
       && TREE_CODE (type) == RECORD_TYPE
@@ -1498,25 +1645,28 @@ add_type_duplicate (odr_type val, tree t
       if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
 	  != BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)))
 	{
-	  if (!warned && !val->odr_violated)
+	  if (!flag_ltrans && !warned && !val->odr_violated)
 	    {
 	      tree extra_base;
 	      warn_odr (type, val->type, NULL, NULL, !warned, &warned,
 			"a type with the same name but different "
 			"number of polymorphic bases is "
 			"defined in another translation unit");
-	      if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
-		  > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)))
-		extra_base = BINFO_BASE_BINFO
-			     (TYPE_BINFO (type),
-			      BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)));
-	      else
-		extra_base = BINFO_BASE_BINFO
-			     (TYPE_BINFO (val->type),
-			      BINFO_N_BASE_BINFOS (TYPE_BINFO (type)));
-	      tree extra_base_type = BINFO_TYPE (extra_base);
-	      inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)),
-		      "the extra base is defined here");
+	      if (warned)
+		{
+		  if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
+		      > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)))
+		    extra_base = BINFO_BASE_BINFO
+				 (TYPE_BINFO (type),
+				  BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)));
+		  else
+		    extra_base = BINFO_BASE_BINFO
+				 (TYPE_BINFO (val->type),
+				  BINFO_N_BASE_BINFOS (TYPE_BINFO (type)));
+		  tree extra_base_type = BINFO_TYPE (extra_base);
+		  inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)),
+			  "the extra base is defined here");
+		}
 	    }
 	  base_mismatch = true;
 	}
@@ -1570,10 +1720,10 @@ add_type_duplicate (odr_type val, tree t
 		   but not for TYPE2 we possibly missed a base when recording
 		   VAL->type earlier.
 		   Be sure this does not happen.  */
-		gcc_assert (TYPE_BINFO (type2)
-			    || !polymorphic_type_binfo_p (TYPE_BINFO (type1))
-			    || build_bases
-			    || val->odr_violated);
+		if (TYPE_BINFO (type1)
+		    && polymorphic_type_binfo_p (TYPE_BINFO (type1))
+		    && !build_bases)
+		  odr_must_violate = true;
 	        break;
 	      }
 	    /* One base is polymorphic and the other not.
@@ -1583,38 +1733,15 @@ add_type_duplicate (odr_type val, tree t
 		     && polymorphic_type_binfo_p (TYPE_BINFO (type1))
 		        != polymorphic_type_binfo_p (TYPE_BINFO (type2)))
 	      {
-		gcc_assert (val->odr_violated);
+		if (!warned && !val->odr_violated)
+		  warn_odr (type, val->type, NULL, NULL,
+			    !warned, &warned,
+			    "a base of the type is polymorphic only in one "
+			    "translation unit");
 		base_mismatch = true;
 		break;
 	      }
 	  }
-#ifdef ENABLE_CHECKING
-      /* Sanity check that all bases will be build same way again.  */
-      if (!base_mismatch && val->bases.length ())
-	{
-	  unsigned int num_poly_bases = 0;
-	  unsigned int j;
-
-	  for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
-	    if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
-					     (TYPE_BINFO (type), i)))
-	      num_poly_bases++;
-	  gcc_assert (num_poly_bases == val->bases.length ());
-	  for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type));
-	       i++)
-	    if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
-					   (TYPE_BINFO (type), i)))
-	      {
-		odr_type base = get_odr_type
-				   (BINFO_TYPE
-				      (BINFO_BASE_BINFO (TYPE_BINFO (type),
-							 i)),
-				    true);
-		gcc_assert (val->bases[j] == base);
-		j++;
-	      }
-	}
-#endif
       if (base_mismatch)
 	{
 	  merge = false;
@@ -1633,6 +1760,59 @@ add_type_duplicate (odr_type val, tree t
 	}
     }
 
+  /* Next compare memory layout.  */
+  if (!odr_types_equivalent_p (val->type, type,
+			       !flag_ltrans && !val->odr_violated && !warned,
+			       &warned, &visited))
+    {
+      merge = false;
+      odr_violation_reported = true;
+      val->odr_violated = true;
+      if (symtab->dump_file)
+	{
+	  fprintf (symtab->dump_file, "ODR violation\n");
+
+	  print_node (symtab->dump_file, "", val->type, 0);
+	  putc ('\n',symtab->dump_file);
+	  print_node (symtab->dump_file, "", type, 0);
+	  putc ('\n',symtab->dump_file);
+	}
+    }
+  gcc_assert (val->odr_violated || !odr_must_violate);
+  /* Sanity check that all bases will be build same way again.  */
+#ifdef ENABLE_CHECKING
+  if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type)
+      && TREE_CODE (val->type) == RECORD_TYPE
+      && TREE_CODE (type) == RECORD_TYPE
+      && TYPE_BINFO (val->type) && TYPE_BINFO (type)
+      && !val->odr_violated
+      && !base_mismatch && val->bases.length ())
+    {
+      unsigned int num_poly_bases = 0;
+      unsigned int j;
+
+      for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
+	if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
+					 (TYPE_BINFO (type), i)))
+	  num_poly_bases++;
+      gcc_assert (num_poly_bases == val->bases.length ());
+      for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type));
+	   i++)
+	if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
+				       (TYPE_BINFO (type), i)))
+	  {
+	    odr_type base = get_odr_type
+			       (BINFO_TYPE
+				  (BINFO_BASE_BINFO (TYPE_BINFO (type),
+						     i)),
+				true);
+	    gcc_assert (val->bases[j] == base);
+	    j++;
+	  }
+    }
+#endif
+
+
   /* Regularize things a little.  During LTO same types may come with
      different BINFOs.  Either because their virtual table was
      not merged by tree merging and only later at decl merging or
@@ -1794,7 +1974,7 @@ get_odr_type (tree type, bool insert)
       tree binfo = TYPE_BINFO (type);
       unsigned int i;
 
-      gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type);
+      gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) == type);
   
       val->all_derivations_known = type_all_derivations_known_p (type);
       for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++)
@@ -1803,10 +1983,9 @@ get_odr_type (tree type, bool insert)
 	   determine ODR equivalency of these during LTO.  */
 	if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo, i)))
 	  {
-	    odr_type base = get_odr_type (BINFO_TYPE (BINFO_BASE_BINFO (binfo,
-									i)),
-					  true);
-	    gcc_assert (TYPE_MAIN_VARIANT (base->type) == base->type);
+	    tree base_type = BINFO_TYPE (BINFO_BASE_BINFO (binfo, i));
+	    odr_type base = get_odr_type (base_type, true);
+	    gcc_assert (TYPE_MAIN_VARIANT (base_type) == base_type);
 	    base->derived_types.safe_push (val);
 	    val->bases.safe_push (base);
 	    if (base->id > base_id)
