mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-08 18:40:53 +08:00
c-tree.h (readonly_error): Remove.
* c-tree.h (readonly_error): Remove. * c-typeck (enum lvalue_use): New. (lvalue_or_else, readonly_error): Use it. All callers changed. (readonly_error): Make static. testsuite: * gcc.dg/lvalue-2.c: New test. From-SVN: r88362
This commit is contained in:
parent
29e12ba8ca
commit
9bf242660a
@ -1,3 +1,10 @@
|
||||
2004-09-30 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
* c-tree.h (readonly_error): Remove.
|
||||
* c-typeck (enum lvalue_use): New.
|
||||
(lvalue_or_else, readonly_error): Use it. All callers changed.
|
||||
(readonly_error): Make static.
|
||||
|
||||
2004-09-30 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR debug/13974
|
||||
|
@ -428,7 +428,6 @@ extern struct c_expr c_expr_sizeof_expr (struct c_expr);
|
||||
extern struct c_expr c_expr_sizeof_type (struct c_type_name *);
|
||||
extern struct c_expr parser_build_binary_op (enum tree_code, struct c_expr,
|
||||
struct c_expr);
|
||||
extern void readonly_error (tree, const char *);
|
||||
extern tree build_conditional_expr (tree, tree, tree);
|
||||
extern tree build_compound_expr (tree, tree);
|
||||
extern tree c_cast_expr (struct c_type_name *, tree);
|
||||
|
@ -44,6 +44,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "tree-iterator.h"
|
||||
#include "tree-gimple.h"
|
||||
|
||||
/* Places where an lvalue, or modifiable lvalue, may be required.
|
||||
Used to select diagnostic messages in lvalue_or_else and
|
||||
readonly_error. */
|
||||
enum lvalue_use {
|
||||
lv_assign,
|
||||
lv_increment,
|
||||
lv_decrement,
|
||||
lv_addressof,
|
||||
lv_asm
|
||||
};
|
||||
|
||||
/* The level of nesting inside "__alignof__". */
|
||||
int in_alignof;
|
||||
|
||||
@ -89,7 +100,8 @@ static void add_pending_init (tree, tree);
|
||||
static void set_nonincremental_init (void);
|
||||
static void set_nonincremental_init_from_string (tree);
|
||||
static tree find_init_member (tree);
|
||||
static int lvalue_or_else (tree, const char *);
|
||||
static int lvalue_or_else (tree, enum lvalue_use);
|
||||
static void readonly_error (tree, enum lvalue_use);
|
||||
|
||||
/* Do `exp = require_complete_type (exp);' to make sure exp
|
||||
does not have an incomplete type. (That includes void types.) */
|
||||
@ -2545,8 +2557,8 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
||||
/* Complain about anything else that is not a true lvalue. */
|
||||
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
|
||||
|| code == POSTINCREMENT_EXPR)
|
||||
? "invalid lvalue in increment"
|
||||
: "invalid lvalue in decrement")))
|
||||
? lv_increment
|
||||
: lv_decrement)))
|
||||
return error_mark_node;
|
||||
|
||||
/* Report a read-only lvalue. */
|
||||
@ -2554,7 +2566,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
||||
readonly_error (arg,
|
||||
((code == PREINCREMENT_EXPR
|
||||
|| code == POSTINCREMENT_EXPR)
|
||||
? "increment" : "decrement"));
|
||||
? lv_increment : lv_decrement));
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE)
|
||||
val = boolean_increment (code, arg);
|
||||
@ -2591,7 +2603,7 @@ build_unary_op (enum tree_code code, tree xarg, int flag)
|
||||
/* Anything not already handled and not a true memory reference
|
||||
or a non-lvalue array is an error. */
|
||||
else if (typecode != FUNCTION_TYPE && !flag
|
||||
&& !lvalue_or_else (arg, "invalid lvalue in unary %<&%>"))
|
||||
&& !lvalue_or_else (arg, lv_addressof))
|
||||
return error_mark_node;
|
||||
|
||||
/* Ordinary case; arg is a COMPONENT_REF or a decl. */
|
||||
@ -2682,40 +2694,73 @@ lvalue_p (tree ref)
|
||||
}
|
||||
|
||||
/* Return nonzero if REF is an lvalue valid for this language;
|
||||
otherwise, print an error message and return zero. MSGID
|
||||
is a format string which receives no arguments, but in which
|
||||
formats such as %< and %> may occur. */
|
||||
otherwise, print an error message and return zero. USE says
|
||||
how the lvalue is being used and so selects the error message. */
|
||||
|
||||
static int
|
||||
lvalue_or_else (tree ref, const char *msgid)
|
||||
lvalue_or_else (tree ref, enum lvalue_use use)
|
||||
{
|
||||
int win = lvalue_p (ref);
|
||||
|
||||
if (! win)
|
||||
error (msgid);
|
||||
if (!win)
|
||||
{
|
||||
switch (use)
|
||||
{
|
||||
case lv_assign:
|
||||
error ("invalid lvalue in assignment");
|
||||
break;
|
||||
case lv_increment:
|
||||
error ("invalid lvalue in increment");
|
||||
break;
|
||||
case lv_decrement:
|
||||
error ("invalid lvalue in decrement");
|
||||
break;
|
||||
case lv_addressof:
|
||||
error ("invalid lvalue in unary %<&%>");
|
||||
break;
|
||||
case lv_asm:
|
||||
error ("invalid lvalue in asm statement");
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
|
||||
/* Warn about storing in something that is `const'. */
|
||||
/* Give an error for storing in something that is 'const'. */
|
||||
|
||||
void
|
||||
readonly_error (tree arg, const char *msgid)
|
||||
static void
|
||||
readonly_error (tree arg, enum lvalue_use use)
|
||||
{
|
||||
gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement);
|
||||
/* Using this macro rather than (for example) arrays of messages
|
||||
ensures that all the format strings are checked at compile
|
||||
time. */
|
||||
#define READONLY_MSG(A, I, D) (use == lv_assign \
|
||||
? (A) \
|
||||
: (use == lv_increment ? (I) : (D)))
|
||||
if (TREE_CODE (arg) == COMPONENT_REF)
|
||||
{
|
||||
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
|
||||
readonly_error (TREE_OPERAND (arg, 0), msgid);
|
||||
readonly_error (TREE_OPERAND (arg, 0), use);
|
||||
else
|
||||
error ("%s of read-only member %qs", _(msgid),
|
||||
error (READONLY_MSG (N_("assignment of read-only member %qs"),
|
||||
N_("increment of read-only member %qs"),
|
||||
N_("decrement of read-only member %qs")),
|
||||
IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (arg, 1))));
|
||||
}
|
||||
else if (TREE_CODE (arg) == VAR_DECL)
|
||||
error ("%s of read-only variable %qs", _(msgid),
|
||||
error (READONLY_MSG (N_("assignment of read-only variable %qs"),
|
||||
N_("increment of read-only variable %qs"),
|
||||
N_("decrement of read-only variable %qs")),
|
||||
IDENTIFIER_POINTER (DECL_NAME (arg)));
|
||||
else
|
||||
error ("%s of read-only location", _(msgid));
|
||||
error (READONLY_MSG (N_("assignment of read-only location"),
|
||||
N_("increment of read-only location"),
|
||||
N_("decrement of read-only location")));
|
||||
}
|
||||
|
||||
/* Mark EXP saying that we need to be able to take the
|
||||
@ -3283,16 +3328,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
|
||||
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
|
||||
}
|
||||
|
||||
if (!lvalue_or_else (lhs, "invalid lvalue in assignment"))
|
||||
if (!lvalue_or_else (lhs, lv_assign))
|
||||
return error_mark_node;
|
||||
|
||||
/* Warn about storing in something that is `const'. */
|
||||
/* Give an error for storing in something that is 'const'. */
|
||||
|
||||
if (TREE_READONLY (lhs) || TYPE_READONLY (lhstype)
|
||||
|| ((TREE_CODE (lhstype) == RECORD_TYPE
|
||||
|| TREE_CODE (lhstype) == UNION_TYPE)
|
||||
&& C_TYPE_FIELDS_READONLY (lhstype)))
|
||||
readonly_error (lhs, "assignment");
|
||||
readonly_error (lhs, lv_assign);
|
||||
|
||||
/* If storing into a structure or union member,
|
||||
it has probably been given type `int'.
|
||||
@ -6249,7 +6294,7 @@ build_asm_expr (tree string, tree outputs, tree inputs, tree clobbers,
|
||||
tree output = TREE_VALUE (tail);
|
||||
STRIP_NOPS (output);
|
||||
TREE_VALUE (tail) = output;
|
||||
lvalue_or_else (output, "invalid lvalue in asm statement");
|
||||
lvalue_or_else (output, lv_asm);
|
||||
|
||||
constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
2004-09-30 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
* gcc.dg/lvalue-2.c: New test.
|
||||
|
||||
2004-09-30 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
PR c/17730
|
||||
|
48
gcc/testsuite/gcc.dg/lvalue-2.c
Normal file
48
gcc/testsuite/gcc.dg/lvalue-2.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Test diagnostic messages for invalid lvalues and non-modifiable
|
||||
lvalues. */
|
||||
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
int a, b;
|
||||
|
||||
void
|
||||
f0 (void)
|
||||
{
|
||||
(a+b) = 1; /* { dg-error "error: invalid lvalue in assignment" } */
|
||||
(a+b)++; /* { dg-error "error: invalid lvalue in increment" } */
|
||||
++(a+b); /* { dg-error "error: invalid lvalue in increment" } */
|
||||
(a+b)--; /* { dg-error "error: invalid lvalue in decrement" } */
|
||||
--(a+b); /* { dg-error "error: invalid lvalue in decrement" } */
|
||||
&(a+b); /* { dg-error "error: invalid lvalue in unary '&'" } */
|
||||
}
|
||||
|
||||
const int c;
|
||||
const struct { int x; } d;
|
||||
struct { const int x; } e;
|
||||
const int *f;
|
||||
|
||||
void
|
||||
f1 (void)
|
||||
{
|
||||
c = 1; /* { dg-error "error: assignment of read-only variable 'c'" } */
|
||||
d.x = 1; /* { dg-error "error: assignment of read-only variable 'd'" } */
|
||||
e.x = 1; /* { dg-error "error: assignment of read-only member 'x'" } */
|
||||
*f = 1; /* { dg-error "error: assignment of read-only location" } */
|
||||
c++; /* { dg-error "error: increment of read-only variable 'c'" } */
|
||||
d.x++; /* { dg-error "error: increment of read-only variable 'd'" } */
|
||||
e.x++; /* { dg-error "error: increment of read-only member 'x'" } */
|
||||
(*f)++; /* { dg-error "error: increment of read-only location" } */
|
||||
++c; /* { dg-error "error: increment of read-only variable 'c'" } */
|
||||
++d.x; /* { dg-error "error: increment of read-only variable 'd'" } */
|
||||
++e.x; /* { dg-error "error: increment of read-only member 'x'" } */
|
||||
++(*f); /* { dg-error "error: increment of read-only location" } */
|
||||
c--; /* { dg-error "error: decrement of read-only variable 'c'" } */
|
||||
d.x--; /* { dg-error "error: decrement of read-only variable 'd'" } */
|
||||
e.x--; /* { dg-error "error: decrement of read-only member 'x'" } */
|
||||
(*f)--; /* { dg-error "error: decrement of read-only location" } */
|
||||
--c; /* { dg-error "error: decrement of read-only variable 'c'" } */
|
||||
--d.x; /* { dg-error "error: decrement of read-only variable 'd'" } */
|
||||
--e.x; /* { dg-error "error: decrement of read-only member 'x'" } */
|
||||
--(*f); /* { dg-error "error: decrement of read-only location" } */
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user