Fix C FE ICE with vector comparison (PR c/84999)

Message ID 20180321202829.GO8577@tucnak
State New
Headers show
Series
  • Fix C FE ICE with vector comparison (PR c/84999)
Related show

Commit Message

Jakub Jelinek March 21, 2018, 8:28 p.m.
Hi!

On ia32, we don't support __int128, nor mode (TI) integers, but we do
support 128-bit __float128 and (generic) vectors containing it.  The result
of a comparison of such vectors is supposed to be integral vector with the
same element size, but we really don't want to allow one in this case,
it would be a loophole for full support of __int128/mode(TI), just do:
typedef __float128 V __attribute__ ((__vector_size__ (2 * sizeof (__float128))));
extern V v;
typedef typeof ((v != 0)[0]) my_int128;
and suddenly you have __int128.

The C++ errors out in this case, you can use such floating point vectors,
but can't use them in comparisons, the C FE instead just segfaulted.

Fixed thusly, making the C FE consistent with what C++ FE does,
bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-03-21  Jakub Jelinek  <jakub@redhat.com>

	PR c/84999
	* c-typeck.c (build_binary_op): If c_common_type_for_size fails when
	building vector comparison, diagnose it and return error_mark_node.

	* c-c++-common/pr84999.c: New test.


	Jakub

Comments

Joseph Myers March 21, 2018, 9:33 p.m. | #1
On Wed, 21 Mar 2018, Jakub Jelinek wrote:

> Hi!

> 

> On ia32, we don't support __int128, nor mode (TI) integers, but we do

> support 128-bit __float128 and (generic) vectors containing it.  The result

> of a comparison of such vectors is supposed to be integral vector with the

> same element size, but we really don't want to allow one in this case,

> it would be a loophole for full support of __int128/mode(TI), just do:

> typedef __float128 V __attribute__ ((__vector_size__ (2 * sizeof (__float128))));

> extern V v;

> typedef typeof ((v != 0)[0]) my_int128;

> and suddenly you have __int128.

> 

> The C++ errors out in this case, you can use such floating point vectors,

> but can't use them in comparisons, the C FE instead just segfaulted.

> 

> Fixed thusly, making the C FE consistent with what C++ FE does,

> bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

Patch

--- gcc/c/c-typeck.c.jj	2018-03-15 08:37:11.640779243 +0100
+++ gcc/c/c-typeck.c	2018-03-21 14:01:25.088183657 +0100
@@ -11504,6 +11504,13 @@  build_binary_op (location_t location, en
           intt = c_common_type_for_size (GET_MODE_BITSIZE
 					 (SCALAR_TYPE_MODE
 					  (TREE_TYPE (type0))), 0);
+	  if (!intt)
+	    {
+	      error_at (location, "could not find an integer type "
+				  "of the same size as %qT",
+			TREE_TYPE (type0));
+	      return error_mark_node;
+	    }
           result_type = build_opaque_vector_type (intt,
 						  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
@@ -11665,6 +11672,13 @@  build_binary_op (location_t location, en
           intt = c_common_type_for_size (GET_MODE_BITSIZE
 					 (SCALAR_TYPE_MODE
 					  (TREE_TYPE (type0))), 0);
+	  if (!intt)
+	    {
+	      error_at (location, "could not find an integer type "
+				  "of the same size as %qT",
+			TREE_TYPE (type0));
+	      return error_mark_node;
+	    }
           result_type = build_opaque_vector_type (intt,
 						  TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
--- gcc/testsuite/c-c++-common/pr84999.c.jj	2018-03-21 14:34:12.819329771 +0100
+++ gcc/testsuite/c-c++-common/pr84999.c	2018-03-21 14:32:37.816361905 +0100
@@ -0,0 +1,12 @@ 
+/* PR c/84999 */
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-options "" } */
+
+typedef __float128 V __attribute__ ((__vector_size__ (2 * sizeof (__float128))));
+V a;
+typeof (a != 0) b;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */
+typeof (a == 0) c;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */
+typeof (a < 0) d;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */
+typeof (a <= 0) e;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */
+typeof (a > 0) f;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */
+typeof (a >= 0) g;	/* { dg-error "could not find an integer type of the same size as" "" { target ia32 } } */