From 487a92fed227132325f624811a4eb80c47da8aca Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Mon, 19 Jul 2004 09:38:52 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 31 +++ gcc/c-common.c | 4 +- gcc/c-common.h | 4 - gcc/c-parse.in | 253 ++++++++++++--------- gcc/c-tree.h | 21 +- gcc/c-typeck.c | 103 +++------ gcc/cp/ChangeLog | 5 + gcc/cp/typeck.c | 8 +- gcc/objc/objc-act.c | 8 +- gcc/testsuite/ChangeLog | 6 + gcc/testsuite/g++.dg/warn/Wparentheses-1.C | 68 ++++++ gcc/testsuite/g++.dg/warn/Wparentheses-2.C | 43 ++++ gcc/testsuite/gcc.dg/Wparentheses-10.c | 42 ++++ gcc/testsuite/gcc.dg/Wparentheses-5.c | 4 +- 14 files changed, 399 insertions(+), 201 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-1.C create mode 100644 gcc/testsuite/g++.dg/warn/Wparentheses-2.C create mode 100644 gcc/testsuite/gcc.dg/Wparentheses-10.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec21efaa9c3..b1053bf38fb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2004-07-19 Joseph S. Myers + + * 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 * config/sh/sh.c (sh_use_dfa_interface): Remove. diff --git a/gcc/c-common.c b/gcc/c-common.c index b729fd89207..1966b0da236 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -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; diff --git a/gcc/c-common.h b/gcc/c-common.h index ba7a2f87d24..89fc7eed098 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -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[]; diff --git a/gcc/c-parse.in b/gcc/c-parse.in index d70139182b3..b56bfee03ac 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -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 ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %type BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF -%type identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist exprlist -%type expr_no_commas cast_expr unary_expr primary STRING +%type identifier IDENTIFIER TYPENAME CONSTANT STRING FUNC_NAME +%type nonnull_exprlist exprlist +%type expr expr_no_commas cast_expr unary_expr primary %type declspecs_nosc_nots_nosa_noea declspecs_nosc_nots_nosa_ea %type declspecs_nosc_nots_sa_noea declspecs_nosc_nots_sa_ea %type 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. */ - $2 = save_expr (default_conversion ($1)); - $1 = lang_hooks.truthvalue_conversion ($2); - skip_evaluation += $1 == truthvalue_true_node; } + $2 = save_expr (default_conversion ($1.value)); + $1.value = lang_hooks.truthvalue_conversion ($2); + skip_evaluation += $1.value == truthvalue_true_node; } ':' expr_no_commas - { skip_evaluation -= $1 == truthvalue_true_node; - $$ = build_conditional_expr ($1, $2, $5); } + { skip_evaluation -= $1.value == truthvalue_true_node; + $$.value = build_conditional_expr ($1.value, $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 ')' - { $$ = c_start_case ($4); } + { $$ = 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); diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 7cb69baf415..d6cdc97be13 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -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); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 4befd126f08..29a9ec3abad 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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< + + * 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 Joseph S. Myers diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 21e7fe4a4ee..0e23e9a48c6 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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); } diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index cdb59d0959a..0da09aec33a 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -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 { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 59db09ff3cc..6df5bc92478 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-07-19 Joseph S. Myers + + * 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 PR fortran/16465 diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-1.C b/gcc/testsuite/g++.dg/warn/Wparentheses-1.C new file mode 100644 index 00000000000..34cb58fc77f --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-1.C @@ -0,0 +1,68 @@ +// Test operation of -Wparentheses. Warnings for assignments used as +// truth-values. Essentially the same as gcc.dg/Wparentheses-3.c. +// Origin: Joseph Myers + +// { 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); +} diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-2.C b/gcc/testsuite/g++.dg/warn/Wparentheses-2.C new file mode 100644 index 00000000000..286e2f97cc5 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-2.C @@ -0,0 +1,43 @@ +// 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 + +// { 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); +} diff --git a/gcc/testsuite/gcc.dg/Wparentheses-10.c b/gcc/testsuite/gcc.dg/Wparentheses-10.c new file mode 100644 index 00000000000..aafcae2ad36 --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wparentheses-10.c @@ -0,0 +1,42 @@ +/* Test operation of -Wparentheses. Warnings for assignments used as + truth-values shouldn't apply other than for plain assignment. */ +/* Origin: Joseph Myers */ + +/* { 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); +} diff --git a/gcc/testsuite/gcc.dg/Wparentheses-5.c b/gcc/testsuite/gcc.dg/Wparentheses-5.c index be12f73f1c2..49c65c21a05 100644 --- a/gcc/testsuite/gcc.dg/Wparentheses-5.c +++ b/gcc/testsuite/gcc.dg/Wparentheses-5.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); 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" } */ -- 2.30.2