From: Joseph Myers Date: Sat, 18 Apr 2009 23:21:34 +0000 (+0100) Subject: re PR c/27676 (gcc is overly strict in assignment to read-only data) X-Git-Tag: releases/gcc-4.5.0~6418 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f37acdf9b1089f74cd5ca953fbe508ae7e9e34c0;p=thirdparty%2Fgcc.git re PR c/27676 (gcc is overly strict in assignment to read-only data) 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: * gcc.dg/lvalue-5.c: New test. From-SVN: r146336 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4035b2c90ebc..405aefa69836 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-04-18 Joseph Myers + + 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. + 2009-04-18 Joseph Myers PR c/22367 diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index bacfdc0e8493..77eafbff0098 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -107,6 +107,7 @@ static void set_nonincremental_init (void); 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); @@ -3540,6 +3546,29 @@ readonly_error (tree arg, enum lvalue_use use) 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 @@ -4292,7 +4321,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))) @@ -4300,6 +4329,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'. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a2b0bb043c3c..c87827bd08b3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-18 Joseph Myers + + PR c/27676 + * gcc.dg/lvalue-5.c: New test. + 2009-04-18 Joseph Myers PR c/22367 diff --git a/gcc/testsuite/gcc.dg/lvalue-5.c b/gcc/testsuite/gcc.dg/lvalue-5.c new file mode 100644 index 000000000000..514f35ed802b --- /dev/null +++ b/gcc/testsuite/gcc.dg/lvalue-5.c @@ -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" } */ +}