OSDN Git Service

* c-tree.h (struct c_expr): Define.
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 19 Jul 2004 08:38:52 +0000 (08:38 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 19 Jul 2004 08:38:52 +0000 (08:38 +0000)
(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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84911 138bc75d-0d04-0410-961f-82ee72b054a4

14 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-parse.in
gcc/c-tree.h
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/objc/objc-act.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wparentheses-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wparentheses-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wparentheses-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wparentheses-5.c

index ec21efa..b1053bf 100644 (file)
@@ -1,3 +1,34 @@
+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.
index b729fd8..1966b0d 100644 (file)
@@ -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;
 
index ba7a2f8..89fc7ee 100644 (file)
@@ -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[];
index d701391..b56bfee 100644 (file)
@@ -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); }
        ;
 \f
 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);
index 7cb69ba..d6cdc97 100644 (file)
@@ -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);
index 4befd12..29a9ec3 100644 (file)
@@ -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));
 }
 \f
-/* 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.  */
index 66c5480..00ef4b5 100644 (file)
@@ -1,3 +1,8 @@
+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>
 
index 21e7fe4..0e23e9a 100644 (file)
@@ -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);
 }
index cdb59d0..0da09ae 100644 (file)
@@ -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
     {
index 59db09f..6df5bc9 100644 (file)
@@ -1,3 +1,9 @@
+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
diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-1.C b/gcc/testsuite/g++.dg/warn/Wparentheses-1.C
new file mode 100644 (file)
index 0000000..34cb58f
--- /dev/null
@@ -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 <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);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-2.C b/gcc/testsuite/g++.dg/warn/Wparentheses-2.C
new file mode 100644 (file)
index 0000000..286e2f9
--- /dev/null
@@ -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 <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);
+}
diff --git a/gcc/testsuite/gcc.dg/Wparentheses-10.c b/gcc/testsuite/gcc.dg/Wparentheses-10.c
new file mode 100644 (file)
index 0000000..aafcae2
--- /dev/null
@@ -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 <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);
+}
index be12f73..49c65c2 100644 (file)
@@ -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" } */