> Hi. > > The patch is attempt to fix ICE which I see in ODR violation warning. > I think the proper fix is to use TYPE_MAIN_VARIANT(t1) instead of t1 > in the problematic condition. > > Patch can bootstrap on x86_64-linux-gnu and survives regression tests. > > Ready to be installed? > Thanks, > Martin > > gcc/ChangeLog: > > 2019-11-27 Martin Liska <mli...@suse.cz> > > PR lto/92609 > * ipa-devirt.c (warn_types_mismatch): Use TYPE_MAIN_VARIANT > consistently. > > gcc/testsuite/ChangeLog: > > 2019-11-27 Martin Liska <mli...@suse.cz> > > PR lto/92609 > * g++.dg/lto/pr92609_0.C: New test. > * g++.dg/lto/pr92609_1.C: New test. OK, thanks! Honza > --- > gcc/ipa-devirt.c | 25 ++++---- > gcc/testsuite/g++.dg/lto/pr92609_0.C | 88 ++++++++++++++++++++++++++++ > gcc/testsuite/g++.dg/lto/pr92609_1.C | 58 ++++++++++++++++++ > 3 files changed, 159 insertions(+), 12 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/lto/pr92609_0.C > create mode 100644 gcc/testsuite/g++.dg/lto/pr92609_1.C > >
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c > index c158d3c968d..0b2475ca292 100644 > --- a/gcc/ipa-devirt.c > +++ b/gcc/ipa-devirt.c > @@ -986,21 +986,24 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, > location_t loc2) > > /* It is a quite common bug to reference anonymous namespace type in > non-anonymous namespace class. */ > - 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)))) > + 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 (TYPE_MAIN_VARIANT (t1)) > - || !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (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) > - && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL); > - tree n1 = TYPE_NAME (t1); > - tree n2 = TYPE_NAME (t2) ? TYPE_NAME (t2) : NULL; > + 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); > @@ -1023,8 +1026,6 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, > location_t loc2) > "the incompatible type defined in another translation unit"); > return; > } > - tree mt1 = TYPE_MAIN_VARIANT (t1); > - tree mt2 = TYPE_MAIN_VARIANT (t2); > /* 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. */ > diff --git a/gcc/testsuite/g++.dg/lto/pr92609_0.C > b/gcc/testsuite/g++.dg/lto/pr92609_0.C > new file mode 100644 > index 00000000000..3cce1811d1e > --- /dev/null > +++ b/gcc/testsuite/g++.dg/lto/pr92609_0.C > @@ -0,0 +1,88 @@ > +// PR lto/92609 > +// { dg-lto-do link } > +// { dg-lto-options { { -fPIC -flto } } } > +// { dg-require-effective-target shared } > +// { dg-require-effective-target fpic } > +// { dg-extra-ld-options "-shared" } > + > +namespace std { > +inline namespace __cxx11 {} > +template < typename _Default > struct __detector { using type = _Default; }; > +template < typename _Default, template < typename > class > > +using __detected_or = __detector< _Default >; > +template < typename _Default, template < typename > class _Op > > +using __detected_or_t = typename __detected_or< _Default, _Op >::type; > +template < typename > class allocator; > +template < class > struct char_traits; > +namespace __cxx11 { > +template < typename _CharT, typename = char_traits< _CharT >, > + typename = allocator< _CharT > > > +class basic_string; > +} > +struct __allocator_traits_base { > + template < typename _Tp > using __pointer = typename _Tp::pointer; > +}; > +struct allocator_traits : __allocator_traits_base { > + using pointer = __detected_or_t< char *, __pointer >; > +}; > +} // std > +struct rebind { > + typedef std::allocator_traits other; > +}; > +namespace std { > +namespace __cxx11 { > +template < typename, typename, typename > class basic_string { > + struct _Alloc_hider { > + rebind::other::pointer _M_p; > + } _M_dataplus; > + unsigned long _M_string_length; > + enum { _S_local_capacity = 15 }; > + union { > + char _M_local_buf[_S_local_capacity + 1]; > + unsigned long _M_allocated_capacity; > + }; > +}; > +} // __cxx11 > +template < typename _Tp > class __uniq_ptr_impl { > + template < typename _Up > struct _Ptr { using type = _Up *; }; > + > +public: > + using pointer = typename _Ptr< _Tp >::type; > +}; > +template < typename _Tp > class unique_ptr { > +public: > + using pointer = typename __uniq_ptr_impl< _Tp >::pointer; > + unique_ptr(pointer); > +}; > +} // std > +class wxRefCounter; > +class wxObject { > + virtual wxRefCounter CreateRefData(); > + wxRefCounter *m_refData; > +}; > +class wxGDIObject : wxObject {}; > +class wxFontBase : wxGDIObject {}; > +class wxFont : wxFontBase {}; > +class VisualTool { > +protected: > + VisualTool(int *, int *); > +}; > +class OpenGLText; > +class VisualToolCross : VisualTool { > + std::unique_ptr< OpenGLText > gl_text; > + VisualToolCross(); > +}; > +class OpenGLText { // { dg-lto-warning "7: type 'struct OpenGLText' violates > the C\\+\\+ One Definition Rule" } > + float r, g, b, a; > + int fontSize; > + bool fontBold; > + bool fontItalics; > + std::basic_string< char > fontFace; > + wxFont font; > + int glyphs; > +}; > +int VisualToolCross_parent; > +int VisualToolCross_context; > +VisualToolCross::VisualToolCross() > + : VisualTool(&VisualToolCross_parent, &VisualToolCross_context), > + gl_text(0) {} > diff --git a/gcc/testsuite/g++.dg/lto/pr92609_1.C > b/gcc/testsuite/g++.dg/lto/pr92609_1.C > new file mode 100644 > index 00000000000..4c65a6a4600 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/lto/pr92609_1.C > @@ -0,0 +1,58 @@ > +namespace std { > +inline namespace __cxx11 {} > +template < typename _Default > struct __detector { using type = _Default; }; > +template < typename _Default, template < typename > class > > +using __detected_or = __detector< _Default >; > +template < typename _Default, template < typename > class _Op > > +using __detected_or_t = typename __detected_or< _Default, _Op >::type; > +template < typename > class allocator; > +template < class > struct char_traits; > +namespace __cxx11 { > +template < typename _CharT, typename = char_traits< _CharT >, > + typename = allocator< _CharT > > > +class basic_string; > +} > +struct __allocator_traits_base { > + template < typename _Tp > using __pointer = typename _Tp::pointer; > +}; > +struct allocator_traits : __allocator_traits_base { > + using pointer = __detected_or_t< char *, __pointer >; > +}; > +namespace __cxx11 { > +template < typename, typename, typename > class basic_string { > + struct _Alloc_hider { > + allocator_traits::pointer _M_p; > + } _M_dataplus; > + unsigned long _M_string_length; > + enum { _S_local_capacity = 15 }; > + union { > + char _M_local_buf[_S_local_capacity + 1]; > + unsigned long _M_allocated_capacity; > + }; > +}; > +} // __cxx11 > +} // std > +class wxRefCounter; > +class wxObject { > + virtual int GetClassInfo(); > + wxRefCounter *m_refData; > +}; > +class wxGDIObject : wxObject {}; > +class wxFontBase : wxGDIObject {}; > +class wxFont : wxFontBase {}; > +template < class > class map {}; > +namespace { > +struct OpenGLTextGlyph; > +} > +typedef map< OpenGLTextGlyph > glyphMap; > +class OpenGLText { > + float r, g, b, a; > + int fontSize; > + bool fontBold; > + bool fontItalics; > + std::basic_string< char > fontFace; > + wxFont font; > + glyphMap glyphs; > + OpenGLText(); > +}; > +OpenGLText::OpenGLText() {} >