Commit 487a92fe by Joseph Myers Committed by Joseph Myers

c-tree.h (struct c_expr): Define.

	* c-tree.h (struct c_expr): Define.
	(C_SET_EXP_ORIGINAL_CODE): Remove.
	(parser_build_binary_op, build_compound_expr): Update prototypes.
	* c-parse.in (%union): Add exprtype.
	(FUNC_NAME): Mark as ttype.
	(expr, expr_no_commas, cast_expr, unary_expr, primary): Change to
	exprtype.
	(expr): Update.  Define directly in terms of expr_no_commas
	instead of using nonnull_exprlist.
	(nonnull_exprlist, unary_expr, cast_expr, expr_no_commas, primary,
	offsetof_member_designator, typespec_nonreserved_nonattr, init,
	initval, designator, component_declarator,
	component_notype_declarator, enumerator, array_declarator,
	condition, exexpr, switch_statement, stmt_nocomp, stmt,
	nonnull_asm_operands, ivar_declarator, receiver): Update.  Don't
	set C_EXP_ORIGINAL_CODE.  Use TREE_NO_WARNING for assignments
	where appropriate.
	* c-common.h (C_EXP_ORIGINAL_CODE): Remove.
	* c-common.c (c_common_truthvalue_conversion): Don't check
	C_EXP_ORIGINAL_CODE.
	* c-typeck.c (parser_build_binary_op): Use c_expr structures.
	Don't use C_EXP_ORIGINAL_CODE.
	(default_conversion, default_function_array_conversion): Don't use
	C_EXP_ORIGINAL_CODE.  Preserve TREE_NO_WARNING.
	(internal_build_compound_expr): Merge into build_compound_expr.
	(build_compound_expr): Take two operands instead of a TREE_LIST.
	* objc/objc-act.c (get_super_receiver): Update calls to
	build_compound_expr.

cp:
	* typeck.c (build_modify_expr, build_x_modify_expr): Set
	TREE_NO_WARNING on assignments with an operator other than '='.

testsuite:
	* g++.dg/warn/Wparentheses-1.C, g++.dg/warn/Wparentheses-2.C,
	gcc.dg/Wparentheses-10.c: New tests.
	* gcc.dg/Wparentheses-5.c: Remove XFAILs.

