Properly use TYPE_MAIN_VARIANT in warn_types_mismatch.

Message ID 00203ffd-b43a-231f-0aaf-200c377d63ad@suse.cz
State New
Headers show
Series
  • Properly use TYPE_MAIN_VARIANT in warn_types_mismatch.
Related show

Commit Message

Martin Liška Nov. 27, 2019, 2:19 p.m.
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  <mliska@suse.cz>

	PR lto/92609
	* ipa-devirt.c (warn_types_mismatch): Use TYPE_MAIN_VARIANT
	consistently.

gcc/testsuite/ChangeLog:

2019-11-27  Martin Liska  <mliska@suse.cz>

	PR lto/92609
	* g++.dg/lto/pr92609_0.C: New test.
	* g++.dg/lto/pr92609_1.C: New test.
---
  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

Comments

Jan Hubicka Nov. 27, 2019, 4 p.m. | #1
> 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  <mliska@suse.cz>

> 

> 	PR lto/92609

> 	* ipa-devirt.c (warn_types_mismatch): Use TYPE_MAIN_VARIANT

> 	consistently.

> 

> gcc/testsuite/ChangeLog:

> 

> 2019-11-27  Martin Liska  <mliska@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() {}

>

Patch

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() {}