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]

Correct checks for assignments to read-only data (PR 27676)


This patch fixes PR 27676, reporting that GCC wrongly gives an error
for assignments to elements of string literals.  Although such
assignments yield undefined behavior at runtime, string literals are
not const-qualified in C and so this code must be accepted.

The original motivation for making assignments to readonly locations
(most of which are const-qualified and so do not need the assignments
to be accepted) hard errors was problems such assignments caused later
in the optimizers.  If this case proves to cause problems we can
arrange for traps to be generated (making sure to preserve any side
effects of the lvalue and the RHS of the assignment that take place
before the undefined behavior), but I don't particularly expect any
new problems given that cases can easily be constructed where such an
assignment becomes visible to the optimizers but isn't in simple
enough form for the lvalue to be seen as readonly in the front end.

Bootstrapped with no regressions on i686-pc-linux-gnu.  Applied to
mainline.

As this was the last known target-independent C90 conformance bug
(i.e. the last one filed in Bugzilla and marked as a dependency of PR
16620, or otherwise known to me - and I did look through "c" and
"preprocessor" bug recently looking for any conformance bugs I'd
previously missed the dependency marking on), I'll now close PR 16620.
Such conformance bugs as are found in future should still be marked as
dependencies of 16620, but I don't think it will be worth reopening
that bug for them; I expect they'll generally be C99 conformance bugs
as well and so should also be marked as dependencies of 16989.

(If you take GCC and glibc together as the GNU hosted C
implementation, there are some technical issues on the glibc side
meaning the combination doesn't provide a fully conforming C90 library
implementation.)

2009-04-18  Joseph Myers  <joseph@codesourcery.com>

	PR c/27676
	* c-typeck.c (readonly_warning): new.
	(build_unary_op, build_modify_expr): Use readonly_warning for
	storing into something readonly but not const-qualified.

testsuite:
2009-04-18  Joseph Myers  <joseph@codesourcery.com>

	PR c/27676
	* gcc.dg/lvalue-5.c: New test.

Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 146324)
+++ gcc/c-typeck.c	(working copy)
@@ -107,6 +107,7 @@ static void set_nonincremental_init (voi
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
 static void readonly_error (tree, enum lvalue_use);
+static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (const_tree, enum lvalue_use);
 static int lvalue_p (const_tree);
 static void record_maybe_used_decl (tree);
@@ -3323,7 +3324,7 @@ build_unary_op (location_t location,
 	  }
 
 	/* Report a read-only lvalue.  */
-	if (TREE_READONLY (arg))
+	if (TYPE_READONLY (argtype))
 	  {
 	    readonly_error (arg,
 			    ((code == PREINCREMENT_EXPR
@@ -3331,6 +3332,11 @@ build_unary_op (location_t location,
 			     ? lv_increment : lv_decrement));
 	    return error_mark_node;
 	  }
+	else if (TREE_READONLY (arg))
+	  readonly_warning (arg,
+			    ((code == PREINCREMENT_EXPR
+			      || code == POSTINCREMENT_EXPR)
+			     ? lv_increment : lv_decrement));
 
 	if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
 	  val = boolean_increment (code, arg);
@@ -3531,6 +3537,29 @@ readonly_error (tree arg, enum lvalue_us
 	   arg);
 }
 
+/* Give a warning for storing in something that is read-only in GCC
+   terms but not const in ISO C terms.  */
+
+static void
+readonly_warning (tree arg, enum lvalue_use use)
+{
+  switch (use)
+    {
+    case lv_assign:
+      warning (0, "assignment of read-only location %qE", arg);
+      break;
+    case lv_increment:
+      warning (0, "increment of read-only location %qE", arg);
+      break;
+    case lv_decrement:
+      warning (0, "decrement of read-only location %qE", arg);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  return;
+}
+
 
 /* Return nonzero if REF is an lvalue valid for this language;
    otherwise, print an error message and return zero.  USE says
@@ -4283,7 +4312,7 @@ build_modify_expr (location_t location,
 
   /* Give an error for storing in something that is 'const'.  */
 
-  if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
+  if (TYPE_READONLY (lhstype)
       || ((TREE_CODE (lhstype) == RECORD_TYPE
 	   || TREE_CODE (lhstype) == UNION_TYPE)
 	  && C_TYPE_FIELDS_READONLY (lhstype)))
@@ -4291,6 +4320,8 @@ build_modify_expr (location_t location,
       readonly_error (lhs, lv_assign);
       return error_mark_node;
     }
+  else if (TREE_READONLY (lhs))
+    readonly_warning (lhs, lv_assign);
 
   /* If storing into a structure or union member,
      it has probably been given type `int'.
Index: gcc/testsuite/gcc.dg/lvalue-5.c
===================================================================
--- gcc/testsuite/gcc.dg/lvalue-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/lvalue-5.c	(revision 0)
@@ -0,0 +1,14 @@
+/* Test assignment to elements of a string literal is a warning, not
+   an error.  PR 27676.  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+void
+f (void)
+{
+  "foo"[0] = 0; /* { dg-warning "assignment of read-only location" } */
+  "foo"[0]++; /* { dg-warning "increment of read-only location" } */
+  "foo"[0]--; /* { dg-warning "decrement of read-only location" } */
+  ++"foo"[0]; /* { dg-warning "increment of read-only location" } */
+  --"foo"[0]; /* { dg-warning "decrement of read-only location" } */
+}

-- 
Joseph S. Myers
joseph@codesourcery.com


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