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>
* config/sh/sh.c (sh_use_dfa_interface): Remove.
......
......@@ -2365,9 +2365,7 @@ c_common_truthvalue_conversion (tree expr)
break;
case MODIFY_EXPR:
if (warn_parentheses
&& C_EXP_ORIGINAL_CODE (expr) == MODIFY_EXPR
&& !TREE_NO_WARNING (expr))
if (warn_parentheses && !TREE_NO_WARNING (expr))
warning ("suggest parentheses around assignment used as truth value");
break;
......
......@@ -598,10 +598,6 @@ extern int skip_evaluation;
#define C_TYPE_OBJECT_OR_INCOMPLETE_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. */
extern const struct attribute_spec c_common_attribute_table[];
extern const struct attribute_spec c_common_format_attribute_table[];
......
......@@ -102,7 +102,7 @@ do { \
%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; }
/* All identifiers that are not reserved words
......@@ -184,8 +184,9 @@ do { \
%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> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist
%type <ttype> expr_no_commas cast_expr unary_expr primary STRING
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT STRING FUNC_NAME
%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_sa_noea declspecs_nosc_nots_sa_ea
%type <ttype> declspecs_nosc_ts_nosa_noea declspecs_nosc_ts_nosa_ea
......@@ -462,8 +463,10 @@ unop: '&'
{ $$ = TRUTH_NOT_EXPR; }
;
expr: nonnull_exprlist
{ $$ = build_compound_expr ($1); }
expr: expr_no_commas
| expr ',' expr_no_commas
{ $$.value = build_compound_expr ($1.value, $3.value);
$$.original_code = COMPOUND_EXPR; }
;
exprlist:
......@@ -474,44 +477,53 @@ exprlist:
nonnull_exprlist:
expr_no_commas
{ $$ = build_tree_list (NULL_TREE, $1); }
{ $$ = build_tree_list (NULL_TREE, $1.value); }
| nonnull_exprlist ',' expr_no_commas
{ chainon ($1, build_tree_list (NULL_TREE, $3)); }
{ chainon ($1, build_tree_list (NULL_TREE, $3.value)); }
;
unary_expr:
primary
| '*' 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 cast_expr %prec UNARY
{ $$ = $2;
RESTORE_EXT_FLAGS ($1); }
| unop cast_expr %prec UNARY
{ $$ = build_unary_op ($1, $2, 0);
overflow_warning ($$); }
{ $$.value = build_unary_op ($1, $2.value, 0);
overflow_warning ($$.value);
$$.original_code = ERROR_MARK; }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
{ $$ = finish_label_address_expr ($2); }
{ $$.value = finish_label_address_expr ($2);
$$.original_code = ERROR_MARK; }
| sizeof unary_expr %prec UNARY
{ skip_evaluation--;
if (TREE_CODE ($2) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($2, 1)))
if (TREE_CODE ($2.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($2.value, 1)))
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
{ skip_evaluation--;
$$ = c_sizeof (groktypename ($3)); }
$$.value = c_sizeof (groktypename ($3));
$$.original_code = ERROR_MARK; }
| alignof unary_expr %prec UNARY
{ skip_evaluation--;
$$ = c_alignof_expr ($2); }
$$.value = c_alignof_expr ($2.value);
$$.original_code = ERROR_MARK; }
| alignof '(' typename ')' %prec HYPERUNARY
{ skip_evaluation--;
$$ = c_alignof (groktypename ($3)); }
$$.value = c_alignof (groktypename ($3));
$$.original_code = ERROR_MARK; }
| 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
{ $$ = build_unary_op (IMAGPART_EXPR, $2, 0); }
{ $$.value = build_unary_op (IMAGPART_EXPR, $2.value, 0);
$$.original_code = ERROR_MARK; }
;
sizeof:
......@@ -529,7 +541,8 @@ typeof:
cast_expr:
unary_expr
| '(' typename ')' cast_expr %prec UNARY
{ $$ = c_cast_expr ($2, $4); }
{ $$.value = c_cast_expr ($2, $4.value);
$$.original_code = ERROR_MARK; }
;
expr_no_commas:
......@@ -559,54 +572,51 @@ expr_no_commas:
| expr_no_commas '^' expr_no_commas
{ $$ = parser_build_binary_op ($2, $1, $3); }
| expr_no_commas ANDAND
{ $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_false_node; }
{ $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1.value));
skip_evaluation += $1.value == truthvalue_false_node; }
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); }
| expr_no_commas OROR
{ $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_true_node; }
{ $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1.value));
skip_evaluation += $1.value == truthvalue_true_node; }
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); }
| expr_no_commas '?'
{ $1 = lang_hooks.truthvalue_conversion
(default_conversion ($1));
skip_evaluation += $1 == truthvalue_false_node; }
{ $1.value = lang_hooks.truthvalue_conversion
(default_conversion ($1.value));
skip_evaluation += $1.value == truthvalue_false_node; }
expr ':'
{ skip_evaluation += (($1 == truthvalue_true_node)
- ($1 == truthvalue_false_node)); }
{ skip_evaluation += (($1.value == truthvalue_true_node)
- ($1.value == truthvalue_false_node)); }
expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node;
$$ = build_conditional_expr ($1, $4, $7); }
{ skip_evaluation -= $1.value == truthvalue_true_node;
$$.value = build_conditional_expr ($1.value, $4.value,
$7.value);
$$.original_code = ERROR_MARK; }
| expr_no_commas '?'
{ if (pedantic)
pedwarn ("ISO C forbids omitting the middle term of a ?: expression");
/* Make sure first operand is calculated only once. */
$<ttype>2 = save_expr (default_conversion ($1));
$1 = lang_hooks.truthvalue_conversion ($<ttype>2);
skip_evaluation += $1 == truthvalue_true_node; }
$<ttype>2 = save_expr (default_conversion ($1.value));
$1.value = lang_hooks.truthvalue_conversion ($<ttype>2);
skip_evaluation += $1.value == truthvalue_true_node; }
':' expr_no_commas
{ skip_evaluation -= $1 == truthvalue_true_node;
$$ = build_conditional_expr ($1, $<ttype>2, $5); }
{ skip_evaluation -= $1.value == truthvalue_true_node;
$$.value = build_conditional_expr ($1.value, $<ttype>2,
$5.value);
$$.original_code = ERROR_MARK; }
| expr_no_commas '=' expr_no_commas
{ char class;
$$ = build_modify_expr ($1, NOP_EXPR, $3);
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
{ $$.value = build_modify_expr ($1.value, NOP_EXPR, $3.value);
$$.original_code = MODIFY_EXPR;
}
| expr_no_commas ASSIGN expr_no_commas
{ char class;
$$ = build_modify_expr ($1, $2, $3);
/* This inhibits warnings in
c_common_truthvalue_conversion. */
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
{ $$.value = build_modify_expr ($1.value, $2, $3.value);
TREE_NO_WARNING ($$.value) = 1;
$$.original_code = ERROR_MARK;
}
;
......@@ -615,12 +625,16 @@ primary:
{
if (yychar == YYEMPTY)
yychar = YYLEX;
$$ = build_external_ref ($1, yychar == '(');
$$.value = build_external_ref ($1, yychar == '(');
$$.original_code = ERROR_MARK;
}
| CONSTANT
{ $$.value = $1; $$.original_code = ERROR_MARK; }
| STRING
{ $$.value = $1; $$.original_code = ERROR_MARK; }
| FUNC_NAME
{ $$ = fname_decl (C_RID_CODE ($$), $$); }
{ $$.value = fname_decl (C_RID_CODE ($1), $1);
$$.original_code = ERROR_MARK; }
| '(' typename ')' '{'
{ start_init (NULL_TREE, NULL, 0);
$2 = groktypename ($2);
......@@ -632,39 +646,45 @@ primary:
if (pedantic && ! flag_isoc99)
pedwarn ("ISO C90 forbids compound literals");
$$ = build_compound_literal (type, constructor);
$$.value = build_compound_literal (type, constructor);
$$.original_code = ERROR_MARK;
}
| '(' expr ')'
{ char class = TREE_CODE_CLASS (TREE_CODE ($2));
if (IS_EXPR_CODE_CLASS (class))
C_SET_EXP_ORIGINAL_CODE ($2, ERROR_MARK);
$$ = $2; }
{ $$.value = $2.value;
if (TREE_CODE ($$.value) == MODIFY_EXPR)
TREE_NO_WARNING ($$.value) = 1;
$$.original_code = ERROR_MARK; }
| '(' error ')'
{ $$ = error_mark_node; }
{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| compstmt_primary_start compstmt_nostart ')'
{ if (pedantic)
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 ')'
{ c_finish_stmt_expr ($1);
$$ = error_mark_node;
$$.value = error_mark_node;
$$.original_code = ERROR_MARK;
}
| 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 ')'
{ $$ = build_va_arg ($3, groktypename ($5)); }
{ $$.value = build_va_arg ($3.value, groktypename ($5));
$$.original_code = ERROR_MARK; }
| OFFSETOF '(' typename ',' offsetof_member_designator ')'
{ $$ = build_offsetof (groktypename ($3), $5); }
{ $$.value = build_offsetof (groktypename ($3), $5);
$$.original_code = ERROR_MARK; }
| OFFSETOF '(' error ')'
{ $$ = error_mark_node; }
{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| CHOOSE_EXPR '(' expr_no_commas ',' expr_no_commas ','
expr_no_commas ')'
{
tree c;
c = fold ($3);
c = fold ($3.value);
STRIP_NOPS (c);
if (TREE_CODE (c) != INTEGER_CST)
error ("first argument to __builtin_choose_expr not"
......@@ -672,7 +692,7 @@ primary:
$$ = integer_zerop (c) ? $7 : $5;
}
| CHOOSE_EXPR '(' error ')'
{ $$ = error_mark_node; }
{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| TYPES_COMPATIBLE_P '(' typename ',' typename ')'
{
tree e1, e2;
......@@ -680,35 +700,46 @@ primary:
e1 = TYPE_MAIN_VARIANT (groktypename ($3));
e2 = TYPE_MAIN_VARIANT (groktypename ($5));
$$ = comptypes (e1, e2)
$$.value = comptypes (e1, e2)
? build_int_2 (1, 0) : build_int_2 (0, 0);
$$.original_code = ERROR_MARK;
}
| TYPES_COMPATIBLE_P '(' error ')'
{ $$ = error_mark_node; }
{ $$.value = error_mark_node; $$.original_code = ERROR_MARK; }
| primary '[' expr ']' %prec '.'
{ $$ = build_array_ref ($1, $3); }
{ $$.value = build_array_ref ($1.value, $3.value);
$$.original_code = ERROR_MARK; }
| primary '.' identifier
{ $$ = build_component_ref ($1, $3); }
{ $$.value = build_component_ref ($1.value, $3);
$$.original_code = ERROR_MARK; }
| primary POINTSAT identifier
{
tree expr = build_indirect_ref ($1, "->");
$$ = build_component_ref (expr, $3);
tree expr = build_indirect_ref ($1.value, "->");
$$.value = build_component_ref (expr, $3);
$$.original_code = ERROR_MARK;
}
| primary PLUSPLUS
{ $$ = build_unary_op (POSTINCREMENT_EXPR, $1, 0); }
{ $$.value = build_unary_op (POSTINCREMENT_EXPR, $1.value, 0);
$$.original_code = ERROR_MARK; }
| primary MINUSMINUS
{ $$ = build_unary_op (POSTDECREMENT_EXPR, $1, 0); }
{ $$.value = build_unary_op (POSTDECREMENT_EXPR, $1.value, 0);
$$.original_code = ERROR_MARK; }
@@ifobjc
| objcmessageexpr
{ $$ = build_message_expr ($1); }
{ $$.value = build_message_expr ($1);
$$.original_code = ERROR_MARK; }
| objcselectorexpr
{ $$ = build_selector_expr ($1); }
{ $$.value = build_selector_expr ($1);
$$.original_code = ERROR_MARK; }
| objcprotocolexpr
{ $$ = build_protocol_expr ($1); }
{ $$.value = build_protocol_expr ($1);
$$.original_code = ERROR_MARK; }
| objcencodeexpr
{ $$ = build_encode_expr ($1); }
{ $$.value = build_encode_expr ($1);
$$.original_code = ERROR_MARK; }
| OBJC_STRING
{ $$ = build_objc_string_object ($1); }
{ $$.value = build_objc_string_object ($1);
$$.original_code = ERROR_MARK; }
@@end_ifobjc
;
......@@ -724,7 +755,7 @@ offsetof_member_designator:
| offsetof_member_designator '.' identifier
{ $$ = tree_cons ($3, NULL_TREE, $1); }
| offsetof_member_designator '[' expr ']'
{ $$ = tree_cons (NULL_TREE, $3, $1); }
{ $$ = tree_cons (NULL_TREE, $3.value, $1); }
;
old_style_parm_decls:
......@@ -1332,10 +1363,10 @@ typespec_nonreserved_nonattr:
@@end_ifobjc
| typeof '(' expr ')'
{ skip_evaluation--;
if (TREE_CODE ($3) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($3, 1)))
if (TREE_CODE ($3.value) == COMPONENT_REF
&& DECL_C_BIT_FIELD (TREE_OPERAND ($3.value, 1)))
error ("`typeof' applied to a bit-field");
$$ = TREE_TYPE ($3); }
$$ = TREE_TYPE ($3.value); }
| typeof '(' typename ')'
{ skip_evaluation--; $$ = groktypename ($3); }
;
......@@ -1445,6 +1476,7 @@ scspec:
init:
expr_no_commas
{ $$ = $1.value; }
| '{'
{ really_start_incremental_init (NULL_TREE); }
initlist_maybe_comma '}'
......@@ -1490,7 +1522,7 @@ initval:
initlist_maybe_comma '}'
{ process_init_element (pop_init_level (0)); }
| expr_no_commas
{ process_init_element ($1); }
{ process_init_element ($1.value); }
| error
;
......@@ -1503,11 +1535,11 @@ designator:
'.' identifier
{ set_init_label ($2); }
| '[' expr_no_commas ELLIPSIS expr_no_commas ']'
{ set_init_index ($2, $4);
{ set_init_index ($2.value, $4.value);
if (pedantic)
pedwarn ("ISO C forbids specifying range of elements to initialize"); }
| '[' expr_no_commas ']'
{ set_init_index ($2, NULL_TREE); }
{ set_init_index ($2.value, NULL_TREE); }
;
nested_function:
......@@ -1809,11 +1841,11 @@ component_declarator:
decl_attributes (&$$,
chainon ($2, all_prefix_attributes), 0); }
| declarator ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, current_declspecs, $3);
{ $$ = grokfield ($1, current_declspecs, $3.value);
decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute
{ $$ = grokfield (NULL_TREE, current_declspecs, $2);
{ $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); }
;
......@@ -1824,11 +1856,11 @@ component_notype_declarator:
decl_attributes (&$$,
chainon ($2, all_prefix_attributes), 0); }
| notype_declarator ':' expr_no_commas maybe_attribute
{ $$ = grokfield ($1, current_declspecs, $3);
{ $$ = grokfield ($1, current_declspecs, $3.value);
decl_attributes (&$$,
chainon ($4, all_prefix_attributes), 0); }
| ':' expr_no_commas maybe_attribute
{ $$ = grokfield (NULL_TREE, current_declspecs, $2);
{ $$ = grokfield (NULL_TREE, current_declspecs, $2.value);
decl_attributes (&$$,
chainon ($3, all_prefix_attributes), 0); }
;
......@@ -1852,7 +1884,7 @@ enumerator:
identifier
{ $$ = build_enumerator ($1, NULL_TREE); }
| identifier '=' expr_no_commas
{ $$ = build_enumerator ($1, $3); }
{ $$ = build_enumerator ($1, $3.value); }
;
typename:
......@@ -1919,16 +1951,16 @@ direct_absdcl1:
array_declarator:
'[' 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 ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 0); }
| '[' maybe_type_quals_attrs '*' ']'
{ $$ = build_array_declarator (NULL_TREE, $2, 0, 1); }
| '[' 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 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
......@@ -2102,7 +2134,7 @@ lineno_label:
;
condition: save_location expr
{ $$ = lang_hooks.truthvalue_conversion ($2);
{ $$ = lang_hooks.truthvalue_conversion ($2.value);
if (EXPR_P ($$))
SET_EXPR_LOCATION ($$, $1); }
;
......@@ -2177,6 +2209,7 @@ xexpr:
/* empty */
{ $$ = NULL_TREE; }
| expr
{ $$ = $1.value; }
;
for_init_stmt:
......@@ -2214,7 +2247,7 @@ for_statement:
switch_statement:
SWITCH c99_block_start '(' expr ')'
{ $<ttype>$ = c_start_case ($4); }
{ $<ttype>$ = c_start_case ($4.value); }
start_break c99_block_lineno_labeled_stmt
{ c_finish_case ($8);
if (c_break_label)
......@@ -2227,7 +2260,7 @@ switch_statement:
/* Parse a single real statement, not including any labels or compounds. */
stmt_nocomp:
expr ';'
{ $$ = c_finish_expr_stmt ($1); }
{ $$ = c_finish_expr_stmt ($1.value); }
| if_statement
{ $$ = NULL_TREE; }
| while_statement
......@@ -2245,23 +2278,23 @@ stmt_nocomp:
| RETURN ';'
{ $$ = c_finish_return (NULL_TREE); }
| RETURN expr ';'
{ $$ = c_finish_return ($2); }
{ $$ = c_finish_return ($2.value); }
| asm_stmt
| GOTO identifier ';'
{ $$ = c_finish_goto_label ($2); }
| GOTO '*' expr ';'
{ $$ = c_finish_goto_ptr ($3); }
{ $$ = c_finish_goto_ptr ($3.value); }
| ';'
{ $$ = NULL_TREE; }
@@ifobjc
| AT_THROW expr ';'
{ $$ = objc_build_throw_stmt ($2); }
{ $$ = objc_build_throw_stmt ($2.value); }
| AT_THROW ';'
{ $$ = objc_build_throw_stmt (NULL_TREE); }
| objc_try_catch_stmt
{ $$ = NULL_TREE; }
| 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:
......@@ -2312,9 +2345,9 @@ stmt:
also at the end of a compound statement. */
label: CASE expr_no_commas ':'
{ $$ = do_case ($2, NULL_TREE); }
{ $$ = do_case ($2.value, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ $$ = do_case ($2, $4); }
{ $$ = do_case ($2.value, $4.value); }
| DEFAULT ':'
{ $$ = do_case (NULL_TREE, NULL_TREE); }
| identifier save_location ':' maybe_attribute
......@@ -2408,12 +2441,13 @@ nonnull_asm_operands:
asm_operand:
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
'(' expr ')' stop_string_translation
{ $2 = build_string (IDENTIFIER_LENGTH ($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:
......@@ -2805,14 +2839,14 @@ ivar_declarator:
{
$$ = add_instance_variable (objc_ivar_context,
objc_public_flag,
$1, current_declspecs, $3);
$1, current_declspecs, $3.value);
}
| ':' expr_no_commas
{
$$ = add_instance_variable (objc_ivar_context,
objc_public_flag,
NULL_TREE,
current_declspecs, $2);
current_declspecs, $2.value);
}
;
......@@ -3068,6 +3102,7 @@ keywordarg:
receiver:
expr
{ $$ = $1.value; }
| CLASSNAME
{
$$ = get_class_reference ($1);
......
......@@ -80,10 +80,6 @@ struct lang_type GTY(())
#define C_TYPE_VARIABLE_SIZE(TYPE) TYPE_LANG_FLAG_1 (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'. */
#define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
......@@ -116,6 +112,18 @@ struct lang_type GTY(())
without prototypes. */
#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
that keep track of the progress of compilation of the current function.
Used for nested functions. */
......@@ -225,10 +233,11 @@ extern tree build_component_ref (tree, tree);
extern tree build_indirect_ref (tree, const char *);
extern tree build_array_ref (tree, tree);
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 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 build_c_cast (tree, tree);
extern tree build_modify_expr (tree, enum tree_code, tree);
......
......@@ -62,7 +62,6 @@ static tree default_function_array_conversion (tree);
static tree lookup_field (tree, tree);
static tree convert_arguments (tree, tree, 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,
int);
static void warn_for_assignment (const char *, const char *, tree, int);
......@@ -1182,9 +1181,8 @@ default_function_array_conversion (tree exp)
exp = TREE_OPERAND (exp, 0);
}
/* Preserve the original expression code. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
if (code == FUNCTION_TYPE)
{
......@@ -1294,9 +1292,8 @@ default_conversion (tree exp)
&& TREE_TYPE (TREE_OPERAND (exp, 0)) == TREE_TYPE (exp)))
exp = TREE_OPERAND (exp, 0);
/* Preserve the original expression code. */
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (exp))))
C_SET_EXP_ORIGINAL_CODE (exp, C_EXP_ORIGINAL_CODE (orig_exp));
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
/* Normally convert enums to int,
but convert wide enums to something wider. */
......@@ -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
in a way that is likely to confuse the user. */
tree
parser_build_binary_op (enum tree_code code, tree arg1, tree arg2)
struct c_expr
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;
char class1 = TREE_CODE_CLASS (TREE_CODE (arg1));
char class2 = TREE_CODE_CLASS (TREE_CODE (arg2));
enum tree_code code1 = ERROR_MARK;
enum tree_code code2 = ERROR_MARK;
enum tree_code code1 = arg1.original_code;
enum tree_code code2 = arg2.original_code;
if (TREE_CODE (result) == ERROR_MARK)
return error_mark_node;
result.value = build_binary_op (code, arg1.value, arg2.value, 1);
result.original_code = code;
if (IS_EXPR_CODE_CLASS (class1))
code1 = C_EXP_ORIGINAL_CODE (arg1);
if (IS_EXPR_CODE_CLASS (class2))
code2 = C_EXP_ORIGINAL_CODE (arg2);
if (TREE_CODE (result.value) == ERROR_MARK)
return result;
/* Check for cases such as x+y<<z which users are likely
to misinterpret. If parens are used, C_EXP_ORIGINAL_CODE
is cleared to prevent these warnings. */
to misinterpret. */
if (warn_parentheses)
{
if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
......@@ -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, arg2);
overflow_warning (result);
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);
}
unsigned_conversion_warning (result.value, arg1.value);
unsigned_conversion_warning (result.value, arg2.value);
overflow_warning (result.value);
return result;
}
......@@ -2894,44 +2870,27 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
return fold (build (COND_EXPR, result_type, ifexp, op1, op2));
}
/* Given a list of expressions, return a compound expression
that performs them all and returns the value of the last of them. */
/* Return a compound expression that performs two expressions and
returns the value of the second of them. */
tree
build_compound_expr (tree list)
build_compound_expr (tree expr1, tree expr2)
{
return internal_build_compound_expr (list, TRUE);
}
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. */
if (!first_p && integer_zerop (TREE_VALUE (list)))
return non_lvalue (TREE_VALUE (list));
return TREE_VALUE (list);
}
/* Convert arrays and functions to pointers. */
expr2 = default_function_array_conversion (expr2);
rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE);
/* Don't let (0, 0) be null pointer constant. */
if (integer_zerop (expr2))
expr2 = non_lvalue (expr2);
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
if (! TREE_SIDE_EFFECTS (expr1))
{
/* 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
any side-effects, unless it was explicitly cast to (void). */
if (warn_unused_value
&& ! (TREE_CODE (TREE_VALUE (list)) == CONVERT_EXPR
&& VOID_TYPE_P (TREE_TYPE (TREE_VALUE (list)))))
&& ! (TREE_CODE (expr1) == CONVERT_EXPR
&& VOID_TYPE_P (TREE_TYPE (expr1))))
warning ("left-hand operand of comma expression has no effect");
}
......@@ -2940,9 +2899,9 @@ internal_build_compound_expr (tree list, int first_p)
`foo() + bar(), baz()' the result of the `+' operator is not used,
so we should issue a warning. */
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. */
......
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>
Joseph S. Myers <jsm@polyomino.org.uk>
......
......@@ -4995,6 +4995,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
tree olhs = NULL_TREE;
bool plain_assign = (modifycode == NOP_EXPR);
/* Avoid duplicate error messages from operands that had errors. */
if (lhs == error_mark_node || rhs == error_mark_node)
......@@ -5254,6 +5255,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
lhstype, lhs, newrhs);
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,
convert the result back to the nominal type of LHS
......@@ -5285,7 +5288,10 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
make_node (modifycode),
/*overloaded_p=*/NULL);
if (rval)
return rval;
{
TREE_NO_WARNING (rval) = 1;
return rval;
}
}
return build_modify_expr (lhs, modifycode, rhs);
}
......
......@@ -7870,7 +7870,7 @@ get_super_receiver (void)
/* Set receiver to self. */
super_expr = build_component_ref (UOBJC_SUPER_decl, self_id);
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. */
#ifdef OBJCPLUS
......@@ -7941,12 +7941,12 @@ get_super_receiver (void)
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);
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
{
......
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>
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)
foo (a && b || c); /* { dg-warning "parentheses" "correct warning" } */
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 || 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 (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