From-SVN: r84911
parent 2de7ffa7
2004-07-19 Joseph S. Myers <jsm@polyomino.org.uk>
* c-tree.h (struct c_expr): Define.
(C_SET_EXP_ORIGINAL_CODE): Remove.
(parser_build_binary_op, build_compound_expr): Update prototypes.
* c-parse.in (%union): Add exprtype.
(FUNC_NAME): Mark as ttype.
(expr, expr_no_commas, cast_expr, unary_expr, primary): Change to
exprtype.
(expr): Update. Define directly in terms of expr_no_commas
instead of using nonnull_exprlist.
(nonnull_exprlist, unary_expr, cast_expr, expr_no_commas, primary,
offsetof_member_designator, typespec_nonreserved_nonattr, init,
initval, designator, component_declarator,
component_notype_declarator, enumerator, array_declarator,
condition, exexpr, switch_statement, stmt_nocomp, stmt,
nonnull_asm_operands, ivar_declarator, receiver): Update. Don't
set C_EXP_ORIGINAL_CODE. Use TREE_NO_WARNING for assignments
where appropriate.
* c-common.h (C_EXP_ORIGINAL_CODE): Remove.
* c-common.c (c_common_truthvalue_conversion): Don't check
C_EXP_ORIGINAL_CODE.
* c-typeck.c (parser_build_binary_op): Use c_expr structures.
Don't use C_EXP_ORIGINAL_CODE.
(default_conversion, default_function_array_conversion): Don't use
C_EXP_ORIGINAL_CODE. Preserve TREE_NO_WARNING.
(internal_build_compound_expr): Merge into build_compound_expr.
(build_compound_expr): Take two operands instead of a TREE_LIST.
* objc/objc-act.c (get_super_receiver): Update calls to
build_compound_expr.
2004-07-12 Paolo Bonzini <bonzini@gnu.org> 2004-07-12 Paolo Bonzini <bonzini@gnu.org>
* config/sh/sh.c (sh_use_dfa_interface): Remove. * config/sh/sh.c (sh_use_dfa_interface): Remove.
......
...@@ -2365,9 +2365,7 @@ c_common_truthvalue_conversion (tree expr) ...@@ -2365,9 +2365,7 @@ c_common_truthvalue_conversion (tree expr)
break; break;
case MODIFY_EXPR: case MODIFY_EXPR:
if (warn_parentheses if (warn_parentheses && !TREE_NO_WARNING (expr))
&& C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR
&& !TREE_NO_WARNING (expr))
warning ("suggest parentheses around assignment used as truth value"); warning ("suggest parentheses around assignment used as truth value");
break; break;
......
...@@ -598,10 +598,6 @@ extern int skip_evaluation; ...@@ -598,10 +598,6 @@ extern int skip_evaluation;
#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \ #define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
(!C_TYPE_FUNCTION_P (type)) (!C_TYPE_FUNCTION_P (type))
/* Record in each node resulting from a binary operator
what operator was specified for it. */
#define C_EXP_ORIGINAL_CODE(exp) ((enum tree_code) TREE_COMPLEXITY (exp))
/* Attribute table common to the C front ends. */ /* Attribute table common to the C front ends. */
extern const struct attribute_spec c_common_attribute_table[]; extern const struct attribute_spec c_common_attribute_table[];
extern const struct attribute_spec c_common_format_attribute_table[]; extern const struct attribute_spec c_common_format_attribute_table[];
......
...@@ -102,7 +102,7 @@ do { \ ...@@ -102,7 +102,7 @@ do { \
%start program %start program
%union {long itype; tree ttype; enum tree_code code; %union {long itype; tree ttype; struct c_expr exprtype; enum tree_code code;
location_t location; } location_t location; }
/* All identifiers that are not reserved words /* All identifiers that are not reserved words
...@@ -184,8 +184,9 @@ do { \ ...@@ -184,8 +184,9 @@ do { \
%type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF %type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT STRING FUNC_NAME
%type <ttype> expr_no_commas cast_expr unary_expr primary STRING %type <ttype> nonnull_exprlist exprlist
%type <exprtype> expr expr_no_commas cast_expr unary_expr primary
%type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea %type <ttype> declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea
%type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea %type <ttype> declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea
%type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea %type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
...@@ -462,8 +463,10 @@ unop: '&' ...@@ -462,8 +463,10 @@ unop: '&'
{ $$ = TRUTH_NOT_EXPR; } { $$ = TRUTH_NOT_EXPR; }
; ;
expr: nonnull_exprlist expr: expr_no_commas
{ $$ = build_compound_expr ($1); } | expr ',' expr_no_commas
{ $$.value = build_compound_expr ($1.value, $3.value);
$$.original_code = COMPOUND_EXPR; }
; ;
exprlist: exprlist:
...@@ -474,44 +477,53 @@ exprlist: ...@@ -474,44 +477,53 @@ exprlist:
nonnull_exprlist: nonnull_exprlist:
expr_no_commas expr_no_commas
{ $$ = build_tree_list (NULL_TREE, $1); } { $$ = build_tree_list (NULL_TREE, $1.value); }
| nonnull_exprlist ',' expr_no_commas | nonnull_exprlist ',' expr_no_commas
{ chainon ($1, build_tree_list (NULL_TREE, $3)); } { chainon ($1, build_tree_list (NULL_TREE, $3.value)); }
; ;
unary_expr: unary_expr:
primary primary
| '*' cast_expr %prec UNARY | '*' cast_expr %prec UNARY
{ $$ = build_indirect_ref ($2, "unary *"); } { $$.value = build_indirect_ref ($2.value, "unary *");
$$.original_code = ERROR_MARK; }
/* __extension__ turns off -pedantic for following primary. */ /* __extension__ turns off -pedantic for following primary. */
| extension cast_expr %prec UNARY | extension cast_expr %prec UNARY
{ $$ = $2; { $$ = $2;
RESTORE_EXT_FLAGS ($1); } RESTORE_EXT_FLAGS ($1); }
| unop cast_expr %prec UNARY | unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0); { $$.value = build_unary_op ($1, $2.value, 0);
overflow_warning ($$); } overflow_warning ($$.value);
$$.original_code = ERROR_MARK; }
/* Refer to the address of a label as a pointer. */ /* Refer to the address of a label as a pointer. */
| ANDAND identifier | ANDAND identifier
{ $$ = finish_label_address_expr ($2); } { $$.value = finish_label_address_expr ($2);
$$.original_code = ERROR_MARK; }
| sizeof unary_expr %prec UNARY | sizeof unary_expr %prec UNARY
{ skip_evaluation--; { skip_evaluation--;
if (TREE_CODE ($2) == COMPONENT_REF if (TREE_CODE ($2.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1))) && DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
error ("`sizeof' applied to a bit-field"); error ("`sizeof' applied to a bit-field");
$$ = c_sizeof (TREE_TYPE ($2)); } $$.value = c_sizeof (TREE_TYPE ($2.value));
$$.original_code = ERROR_MARK; }
| sizeof '(' typename ')' %prec HYPERUNARY | sizeof '(' typename ')' %prec HYPERUNARY
{ skip_evaluation--; { skip_evaluation--;
$$ = c_sizeof (groktypename ($3)); } $$.value = c_sizeof (groktypename ($3));
$$.original_code = ERROR_MARK; }
| alignof unary_expr %prec UNARY | alignof unary_expr %prec UNARY
{ skip_evaluation--; { skip_evaluation--;
$$ = c_alignof_expr ($2); } $$.value = c_alignof_expr ($2.value);
$$.original_code = ERROR_MARK; }
| alignof '(' typename ')' %prec HYPERUNARY | alignof '(' typename ')' %prec HYPERUNARY
{ skip_evaluation--; { skip_evaluation--;
$$ = c_alignof (groktypename ($3)); } $$.value = c_alignof (groktypename ($3));
$$.original_code = ERROR_MARK; }
| REALPART cast_expr %prec UNARY | REALPART cast_expr %prec UNARY
{ $$ = build_unary_op (REALPART_EXPR, $2, 0); } { $$.value = build_unary_op (REALPART_EXPR, $2.value, 0);
$$.original_code = ERROR_MARK; }
| IMAGPART cast_expr %prec UNARY | IMAGPART cast_expr %prec UNARY
{ $$ = build_unary_op (IMAGPART_EXPR, $2, 0); } { $$.value = build_unary_op (IMAGPART_EXPR, $2.value, 0);
$$.original_code = ERROR_MARK; }
; ;
sizeof: sizeof:
...@@ -529,7 +541,8 @@ typeof: ...@@ -529,7 +541,8 @@ typeof:
cast_expr: cast_expr:
unary_expr unary_expr
| '(' typename ')' cast_expr %prec UNARY | '(' typename ')' cast_expr %prec UNARY
{ $$ = c_cast_expr ($2, $4); } { $$.value = c_cast_expr ($2, $4.value);
$$.original_code = ERROR_MARK; }
; ;
expr_no_commas: expr_no_commas:
...@@ -559,54 +572,51 @@ expr_no_commas: ...@@ -559,54 +572,51 @@ expr_no_commas:
| expr_no_commas '^' expr_no_commas | expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); } { $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas ANDAND | expr_no_commas ANDAND
{ $1 = lang_hooks.truthvalue_conversion { $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1)); (default_conversion ($1.value));
skip_evaluation += $1 == truthvalue_false_node; } skip_evaluation += $1.value == truthvalue_false_node; }
expr_no_commas expr_no_commas
{ skip_evaluation -= $1 == truthvalue_false_node; { skip_evaluation -= $1.value == truthvalue_false_node;
$$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); } $$ = parser_build_binary_op (TRUTH_ANDIF_EXPR, $1, $4); }
| expr_no_commas OROR | expr_no_commas OROR
{ $1 = lang_hooks.truthvalue_conversion { $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1)); (default_conversion ($1.value));
skip_evaluation += $1 == truthvalue_true_node; } skip_evaluation += $1.value == truthvalue_true_node; }
expr_no_commas expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node; { skip_evaluation -= $1.value == truthvalue_true_node;
$$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); } $$ = parser_build_binary_op (TRUTH_ORIF_EXPR, $1, $4); }
| expr_no_commas '?' | expr_no_commas '?'
{ $1 = lang_hooks.truthvalue_conversion { $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1)); (default_conversion ($1.value));
skip_evaluation += $1 == truthvalue_false_node; } skip_evaluation += $1.value == truthvalue_false_node; }
expr ':' expr ':'
{ skip_evaluation += (($1 == truthvalue_true_node) { skip_evaluation += (($1.value == truthvalue_true_node)
- ($1 == truthvalue_false_node)); } - ($1.value == truthvalue_false_node)); }
expr_no_commas expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node; { skip_evaluation -= $1.value == truthvalue_true_node;
$$ = build_conditional_expr ($1, $4, $7); } $$.value = build_conditional_expr ($1.value, $4.value,
$7.value);
$$.original_code = ERROR_MARK; }
| expr_no_commas '?' | expr_no_commas '?'
{ if (pedantic) { if (pedantic)
pedwarn ("ISO C forbids omitting the middle term of a ?: expression"); pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */ /* Make sure first operand is calculated only once. */
$<ttype>2 = save_expr (default_conversion ($1)); $<ttype>2 = save_expr (default_conversion ($1.value));
$1 = lang_hooks.truthvalue_conversion ($<ttype>2); $1.value = lang_hooks.truthvalue_conversion ($<ttype>2);
skip_evaluation += $1 == truthvalue_true_node; } skip_evaluation += $1.value == truthvalue_true_node; }
':' expr_no_commas ':' expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node; { skip_evaluation -= $1.value == truthvalue_true_node;
$$ = build_conditional_expr ($1, $<ttype>2, $5); } $$.value = build_conditional_expr ($1.value, $<ttype>2,
$5.value);
$$.original_code = ERROR_MARK; }
| expr_no_commas '=' expr_no_commas | expr_no_commas '=' expr_no_commas
{ char class; { $$.value = build_modify_expr ($1.value, NOP_EXPR, $3.value);
$$ = build_modify_expr ($1, NOP_EXPR, $3); $$.original_code = MODIFY_EXPR;
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
} }
| expr_no_commas ASSIGN expr_no_commas | expr_no_commas ASSIGN expr_no_commas
{ char class; { $$.value = build_modify_expr ($1.value, $2, $3.value);
$$ = build_modify_expr ($1, $2, $3); TREE_NO_WARNING ($$.value) = 1;
/* This inhibits warnings in $$.original_code = ERROR_MARK;
c_common_truthvalue_conversion. */
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
} }
; ;
...@@ -615,12 +625,16 @@ primary: ...@@ -615,12 +625,16 @@ primary:
{ {
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
yychar = YYLEX; yychar = YYLEX;
$$ = build_external_ref ($1, yychar == '('); $$.value = build_external_ref ($1, yychar == '(');
$$.original_code = ERROR_MARK;
} }
| CONSTANT | CONSTANT
{ $$.value = $1; $$.original_code = ERROR_MARK; }
| STRING | STRING
{ $$.value = $1; $$.original_code = ERROR_MARK; }
| FUNC_NAME | FUNC_NAME
{ $$ = fname_decl (C_RID_CODE ($$), $$); } { $$.value = fname_decl (C_RID_CODE ($1), $1);
$$.original_code = ERROR_MARK; }
| '(' typename ')' '{' | '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0); { start_init (NULL_TREE, NULL, 0);
$2 = groktypename ($2); $2 = groktypename ($2);
...@@ -632,39 +646,45 @@ primary: ...@@ -632,39 +646,45 @@ primary:
if (pedantic && ! flag_isoc99) if (pedantic && ! flag_isoc99)
pedwarn ("ISO C90 forbids compound literals"); pedwarn ("ISO C90 forbids compound literals");
$$ = build_compound_literal (type, constructor); $$.value = build_compound_literal (type, constructor);
$$.original_code = ERROR_MARK;
} }
| '(' expr ')' | '(' expr ')'
{ char class = TREE_CODE_CLASS (TREE_CODE ($2)); { $$.value = $2.value;
if (IS_EXPR_CODE_CLASS (class)) if (TREE_CODE ($$.value) == MODIFY_EXPR)
C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK); TREE_NO_WARNING ($$.value) = 1;
$$ = $2; } $$.original_code = ERROR_MARK; }
| '(' error ')' | '(' error ')'
{ $$ = error_mark_node; } { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| compstmt_primary_start compstmt_nostart ')' | compstmt_primary_start compstmt_nostart ')'
{ if (pedantic) { if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions"); pedwarn ("ISO C forbids braced-groups within expressions");
$$ = c_finish_stmt_expr ($1); $$.value = c_finish_stmt_expr ($1);
$$.original_code = ERROR_MARK;
} }
| compstmt_primary_start error ')' | compstmt_primary_start error ')'
{ c_finish_stmt_expr ($1); { c_finish_stmt_expr ($1);
$$ = error_mark_node; $$.value = error_mark_node;
$$.original_code = ERROR_MARK;
} }
| primary '(' exprlist ')' %prec '.' | primary '(' exprlist ')' %prec '.'
{ $$ = build_function_call ($1, $3); } { $$.value = build_function_call ($1.value, $3);
$$.original_code = ERROR_MARK; }
| VA_ARG '(' expr_no_commas ',' typename ')' | VA_ARG '(' expr_no_commas ',' typename ')'
{ $$ = build_va_arg ($3, groktypename ($5)); } { $$.value = build_va_arg ($3.value, groktypename ($5));
$$.original_code = ERROR_MARK; }
| OFFSETOF '(' typename ',' offsetof_member_designator ')' | OFFSETOF '(' typename ',' offsetof_member_designator ')'
{ $$ = build_offsetof (groktypename ($3), $5); } { $$.value = build_offsetof (groktypename ($3), $5);
$$.original_code = ERROR_MARK; }
| OFFSETOF '(' error ')' | OFFSETOF '(' error ')'
{ $$ = error_mark_node; } { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ',' | CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
expr_no_commas ')' expr_no_commas ')'
{ {
tree c; tree c;
c = fold ($3); c = fold ($3.value);
STRIP_NOPS (c); STRIP_NOPS (c);
if (TREE_CODE (c) != INTEGER_CST) if (TREE_CODE (c) != INTEGER_CST)
error ("first argument to __builtin_choose_expr not" error ("first argument to __builtin_choose_expr not"
...@@ -672,7 +692,7 @@ primary: ...@@ -672,7 +692,7 @@ primary:
$$ = integer_zerop (c) ? $7 : $5; $$ = integer_zerop (c) ? $7 : $5;
} }
| CHOOSE_EXPR '(' error ')' | CHOOSE_EXPR '(' error ')'
{ $$ = error_mark_node; } { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| TYPES_COMPATIBLE_P '(' typename ',' typename ')' | TYPES_COMPATIBLE_P '(' typename ',' typename ')'
{ {
tree e1, e2; tree e1, e2;
...@@ -680,35 +700,46 @@ primary: ...@@ -680,35 +700,46 @@ primary:
e1 = TYPE_MAIN_VARIANT (groktypename ($3)); e1 = TYPE_MAIN_VARIANT (groktypename ($3));
e2 = TYPE_MAIN_VARIANT (groktypename ($5)); e2 = TYPE_MAIN_VARIANT (groktypename ($5));
$$ = comptypes (e1, e2) $$.value = comptypes (e1, e2)
? build_int_2 (1, 0) : build_int_2 (0, 0); ? build_int_2 (1, 0) : build_int_2 (0, 0);
$$.original_code = ERROR_MARK;
} }
| TYPES_COMPATIBLE_P '(' error ')' | TYPES_COMPATIBLE_P '(' error ')'
{ $$ = error_mark_node; } { $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| primary '[' expr ']' %prec '.' | primary '[' expr ']' %prec '.'
{ $$ = build_array_ref ($1, $3); } { $$.value = build_array_ref ($1.value, $3.value);
$$.original_code = ERROR_MARK; }
| primary '.' identifier | primary '.' identifier
{ $$ = build_component_ref ($1, $3); } { $$.value = build_component_ref ($1.value, $3);
$$.original_code = ERROR_MARK; }
| primary POINTSAT identifier | primary POINTSAT identifier
{ {
tree expr = build_indirect_ref ($1, "->"); tree expr = build_indirect_ref ($1.value, "->");
$$ = build_component_ref (expr, $3); $$.value = build_component_ref (expr, $3);
$$.original_code = ERROR_MARK;
} }
| primary PLUSPLUS | primary PLUSPLUS
{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); } { $$.value = build_unary_op (POSTINCREMENT_EXPR, $1.value, 0);
$$.original_code = ERROR_MARK; }
| primary MINUSMINUS | primary MINUSMINUS
{ $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); } { $$.value = build_unary_op (POSTDECREMENT_EXPR, $1.value, 0);
$$.original_code = ERROR_MARK; }
@@ifobjc @@ifobjc
| objcmessageexpr | objcmessageexpr
{ $$ = build_message_expr ($1); } { $$.value = build_message_expr ($1);
$$.original_code = ERROR_MARK; }
| objcselectorexpr | objcselectorexpr
{ $$ = build_selector_expr ($1); } { $$.value = build_selector_expr ($1);
$$.original_code = ERROR_MARK; }
| objcprotocolexpr | objcprotocolexpr
{ $$ = build_protocol_expr ($1); } { $$.value = build_protocol_expr ($1);
$$.original_code = ERROR_MARK; }
| objcencodeexpr | objcencodeexpr
{ $$ = build_encode_expr ($1); } { $$.value = build_encode_expr ($1);
$$.original_code = ERROR_MARK; }
| OBJC_STRING | OBJC_STRING
{ $$ = build_objc_string_object ($1); } { $$.value = build_objc_string_object ($1);
$$.original_code = ERROR_MARK; }
@@end_ifobjc @@end_ifobjc
; ;
...@@ -724,7 +755,7 @@ offsetof_member_designator: ...@@ -724,7 +755,7 @@ offsetof_member_designator:
| offsetof_member_designator '.' identifier | offsetof_member_designator '.' identifier
{ $$ = tree_cons ($3, NULL_TREE, $1); } { $$ = tree_cons ($3, NULL_TREE, $1); }
| offsetof_member_designator '[' expr ']' | offsetof_member_designator '[' expr ']'
{ $$ = tree_cons (NULL_TREE, $3, $1); } { $$ = tree_cons (NULL_TREE, $3.value, $1); }
; ;
old_style_parm_decls: old_style_parm_decls:
...@@ -1332,10 +1363,10 @@ typespec_nonreserved_nonattr: ...@@ -1332,10 +1363,10 @@ typespec_nonreserved_nonattr:
@@end_ifobjc @@end_ifobjc
| typeof '(' expr ')' | typeof '(' expr ')'
{ skip_evaluation--; { skip_evaluation--;
if (TREE_CODE ($3) == COMPONENT_REF if (TREE_CODE ($3.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($3, 1))) && DECL_C_BIT_FIELD (TREE_OPERAND ($3.value, 1)))
error ("`typeof' applied to a bit-field"); error ("`typeof' applied to a bit-field");
$$ = TREE_TYPE ($3); } $$ = TREE_TYPE ($3.value); }
| typeof '(' typename ')' | typeof '(' typename ')'
{ skip_evaluation--; $$ = groktypename ($3); } { skip_evaluation--; $$ = groktypename ($3); }
; ;
...@@ -1445,6 +1476,7 @@ scspec: ...@@ -1445,6 +1476,7 @@ scspec:
init: init:
expr_no_commas expr_no_commas
{ $$ = $1.value; }
| '{' | '{'
{ really_start_incremental_init (NULL_TREE); } { really_start_incremental_init (NULL_TREE); }
initlist_maybe_comma '}' initlist_maybe_comma '}'
...@@ -1490,7 +1522,7 @@ initval: ...@@ -1490,7 +1522,7 @@ initval:
initlist_maybe_comma '}' initlist_maybe_comma '}'
{ process_init_element (pop_init_level (0)); } { process_init_element (pop_init_level (0)); }
| expr_no_commas | expr_no_commas
{ process_init_element ($1); } { process_init_element ($1.value); }
| error | error
; ;
...@@ -1503,11 +1535,11 @@ designator: ...@@ -1503,11 +1535,11 @@ designator:
'.' identifier '.' identifier
{ set_init_label ($2); } { set_init_label ($2); }
| '[' expr_no_commas ELLIPSIS expr_no_commas ']' | '[' expr_no_commas ELLIPSIS expr_no_commas ']'
{ set_init_index ($2, $4); { set_init_index ($2.value, $4.value);
if (pedantic) if (pedantic)
pedwarn ("ISO C forbids specifying range of elements to initialize"); } pedwarn ("ISO C forbids specifying range of elements to initialize"); }
| '[' expr_no_commas ']' | '[' expr_no_commas ']'
{ set_init_index ($2, NULL_TREE); } { set_init_index ($2.value, NULL_TREE); }
; ;
nested_function: nested_function:
...@@ -1809,11 +1841,11 @@ component_declarator: ...@@ -1809,11 +1841,11 @@ component_declarator:
decl_attributes (&$$, decl_attributes (&$$,
chainon ($2, all_prefix_attributes), 0); } chainon ($2, all_prefix_attributes), 0); }
| declarator ':' expr_no_commas maybe_attribute | declarator ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, current_declspecs, $3); { $$ = grokfield ($1, current_declspecs, $3.value);
decl_attributes (&$$, decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); } chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute | ':' expr_no_commas maybe_attribute
{ $$ = grokfield (NULL_TREE, current_declspecs, $2); { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
decl_attributes (&$$, decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); } chainon ($3, all_prefix_attributes), 0); }
; ;
...@@ -1824,11 +1856,11 @@ component_notype_declarator: ...@@ -1824,11 +1856,11 @@ component_notype_declarator:
decl_attributes (&$$, decl_attributes (&$$,
chainon ($2, all_prefix_attributes), 0); } chainon ($2, all_prefix_attributes), 0); }
| notype_declarator ':' expr_no_commas maybe_attribute | notype_declarator ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, current_declspecs, $3); { $$ = grokfield ($1, current_declspecs, $3.value);
decl_attributes (&$$, decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); } chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute | ':' expr_no_commas maybe_attribute
{ $$ = grokfield (NULL_TREE, current_declspecs, $2); { $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
decl_attributes (&$$, decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); } chainon ($3, all_prefix_attributes), 0); }
; ;
...@@ -1852,7 +1884,7 @@ enumerator: ...@@ -1852,7 +1884,7 @@ enumerator:
identifier identifier
{ $$ = build_enumerator ($1, NULL_TREE); } { $$ = build_enumerator ($1, NULL_TREE); }
| identifier '=' expr_no_commas | identifier '=' expr_no_commas
{ $$ = build_enumerator ($1, $3); } { $$ = build_enumerator ($1, $3.value); }
; ;
typename: typename:
...@@ -1919,16 +1951,16 @@ direct_absdcl1: ...@@ -1919,16 +1951,16 @@ direct_absdcl1:
array_declarator: array_declarator:
'[' maybe_type_quals_attrs expr_no_commas ']' '[' maybe_type_quals_attrs expr_no_commas ']'
{ $$ = build_array_declarator ($3, $2, 0, 0); } { $$ = build_array_declarator ($3.value, $2, 0, 0); }
| '[' maybe_type_quals_attrs ']' | '[' maybe_type_quals_attrs ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); } { $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
| '[' maybe_type_quals_attrs '*' ']' | '[' maybe_type_quals_attrs '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); } { $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
| '[' STATIC maybe_type_quals_attrs expr_no_commas ']' | '[' STATIC maybe_type_quals_attrs expr_no_commas ']'
{ $$ = build_array_declarator ($4, $3, 1, 0); } { $$ = build_array_declarator ($4.value, $3, 1, 0); }
/* declspecs_nosc_nots is a synonym for type_quals_attrs. */ /* declspecs_nosc_nots is a synonym for type_quals_attrs. */
| '[' declspecs_nosc_nots STATIC expr_no_commas ']' | '[' declspecs_nosc_nots STATIC expr_no_commas ']'
{ $$ = build_array_declarator ($4, $2, 1, 0); } { $$ = build_array_declarator ($4.value, $2, 1, 0); }
; ;
/* A nonempty series of declarations and statements (possibly followed by /* A nonempty series of declarations and statements (possibly followed by
...@@ -2102,7 +2134,7 @@ lineno_label: ...@@ -2102,7 +2134,7 @@ lineno_label:
; ;
condition: save_location expr condition: save_location expr
{ $$ = lang_hooks.truthvalue_conversion ($2); { $$ = lang_hooks.truthvalue_conversion ($2.value);
if (EXPR_P ($$)) if (EXPR_P ($$))
SET_EXPR_LOCATION ($$, $1); } SET_EXPR_LOCATION ($$, $1); }
; ;
...@@ -2177,6 +2209,7 @@ xexpr: ...@@ -2177,6 +2209,7 @@ xexpr:
/* empty */ /* empty */
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
| expr | expr
{ $$ = $1.value; }
; ;
for_init_stmt: for_init_stmt:
...@@ -2214,7 +2247,7 @@ for_statement: ...@@ -2214,7 +2247,7 @@ for_statement:
switch_statement: switch_statement:
SWITCH c99_block_start '(' expr ')' SWITCH c99_block_start '(' expr ')'
{ $<ttype>$ = c_start_case ($4); } { $<ttype>$ = c_start_case ($4.value); }
start_break c99_block_lineno_labeled_stmt start_break c99_block_lineno_labeled_stmt
{ c_finish_case ($8); { c_finish_case ($8);
if (c_break_label) if (c_break_label)
...@@ -2227,7 +2260,7 @@ switch_statement: ...@@ -2227,7 +2260,7 @@ switch_statement:
/* Parse a single real statement, not including any labels or compounds. */ /* Parse a single real statement, not including any labels or compounds. */
stmt_nocomp: stmt_nocomp:
expr ';' expr ';'
{ $$ = c_finish_expr_stmt ($1); } { $$ = c_finish_expr_stmt ($1.value); }
| if_statement | if_statement
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
| while_statement | while_statement
...@@ -2245,23 +2278,23 @@ stmt_nocomp: ...@@ -2245,23 +2278,23 @@ stmt_nocomp:
| RETURN ';' | RETURN ';'
{ $$ = c_finish_return (NULL_TREE); } { $$ = c_finish_return (NULL_TREE); }
| RETURN expr ';' | RETURN expr ';'
{ $$ = c_finish_return ($2); } { $$ = c_finish_return ($2.value); }
| asm_stmt | asm_stmt
| GOTO identifier ';' | GOTO identifier ';'
{ $$ = c_finish_goto_label ($2); } { $$ = c_finish_goto_label ($2); }
| GOTO '*' expr ';' | GOTO '*' expr ';'
{ $$ = c_finish_goto_ptr ($3); } { $$ = c_finish_goto_ptr ($3.value); }
| ';' | ';'
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
@@ifobjc @@ifobjc
| AT_THROW expr ';' | AT_THROW expr ';'
{ $$ = objc_build_throw_stmt ($2); } { $$ = objc_build_throw_stmt ($2.value); }
| AT_THROW ';' | AT_THROW ';'
{ $$ = objc_build_throw_stmt (NULL_TREE); } { $$ = objc_build_throw_stmt (NULL_TREE); }
| objc_try_catch_stmt | objc_try_catch_stmt
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
| AT_SYNCHRONIZED save_location '(' expr ')' compstmt | AT_SYNCHRONIZED save_location '(' expr ')' compstmt
{ objc_build_synchronized ($2, $4, $6); $$ = NULL_TREE; } { objc_build_synchronized ($2, $4.value, $6); $$ = NULL_TREE; }
; ;
objc_catch_prefix: objc_catch_prefix:
...@@ -2312,9 +2345,9 @@ stmt: ...@@ -2312,9 +2345,9 @@ stmt:
also at the end of a compound statement. */ also at the end of a compound statement. */
label: CASE expr_no_commas ':' label: CASE expr_no_commas ':'
{ $$ = do_case ($2, NULL_TREE); } { $$ = do_case ($2.value, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':' | CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ $$ = do_case ($2, $4); } { $$ = do_case ($2.value, $4.value); }
| DEFAULT ':' | DEFAULT ':'
{ $$ = do_case (NULL_TREE, NULL_TREE); } { $$ = do_case (NULL_TREE, NULL_TREE); }
| identifier save_location ':' maybe_attribute | identifier save_location ':' maybe_attribute
...@@ -2408,12 +2441,13 @@ nonnull_asm_operands: ...@@ -2408,12 +2441,13 @@ nonnull_asm_operands:
asm_operand: asm_operand:
STRING start_string_translation '(' expr ')' stop_string_translation STRING start_string_translation '(' expr ')' stop_string_translation
{ $$ = build_tree_list (build_tree_list (NULL_TREE, $1), $4); } { $$ = build_tree_list (build_tree_list (NULL_TREE, $1),
$4.value); }
| '[' identifier ']' STRING start_string_translation | '[' identifier ']' STRING start_string_translation
'(' expr ')' stop_string_translation '(' expr ')' stop_string_translation
{ $2 = build_string (IDENTIFIER_LENGTH ($2), { $2 = build_string (IDENTIFIER_LENGTH ($2),
IDENTIFIER_POINTER ($2)); IDENTIFIER_POINTER ($2));
$$ = build_tree_list (build_tree_list ($2, $4), $7); } $$ = build_tree_list (build_tree_list ($2, $4), $7.value); }
; ;
asm_clobbers: asm_clobbers:
...@@ -2805,14 +2839,14 @@ ivar_declarator: ...@@ -2805,14 +2839,14 @@ ivar_declarator:
{ {
$$ = add_instance_variable (objc_ivar_context, $$ = add_instance_variable (objc_ivar_context,
objc_public_flag, objc_public_flag,
$1, current_declspecs, $3); $1, current_declspecs, $3.value);
} }
| ':' expr_no_commas | ':' expr_no_commas
{ {
$$ = add_instance_variable (objc_ivar_context, $$ = add_instance_variable (objc_ivar_context,
objc_public_flag, objc_public_flag,
NULL_TREE, NULL_TREE,
current_declspecs, $2); current_declspecs, $2.value);
} }
; ;
...@@ -3068,6 +3102,7 @@ keywordarg: ...@@ -3068,6 +3102,7 @@ keywordarg:
receiver: receiver:
expr expr
{ $$ = $1.value; }
| CLASSNAME | CLASSNAME
{ {
$$ = get_class_reference ($1); $$ = get_class_reference ($1);
......
...@@ -80,10 +80,6 @@ struct lang_type GTY(()) ...@@ -80,10 +80,6 @@ struct lang_type GTY(())
#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE) #define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (TYPE)
#define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE) #define C_DECL_VARIABLE_SIZE(TYPE) DECL_LANG_FLAG_0 (TYPE)
/* Store a value in that field. */
#define C_SET_EXP_ORIGINAL_CODE(EXP, CODE) \
(TREE_COMPLEXITY (EXP) = (int) (CODE))
/* Record whether a typedef for type `int' was actually `signed int'. */ /* Record whether a typedef for type `int' was actually `signed int'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP) #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
...@@ -116,6 +112,18 @@ struct lang_type GTY(()) ...@@ -116,6 +112,18 @@ struct lang_type GTY(())
without prototypes. */ without prototypes. */
#define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE) #define TYPE_ACTUAL_ARG_TYPES(NODE) TYPE_LANG_SLOT_1 (NODE)
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
struct c_expr
{
/* The value of the expression. */
tree value;
/* Record the original binary operator of an expression, which may
have been changed by fold, or ERROR_MARK for other expressions
(including parenthesized expressions). */
enum tree_code original_code;
};
/* Save and restore the variables in this file and elsewhere /* Save and restore the variables in this file and elsewhere
that keep track of the progress of compilation of the current function. that keep track of the progress of compilation of the current function.
Used for nested functions. */ Used for nested functions. */
...@@ -225,10 +233,11 @@ extern tree build_component_ref (tree, tree); ...@@ -225,10 +233,11 @@ extern tree build_component_ref (tree, tree);
extern tree build_indirect_ref (tree, const char *); extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree); extern tree build_array_ref (tree, tree);
extern tree build_external_ref (tree, int); extern tree build_external_ref (tree, int);
extern tree parser_build_binary_op (enum tree_code, tree, tree); 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 void readonly_error (tree, const char *);
extern tree build_conditional_expr (tree, tree, tree); extern tree build_conditional_expr (tree, tree, tree);
extern tree build_compound_expr (tree); extern tree build_compound_expr (tree, tree);
extern tree c_cast_expr (tree, tree); extern tree c_cast_expr (tree, tree);
extern tree build_c_cast (tree, tree); extern tree build_c_cast (tree, tree);
extern tree build_modify_expr (tree, enum tree_code, tree); extern tree build_modify_expr (tree, enum tree_code, tree);
......
...@@ -62,7 +62,6 @@ static tree default_function_array_conversion (tree); ...@@ -62,7 +62,6 @@ static tree default_function_array_conversion (tree);
static tree lookup_field (tree, tree); static tree lookup_field (tree, tree);
static tree convert_arguments (tree, tree, tree, tree); static tree convert_arguments (tree, tree, tree, tree);
static tree pointer_diff (tree, tree); static tree pointer_diff (tree, tree);
static tree internal_build_compound_expr (tree, int);
static tree convert_for_assignment (tree, tree, const char *, tree, tree, static tree convert_for_assignment (tree, tree, const char *, tree, tree,
int); int);
static void warn_for_assignment (const char *, const char *, tree, int); static void warn_for_assignment (const char *, const char *, tree, int);
...@@ -1182,9 +1181,8 @@ default_function_array_conversion (tree exp) ...@@ -1182,9 +1181,8 @@ default_function_array_conversion (tree exp)
exp = TREE_OPERAND (exp, 0); exp = TREE_OPERAND (exp, 0);
} }
/* Preserve the original expression code. */ if (TREE_NO_WARNING (orig_exp))
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) TREE_NO_WARNING (exp) = 1;
C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
if (code == FUNCTION_TYPE) if (code == FUNCTION_TYPE)
{ {
...@@ -1294,9 +1292,8 @@ default_conversion (tree exp) ...@@ -1294,9 +1292,8 @@ default_conversion (tree exp)
&& TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp))) && TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
exp = TREE_OPERAND (exp, 0); exp = TREE_OPERAND (exp, 0);
/* Preserve the original expression code. */ if (TREE_NO_WARNING (orig_exp))
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp)))) TREE_NO_WARNING (exp) = 1;
C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
/* Normally convert enums to int, /* Normally convert enums to int,
but convert wide enums to something wider. */ but convert wide enums to something wider. */
...@@ -2099,28 +2096,23 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl) ...@@ -2099,28 +2096,23 @@ convert_arguments (tree typelist, tree values, tree name, tree fundecl)
we check for operands that were written with other binary operators we check for operands that were written with other binary operators
in a way that is likely to confuse the user. */ in a way that is likely to confuse the user. */
tree struct c_expr
parser_build_binary_op (enum tree_code code, tree arg1, tree arg2) parser_build_binary_op (enum tree_code code, struct c_expr arg1,
struct c_expr arg2)
{ {
tree result = build_binary_op (code, arg1, arg2, 1); struct c_expr result;
char class; enum tree_code code1 = arg1.original_code;
char class1 = TREE_CODE_CLASS (TREE_CODE (arg1)); enum tree_code code2 = arg2.original_code;
char class2 = TREE_CODE_CLASS (TREE_CODE (arg2));
enum tree_code code1 = ERROR_MARK;
enum tree_code code2 = ERROR_MARK;
if (TREE_CODE (result) == ERROR_MARK) result.value = build_binary_op (code, arg1.value, arg2.value, 1);
return error_mark_node; result.original_code = code;
if (IS_EXPR_CODE_CLASS (class1)) if (TREE_CODE (result.value) == ERROR_MARK)
code1 = C_EXP_ORIGINAL_CODE (arg1); return result;
if (IS_EXPR_CODE_CLASS (class2))
code2 = C_EXP_ORIGINAL_CODE (arg2);
/* Check for cases such as x+y<<z which users are likely /* Check for cases such as x+y<<z which users are likely
to misinterpret. If parens are used, C_EXP_ORIGINAL_CODE to misinterpret. */
is cleared to prevent these warnings. */
if (warn_parentheses) if (warn_parentheses)
{ {
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR) if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
...@@ -2178,25 +2170,9 @@ parser_build_binary_op (enum tree_code code, tree arg1, tree arg2) ...@@ -2178,25 +2170,9 @@ parser_build_binary_op (enum tree_code code, tree arg1, tree arg2)
} }
unsigned_conversion_warning (result, arg1); unsigned_conversion_warning (result.value, arg1.value);
unsigned_conversion_warning (result, arg2); unsigned_conversion_warning (result.value, arg2.value);
overflow_warning (result); overflow_warning (result.value);
class = TREE_CODE_CLASS (TREE_CODE (result));
/* Record the code that was specified in the source,
for the sake of warnings about confusing nesting. */
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE (result, code);
else
{
/* We used to use NOP_EXPR rather than NON_LVALUE_EXPR
so that convert_for_assignment wouldn't strip it.
That way, we got warnings for things like p = (1 - 1).
But it turns out we should not get those warnings. */
result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
C_SET_EXP_ORIGINAL_CODE (result, code);
}
return result; return result;
} }
...@@ -2894,44 +2870,27 @@ build_conditional_expr (tree ifexp, tree op1, tree op2) ...@@ -2894,44 +2870,27 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
return fold (build (COND_EXPR, result_type, ifexp, op1, op2)); return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
} }
/* Given a list of expressions, return a compound expression /* Return a compound expression that performs two expressions and
that performs them all and returns the value of the last of them. */ returns the value of the second of them. */
tree tree
build_compound_expr (tree list) build_compound_expr (tree expr1, tree expr2)
{ {
return internal_build_compound_expr (list, TRUE); /* Convert arrays and functions to pointers. */
} expr2 = default_function_array_conversion (expr2);
static tree
internal_build_compound_expr (tree list, int first_p)
{
tree rest;
if (TREE_CHAIN (list) == 0)
{
/* Convert arrays and functions to pointers when there
really is a comma operator. */
if (!first_p)
TREE_VALUE (list)
= default_function_array_conversion (TREE_VALUE (list));
/* Don't let (0, 0) be null pointer constant. */ /* Don't let (0, 0) be null pointer constant. */
if (!first_p && integer_zerop (TREE_VALUE (list))) if (integer_zerop (expr2))
return non_lvalue (TREE_VALUE (list)); expr2 = non_lvalue (expr2);
return TREE_VALUE (list);
}
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) if (! TREE_SIDE_EFFECTS (expr1))
{ {
/* The left-hand operand of a comma expression is like an expression /* The left-hand operand of a comma expression is like an expression
statement: with -Wextra or -Wunused, we should warn if it doesn't have statement: with -Wextra or -Wunused, we should warn if it doesn't have
any side-effects, unless it was explicitly cast to (void). */ any side-effects, unless it was explicitly cast to (void). */
if (warn_unused_value if (warn_unused_value
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR && ! (TREE_CODE (expr1) == CONVERT_EXPR
&& VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list))))) && VOID_TYPE_P (TREE_TYPE (expr1))))
warning ("left-hand operand of comma expression has no effect"); warning ("left-hand operand of comma expression has no effect");
} }
...@@ -2940,9 +2899,9 @@ internal_build_compound_expr (tree list, int first_p) ...@@ -2940,9 +2899,9 @@ internal_build_compound_expr (tree list, int first_p)
`foo() + bar(), baz()' the result of the `+' operator is not used, `foo() + bar(), baz()' the result of the `+' operator is not used,
so we should issue a warning. */ so we should issue a warning. */
else if (warn_unused_value) else if (warn_unused_value)
warn_if_unused_value (TREE_VALUE (list), input_location); warn_if_unused_value (expr1, input_location);
return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest); return build (COMPOUND_EXPR, TREE_TYPE (expr2), expr1, expr2);
} }
/* Build an expression representing a cast to type TYPE of expression EXPR. */ /* Build an expression representing a cast to type TYPE of expression EXPR. */
......
2004-07-19 Joseph S. Myers <jsm@polyomino.org.uk>
* typeck.c (build_modify_expr, build_x_modify_expr): Set
TREE_NO_WARNING on assignments with an operator other than '='.
2004-07-10 Steven Bosscher <stevenb@suse.de> 2004-07-10 Steven Bosscher <stevenb@suse.de>
Joseph S. Myers <jsm@polyomino.org.uk> Joseph S. Myers <jsm@polyomino.org.uk>
......
...@@ -4995,6 +4995,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -4995,6 +4995,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
tree lhstype = TREE_TYPE (lhs); tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype; tree olhstype = lhstype;
tree olhs = NULL_TREE; tree olhs = NULL_TREE;
bool plain_assign = (modifycode == NOP_EXPR);
/* Avoid duplicate error messages from operands that had errors. */ /* Avoid duplicate error messages from operands that had errors. */
if (lhs == error_mark_node || rhs == error_mark_node) if (lhs == error_mark_node || rhs == error_mark_node)
...@@ -5254,6 +5255,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -5254,6 +5255,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
lhstype, lhs, newrhs); lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1; TREE_SIDE_EFFECTS (result) = 1;
if (!plain_assign)
TREE_NO_WARNING (result) = 1;
/* If we got the LHS in a different type for storing in, /* If we got the LHS in a different type for storing in,
convert the result back to the nominal type of LHS convert the result back to the nominal type of LHS
...@@ -5285,8 +5288,11 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -5285,8 +5288,11 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
make_node (modifycode), make_node (modifycode),
/*overloaded_p=*/NULL); /*overloaded_p=*/NULL);
if (rval) if (rval)
{
TREE_NO_WARNING (rval) = 1;
return rval; return rval;
} }
}
return build_modify_expr (lhs, modifycode, rhs); return build_modify_expr (lhs, modifycode, rhs);
} }
......
...@@ -7870,7 +7870,7 @@ get_super_receiver (void) ...@@ -7870,7 +7870,7 @@ get_super_receiver (void)
/* Set receiver to self. */ /* Set receiver to self. */
super_expr = build_component_ref (UOBJC_SUPER_decl, self_id); super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl); super_expr = build_modify_expr (super_expr, NOP_EXPR, self_decl);
super_expr_list = build_tree_list (NULL_TREE, super_expr); super_expr_list = super_expr;
/* Set class to begin searching. */ /* Set class to begin searching. */
#ifdef OBJCPLUS #ifdef OBJCPLUS
...@@ -7941,12 +7941,12 @@ get_super_receiver (void) ...@@ -7941,12 +7941,12 @@ get_super_receiver (void)
super_class)); super_class));
} }
chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); super_expr_list = build_compound_expr (super_expr_list, super_expr);
super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0); super_expr = build_unary_op (ADDR_EXPR, UOBJC_SUPER_decl, 0);
chainon (super_expr_list, build_tree_list (NULL_TREE, super_expr)); super_expr_list = build_compound_expr (super_expr_list, super_expr);
return build_compound_expr (super_expr_list); return super_expr_list;
} }
else else
{ {
......
2004-07-19 Joseph S. Myers <jsm@polyomino.org.uk>
* g++.dg/warn/Wparentheses-1.C, g++.dg/warn/Wparentheses-2.C,
gcc.dg/Wparentheses-10.c: New tests.
* gcc.dg/Wparentheses-5.c: Remove XFAILs.
2004-07-18 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de> 2004-07-18 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
PR fortran/16465 PR fortran/16465
......
// Test operation of -Wparentheses. Warnings for assignments used as
// truth-values. Essentially the same as gcc.dg/Wparentheses-3.c.
// Origin: Joseph Myers <jsm@polyomino.org.uk>
// { dg-do compile }
// { dg-options "-Wparentheses" }
int foo (int);
int a, b, c;
bool d;
void
bar (void)
{
if (a = b) // { dg-warning "assignment" "correct warning" }
foo (0);
if ((a = b))
foo (1);
if (a = a) // { dg-warning "assignment" "correct warning" }
foo (2);
if ((a = a))
foo (3);
if (b = c) // { dg-warning "assignment" "correct warning" }
foo (4);
else
foo (5);
if ((b = c))
foo (6);
else
foo (7);
if (b = b) // { dg-warning "assignment" "correct warning" }
foo (8);
else
foo (9);
if ((b = b))
foo (10);
else
foo (11);
while (c = b) // { dg-warning "assignment" "correct warning" }
foo (12);
while ((c = b))
foo (13);
while (c = c) // { dg-warning "assignment" "correct warning" }
foo (14);
while ((c = c))
foo (15);
do foo (16); while (a = b); // { dg-warning "assignment" "correct warning" }
do foo (17); while ((a = b));
do foo (18); while (a = a); // { dg-warning "assignment" "correct warning" }
do foo (19); while ((a = a));
for (;c = b;) // { dg-warning "assignment" "correct warning" }
foo (20);
for (;(c = b);)
foo (21);
for (;c = c;) // { dg-warning "assignment" "correct warning" }
foo (22);
for (;(c = c);)
foo (23);
d = a = b; // { dg-warning "assignment" "correct warning" }
foo (24);
d = (a = b);
foo (25);
d = a = a; // { dg-warning "assignment" "correct warning" }
foo (26);
d = (a = a);
foo (27);
}
// Test operation of -Wparentheses. Warnings for assignments used as
// truth-values shouldn't apply other than for plain assignment.
// Essentially the same as gcc.dg/Wparentheses-10.c.
// Origin: Joseph Myers <jsm@polyomino.org.uk>
// { dg-do compile }
// { dg-options "-Wparentheses" }
int foo (int);
int a, b, c;
bool d;
void
bar (void)
{
if (a += b)
foo (0);
if (a -= a)
foo (1);
if (b *= c)
foo (2);
else
foo (3);
if (b /= b)
foo (4);
else
foo (5);
while (c %= b)
foo (6);
while (c <<= c)
foo (7);
do foo (8); while (a >>= b);
do foo (9); while (a &= a);
for (;c ^= b;)
foo (10);
for (;c |= c;)
foo (11);
d = a += b;
foo (12);
d = a -= a;
foo (13);
}
/* Test operation of -Wparentheses. Warnings for assignments used as
truth-values shouldn't apply other than for plain assignment. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */
/* { dg-options "-Wparentheses -std=gnu99" } */
int foo (int);
int a, b, c;
_Bool d;
void
bar (void)
{
if (a += b)
foo (0);
if (a -= a)
foo (1);
if (b *= c)
foo (2);
else
foo (3);
if (b /= b)
foo (4);
else
foo (5);
while (c %= b)
foo (6);
while (c <<= c)
foo (7);
do foo (8); while (a >>= b);
do foo (9); while (a &= a);
for (;c ^= b;)
foo (10);
for (;c |= c;)
foo (11);
d = a += b;
foo (12);
d = a -= a;
foo (13);
}
...@@ -13,10 +13,10 @@ bar (int a, int b, int c) ...@@ -13,10 +13,10 @@ bar (int a, int b, int c)
foo (a && b || c); /* { dg-warning "parentheses" "correct warning" } */ foo (a && b || c); /* { dg-warning "parentheses" "correct warning" } */
foo ((a && b) || c); foo ((a && b) || c);
foo (a && (b || c)); foo (a && (b || c));
foo (1 && 2 || c); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ foo (1 && 2 || c); /* { dg-warning "parentheses" "correct warning" } */
foo ((1 && 2) || c); foo ((1 && 2) || c);
foo (1 && (2 || c)); foo (1 && (2 || c));
foo (1 && 2 || 3); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ foo (1 && 2 || 3); /* { dg-warning "parentheses" "correct warning" } */
foo ((1 && 2) || 3); foo ((1 && 2) || 3);
foo (1 && (2 || 3)); foo (1 && (2 || 3));
foo (a || b && c); /* { dg-warning "parentheses" "correct warning" } */ foo (a || b && c); /* { dg-warning "parentheses" "correct warning" } */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment