re PR c/48418 (Bit shift operator >>=)
authorJakub Jelinek <jakub@redhat.com>
Wed, 9 Jan 2013 14:51:09 +0000 (15:51 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 9 Jan 2013 14:51:09 +0000 (15:51 +0100)
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
gcc/c-family/c-common.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr48418.c [new file with mode: 0644]

index a743517..84addf7 100644 (file)
@@ -1,3 +1,11 @@
+2013-01-09  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <polacek@redhat.com>
 
        PR c/55570
index 0127513..7248393 100644 (file)
@@ -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:
index 4658353..d67a3c4 100644 (file)
@@ -1,3 +1,10 @@
+2013-01-09  Jakub Jelinek  <jakub@redhat.com>
+
+       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  <paolo.carlini@oracle.com>
 
        PR c++/55801
index 66fb33a..8642135 100644 (file)
@@ -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)
index f300905..5b95a47 100644 (file)
@@ -1,3 +1,8 @@
+2013-01-09  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c/48418
+       * c-c++-common/pr48418.c: New test.
+
 2013-01-09  Paolo Carlini  <paolo.carlini@oracle.com>
 
        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 (file)
index 0000000..95ff855
--- /dev/null
@@ -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;
+}