Commit 541e35a6 by Marek Polacek Committed by Marek Polacek

re PR c/63862 (C frontend converts shift-count to int while standard wants integer promotions)

	PR c/63862
c-family/
	* c-ubsan.c (ubsan_instrument_shift): Change the type of a MINUS_EXPR
	to op1_utype.
	* c-gimplify.c (c_gimplify_expr): Convert right operand of a shift
	expression to unsigned_type_node.
c/
	* c-typeck.c (build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
	convert the right operand to integer type.
cp/
	* typeck.c (cp_build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
	convert the right operand to integer type.
testsuite/
	* gcc.c-torture/execute/shiftopt-1.c: Don't XFAIL anymore.
	* c-c++-common/ubsan/shift-7.c: New test.

From-SVN: r218142
parent 7e015fce
2014-11-28 Marek Polacek <polacek@redhat.com>
PR c/63862
* c-ubsan.c (ubsan_instrument_shift): Change the type of a MINUS_EXPR
to op1_utype.
* c-gimplify.c (c_gimplify_expr): Convert right operand of a shift
expression to unsigned_type_node.
2014-11-20 Mark Wielaard <mjw@redhat.com> 2014-11-20 Mark Wielaard <mjw@redhat.com>
PR debug/38757 PR debug/38757
......
...@@ -242,6 +242,24 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, ...@@ -242,6 +242,24 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
switch (code) switch (code)
{ {
case LSHIFT_EXPR:
case RSHIFT_EXPR:
{
/* We used to convert the right operand of a shift-expression
to an integer_type_node in the FEs. But it is unnecessary
and not desirable for diagnostics and sanitizers. We keep
this here to not pessimize the code, but we convert to an
unsigned type, because negative shift counts are undefined
anyway.
We should get rid of this conversion when we have a proper
type demotion/promotion pass. */
tree *op1_p = &TREE_OPERAND (*expr_p, 1);
if (TREE_CODE (TREE_TYPE (*op1_p)) != VECTOR_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)) != unsigned_type_node)
*op1_p = convert (unsigned_type_node, *op1_p);
break;
}
case DECL_EXPR: case DECL_EXPR:
/* This is handled mostly by gimplify.c, but we have to deal with /* This is handled mostly by gimplify.c, but we have to deal with
not warning about int x = x; as it is a GCC extension to turn off not warning about int x = x; as it is a GCC extension to turn off
......
...@@ -151,7 +151,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, ...@@ -151,7 +151,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code,
&& !TYPE_UNSIGNED (type0) && !TYPE_UNSIGNED (type0)
&& flag_isoc99) && flag_isoc99)
{ {
tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1, tree x = fold_build2 (MINUS_EXPR, op1_utype, uprecm1,
fold_convert (op1_utype, op1)); fold_convert (op1_utype, op1));
tt = fold_convert_loc (loc, unsigned_type_for (type0), op0); tt = fold_convert_loc (loc, unsigned_type_for (type0), op0);
tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x); tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x);
......
2014-11-28 Marek Polacek <polacek@redhat.com>
PR c/63862
* c-typeck.c (build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
convert the right operand to integer type.
2014-11-25 Marek Polacek <polacek@redhat.com> 2014-11-25 Marek Polacek <polacek@redhat.com>
PR c/63877 PR c/63877
......
...@@ -10513,11 +10513,6 @@ build_binary_op (location_t location, enum tree_code code, ...@@ -10513,11 +10513,6 @@ build_binary_op (location_t location, enum tree_code code,
/* Use the type of the value to be shifted. */ /* Use the type of the value to be shifted. */
result_type = type0; result_type = type0;
/* Convert the non vector shift-count to an integer, regardless
of size of value being shifted. */
if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */ /* Avoid converting op1 to result_type later. */
converted = 1; converted = 1;
} }
...@@ -10563,11 +10558,6 @@ build_binary_op (location_t location, enum tree_code code, ...@@ -10563,11 +10558,6 @@ build_binary_op (location_t location, enum tree_code code,
/* Use the type of the value to be shifted. */ /* Use the type of the value to be shifted. */
result_type = type0; result_type = type0;
/* Convert the non vector shift-count to an integer, regardless
of size of value being shifted. */
if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */ /* Avoid converting op1 to result_type later. */
converted = 1; converted = 1;
} }
......
2014-11-28 Marek Polacek <polacek@redhat.com>
PR c/63862
* typeck.c (cp_build_binary_op) <RSHIFT_EXPR, LSHIFT_EXPR>: Don't
convert the right operand to integer type.
2014-11-27 Kai Tietz <ktietz@redhat.com> 2014-11-27 Kai Tietz <ktietz@redhat.com>
PR c++/63904 PR c++/63904
......
...@@ -4295,10 +4295,6 @@ cp_build_binary_op (location_t location, ...@@ -4295,10 +4295,6 @@ cp_build_binary_op (location_t location,
"right shift count >= width of type"); "right shift count >= width of type");
} }
} }
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = cp_convert (integer_type_node, op1, complain);
/* Avoid converting op1 to result_type later. */ /* Avoid converting op1 to result_type later. */
converted = 1; converted = 1;
} }
...@@ -4344,10 +4340,6 @@ cp_build_binary_op (location_t location, ...@@ -4344,10 +4340,6 @@ cp_build_binary_op (location_t location,
"left shift count >= width of type"); "left shift count >= width of type");
} }
} }
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
op1 = cp_convert (integer_type_node, op1, complain);
/* Avoid converting op1 to result_type later. */ /* Avoid converting op1 to result_type later. */
converted = 1; converted = 1;
} }
......
2014-11-28 Marek Polacek <polacek@redhat.com>
PR c/63862
* gcc.c-torture/execute/shiftopt-1.c: Don't XFAIL anymore.
* c-c++-common/ubsan/shift-7.c: New test.
2014-11-28 Richard Biener <rguenther@suse.de> 2014-11-28 Richard Biener <rguenther@suse.de>
PR middle-end/64084 PR middle-end/64084
......
/* PR c/63862 */
/* { dg-do run } */
/* { dg-options "-fsanitize=undefined" } */
unsigned long long int __attribute__ ((noinline, noclone))
foo (unsigned long long int i, unsigned long long int j)
{
asm ("");
return i >> j;
}
unsigned long long int __attribute__ ((noinline, noclone))
bar (unsigned long long int i, unsigned long long int j)
{
asm ("");
return i << j;
}
int
main ()
{
foo (1ULL, 0x100000000ULL);
bar (1ULL, 0x100000000ULL);
}
/* { dg-output "shift exponent 4294967296 is too large for \[^\n\r]*-bit type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output "\[^\n\r]*shift exponent 4294967296 is too large for \[^\n\r]*-bit type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */
...@@ -22,16 +22,11 @@ utest (unsigned int x) ...@@ -22,16 +22,11 @@ utest (unsigned int x)
if (0 >> x != 0) if (0 >> x != 0)
link_error (); link_error ();
/* XFAIL: the C frontend converts the shift amount to 'int'
thus we get -1 >> (int)x which means the shift amount may
be negative. See PR63862. */
#if 0
if (-1 >> x != -1) if (-1 >> x != -1)
link_error (); link_error ();
if (~0 >> x != ~0) if (~0 >> x != ~0)
link_error (); link_error ();
#endif
} }
void void
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment