From cc83c823a2be3dc48f011c07c9e407af0a7974c0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 9 Jan 2013 15:51:09 +0100 Subject: [PATCH] re PR c/48418 (Bit shift operator >>=) PR c/48418 * c-common.c (c_fully_fold_internal): Warn for LSHIFT_EXPR and RSHIFT_EXPR, if orig_op1 isn't INTEGER_CST, op1 is INTEGER_CST and is either negative or bigger or equal to type precision of the first operand. * typeck.c (cp_build_binary_op): For LSHIFT_EXPR and RSHIFT_EXPR, call maybe_constant_value for the negative or too big shift count warnings. * c-c++-common/pr48418.c: New test. From-SVN: r195051 --- gcc/c-family/ChangeLog | 8 ++++++++ gcc/c-family/c-common.c | 23 +++++++++++++++++++++-- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/typeck.c | 21 ++++++++++++++------- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/c-c++-common/pr48418.c | 20 ++++++++++++++++++++ 6 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/pr48418.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index a743517..84addf7 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2013-01-09 Jakub Jelinek + + PR c/48418 + * c-common.c (c_fully_fold_internal): Warn for LSHIFT_EXPR and + RSHIFT_EXPR, if orig_op1 isn't INTEGER_CST, op1 is INTEGER_CST + and is either negative or bigger or equal to type precision + of the first operand. + 2012-12-03 Marek Polacek PR c/55570 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 0127513..7248393 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1,7 +1,7 @@ /* Subroutines shared by all languages that are variants of C. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 - Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, + 2013 Free Software Foundation, Inc. This file is part of GCC. @@ -1269,6 +1269,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, && !TREE_OVERFLOW_P (op0) && !TREE_OVERFLOW_P (op1)) overflow_warning (EXPR_LOCATION (expr), ret); + if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR) + && TREE_CODE (orig_op1) != INTEGER_CST + && TREE_CODE (op1) == INTEGER_CST + && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE) + && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE + && c_inhibit_evaluation_warnings == 0) + { + if (tree_int_cst_sgn (op1) < 0) + warning_at (loc, 0, (code == LSHIFT_EXPR + ? G_("left shift count is negative") + : G_("right shift count is negative"))); + else if (compare_tree_int (op1, + TYPE_PRECISION (TREE_TYPE (orig_op0))) + >= 0) + warning_at (loc, 0, (code == LSHIFT_EXPR + ? G_("left shift count >= width of type") + : G_("right shift count >= width of type"))); + } goto out; case INDIRECT_REF: diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4658353..d67a3c4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2013-01-09 Jakub Jelinek + + PR c/48418 + * typeck.c (cp_build_binary_op): For LSHIFT_EXPR and RSHIFT_EXPR, + call maybe_constant_value for the negative or too big shift + count warnings. + 2013-01-09 Paolo Carlini PR c++/55801 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 66fb33a..8642135 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1,7 +1,7 @@ /* Build expressions with type checking for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 2012 + 2011, 2012, 2013 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -4095,10 +4095,13 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { + tree const_op1 = maybe_constant_value (op1); + if (TREE_CODE (const_op1) != INTEGER_CST) + const_op1 = op1; result_type = type0; - if (TREE_CODE (op1) == INTEGER_CST) + if (TREE_CODE (const_op1) == INTEGER_CST) { - if (tree_int_cst_lt (op1, integer_zero_node)) + if (tree_int_cst_lt (const_op1, integer_zero_node)) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) @@ -4106,7 +4109,7 @@ cp_build_binary_op (location_t location, } else { - if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0 + if (compare_tree_int (const_op1, TYPE_PRECISION (type0)) >= 0 && (complain & tf_warning) && c_inhibit_evaluation_warnings == 0) warning (0, "right shift count >= width of type"); @@ -4138,16 +4141,20 @@ cp_build_binary_op (location_t location, } else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE) { + tree const_op1 = maybe_constant_value (op1); + if (TREE_CODE (const_op1) != INTEGER_CST) + const_op1 = op1; result_type = type0; - if (TREE_CODE (op1) == INTEGER_CST) + if (TREE_CODE (const_op1) == INTEGER_CST) { - if (tree_int_cst_lt (op1, integer_zero_node)) + if (tree_int_cst_lt (const_op1, integer_zero_node)) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) warning (0, "left shift count is negative"); } - else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + else if (compare_tree_int (const_op1, + TYPE_PRECISION (type0)) >= 0) { if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f300905..5b95a47 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-01-09 Jakub Jelinek + + PR c/48418 + * c-c++-common/pr48418.c: New test. + 2013-01-09 Paolo Carlini PR c++/55801 diff --git a/gcc/testsuite/c-c++-common/pr48418.c b/gcc/testsuite/c-c++-common/pr48418.c new file mode 100644 index 0000000..95ff855 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr48418.c @@ -0,0 +1,20 @@ +/* PR c/48418 */ +/* { dg-do compile } */ +/* { dg-options "-Wall -O2" } */ + +int +foo (int x) +{ + const int a = sizeof (int) * __CHAR_BIT__; + const int b = -7; + int c = 0; + c += x << a; /* { dg-warning "left shift count >= width of type" } */ + c += x << b; /* { dg-warning "left shift count is negative" } */ + c += x << (sizeof (int) * __CHAR_BIT__); /* { dg-warning "left shift count >= width of type" } */ + c += x << -7; /* { dg-warning "left shift count is negative" } */ + c += x >> a; /* { dg-warning "right shift count >= width of type" } */ + c += x >> b; /* { dg-warning "right shift count is negative" } */ + c += x >> (sizeof (int) * __CHAR_BIT__); /* { dg-warning "right shift count >= width of type" } */ + c += x >> -7; /* { dg-warning "right shift count is negative" } */ + return c; +} -- 2.7.4