This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C and C++ PATCH] Properly diagnose ++ or -- on non-lvalue (PR c++/37561)


Hi!

Both C and C++ FE diagnose ++ or -- on non-lvalue only in some cases,
but don't diagnose if an lvalue is casted to a wider integer type.

The problem is in a get_unwidened call, IMHO a left over from the days when
GCC supported the cast-as-lvalue extension.  ATM get_unwidened does
something only for NOP_EXPR/CONVERT_EXPR, for all others it returns the
passed first argument unmodified.  And NOP_EXPR/CONVERT_EXPR is always
non-lvalue and needs to be diagnosed by lvalue_or_else.  This patch
removes the get_unwidened call and as argtype is now always the same as
result_type, also changes all uses of result_type to argtype.

Bootstrapped/regtested on x86_64-linux, fixes g++.old-deja/g++.mike/warn1.C
failures on 64-bit arches and the new tests also pass.

Ok for trunk?

2008-11-14  Jakub Jelinek  <jakub@redhat.com>

	PR c++/37561
	* c-typeck.c (build_unary_op): Don't call get_unwidened.  Use
	argtype instead of result_type.

	* typeck.c (cp_build_unary_op): Don't call get_unwidened.  Use
	argtype instead of result_type.

	* gcc.dg/pr37561.c: New test.
	* g++.dg/other/increment1.C: New test.

--- gcc/c-typeck.c.jj	2008-10-27 08:26:46.000000000 +0100
+++ gcc/c-typeck.c	2008-11-14 17:11:10.000000000 +0100
@@ -3080,9 +3080,7 @@ build_unary_op (location_t location,
 
       {
 	tree inc;
-	tree result_type = TREE_TYPE (arg);
 
-	arg = get_unwidened (arg, 0);
 	argtype = TREE_TYPE (arg);
 
 	/* Compute the increment.  */
@@ -3091,7 +3089,7 @@ build_unary_op (location_t location,
 	  {
 	    /* If pointer target is an undefined struct,
 	       we just cannot know how to do the arithmetic.  */
-	    if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
+	    if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
 	      {
 		if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
 		  error_at (location,
@@ -3100,8 +3098,8 @@ build_unary_op (location_t location,
 		  error_at (location,
 			    "decrement of pointer to unknown structure");
 	      }
-	    else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
-		     || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
+	    else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
+		     || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
 	      {
 		if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
 		  pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
@@ -3111,10 +3109,10 @@ build_unary_op (location_t location,
 			   "wrong type argument to decrement");
 	      }
 
-	    inc = c_size_in_bytes (TREE_TYPE (result_type));
+	    inc = c_size_in_bytes (TREE_TYPE (argtype));
 	    inc = fold_convert (sizetype, inc);
 	  }
-	else if (FRACT_MODE_P (TYPE_MODE (result_type)))
+	else if (FRACT_MODE_P (TYPE_MODE (argtype)))
 	  {
 	    /* For signed fract types, we invert ++ to -- or
 	       -- to ++, and change inc from 1 to -1, because
@@ -3161,7 +3159,6 @@ build_unary_op (location_t location,
 	else
 	  val = build2 (code, TREE_TYPE (arg), arg, inc);
 	TREE_SIDE_EFFECTS (val) = 1;
-	val = convert (result_type, val);
 	if (TREE_CODE (val) != code)
 	  TREE_NO_WARNING (val) = 1;
 	ret = val;
--- gcc/cp/typeck.c.jj	2008-11-13 15:02:54.000000000 +0100
+++ gcc/cp/typeck.c	2008-11-14 17:21:15.000000000 +0100
@@ -4348,12 +4348,8 @@ cp_build_unary_op (enum tree_code code, 
 
       {
 	tree inc;
-	tree declared_type;
-	tree result_type = TREE_TYPE (arg);
+	tree declared_type = unlowered_expr_type (arg);
 
-	declared_type = unlowered_expr_type (arg);
-
-	arg = get_unwidened (arg, 0);
 	argtype = TREE_TYPE (arg);
 
 	/* ARM $5.2.5 last annotation says this should be forbidden.  */
@@ -4427,7 +4423,7 @@ cp_build_unary_op (enum tree_code code, 
 	  val = build2 (code, TREE_TYPE (arg), arg, inc);
 
 	TREE_SIDE_EFFECTS (val) = 1;
-	return cp_convert (result_type, val);
+	return val;
       }
 
     case ADDR_EXPR:
--- gcc/testsuite/gcc.dg/pr37561.c.jj	2008-11-14 17:35:51.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr37561.c	2008-11-14 18:06:36.000000000 +0100
@@ -0,0 +1,14 @@
+/* PR c++/37561 */
+/* { dg-do compile { target { ilp32 || lp64 } } } */
+
+__PTRDIFF_TYPE__ p;
+char q;
+
+void
+foo ()
+{
+  ((char *) p)++;	/* { dg-error "lvalue" } */
+  ((char *) q)++;	/* { dg-error "lvalue" } */
+}
+
+/* { dg-warning "cast to pointer from integer of different size" "" { target *-*-* } 11 } */
--- gcc/testsuite/g++.dg/other/increment1.C.jj	2008-11-14 18:07:24.000000000 +0100
+++ gcc/testsuite/g++.dg/other/increment1.C	2008-11-14 18:07:43.000000000 +0100
@@ -0,0 +1,12 @@
+// PR c++/37561
+// { dg-do compile }
+
+__PTRDIFF_TYPE__ p;
+char q;
+
+void
+foo ()
+{
+  ((char *) p)++;	// { dg-error "lvalue" }
+  ((char *) q)++;	// { dg-error "lvalue" }
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]