public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C/C++ PATCH] shift with negative or too big count warning (PR c/48418)
@ 2013-01-08 20:04 Jakub Jelinek
  2013-01-08 22:33 ` Joseph S. Myers
  2013-01-09 14:45 ` Jason Merrill
  0 siblings, 2 replies; 3+ messages in thread
From: Jakub Jelinek @ 2013-01-08 20:04 UTC (permalink / raw)
  To: Joseph S. Myers, Jason Merrill; +Cc: gcc-patches

Hi!

As discussed in the PR, on the following testcase we've regressed with the
introduction of c_fully_fold, when the C FE normally warns the argument
isn't folded yet.  Fixed by also warning in c_fully_fold_internal, if before
that function the shift count wasn't INTEGER_CST and after it it is.

The testcase also revealed a regression on the C++ FE side, caused by
SIZEOF_EXPR folding deferral.

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

2013-01-08  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.

	* 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.

--- gcc/c-family/c-common.c.jj	2012-12-31 15:05:45.000000000 +0100
+++ gcc/c-family/c-common.c	2013-01-08 15:15:47.019347593 +0100
@@ -1269,6 +1269,25 @@ c_fully_fold_internal (tree expr, bool i
 	  && !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
+				 ? "left shift count is negative"
+				 : "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
+				 ? "left shift count >= width of type"
+				 : "right shift count >= width of type"));
+	}
       goto out;
 
     case INDIRECT_REF:
--- gcc/cp/typeck.c.jj	2013-01-07 14:14:44.000000000 +0100
+++ gcc/cp/typeck.c	2013-01-08 15:30:20.202388635 +0100
@@ -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)
--- gcc/testsuite/c-c++-common/pr48418.c.jj	2013-01-08 15:25:36.501003969 +0100
+++ gcc/testsuite/c-c++-common/pr48418.c	2013-01-08 15:21:54.000000000 +0100
@@ -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;
+}

	Jakub

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [C/C++ PATCH] shift with negative or too big count warning (PR c/48418)
  2013-01-08 20:04 [C/C++ PATCH] shift with negative or too big count warning (PR c/48418) Jakub Jelinek
@ 2013-01-08 22:33 ` Joseph S. Myers
  2013-01-09 14:45 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Joseph S. Myers @ 2013-01-08 22:33 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Jason Merrill, gcc-patches

On Tue, 8 Jan 2013, Jakub Jelinek wrote:

> Hi!
> 
> As discussed in the PR, on the following testcase we've regressed with the
> introduction of c_fully_fold, when the C FE normally warns the argument
> isn't folded yet.  Fixed by also warning in c_fully_fold_internal, if before
> that function the shift count wasn't INTEGER_CST and after it it is.
> 
> The testcase also revealed a regression on the C++ FE side, caused by
> SIZEOF_EXPR folding deferral.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

The C front-end changes are OK.  Properly diagnostic messages inside ? : 
conditionals should be marked up with G_() to ensure that both cases are 
extracted for translation, though in this case it doesn't matter much 
given that the message wording should stay identical to other copies of 
the same messages.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [C/C++ PATCH] shift with negative or too big count warning (PR c/48418)
  2013-01-08 20:04 [C/C++ PATCH] shift with negative or too big count warning (PR c/48418) Jakub Jelinek
  2013-01-08 22:33 ` Joseph S. Myers
@ 2013-01-09 14:45 ` Jason Merrill
  1 sibling, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2013-01-09 14:45 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Joseph S. Myers, gcc-patches

The C++ change is OK.

Jason

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2013-01-09 14:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-08 20:04 [C/C++ PATCH] shift with negative or too big count warning (PR c/48418) Jakub Jelinek
2013-01-08 22:33 ` Joseph S. Myers
2013-01-09 14:45 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).