diff options
author | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-19 11:04:13 +0000 |
---|---|---|
committer | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-04-19 11:04:13 +0000 |
commit | 03033af4c1f68904bbecf8aaa95b58d285847c5c (patch) | |
tree | bcaf465ab5ba49fd67b08ce44d9d4349c54cc20e | |
parent | 3e682e423ffe1603a4533e89fc766a39c86caeef (diff) | |
download | gcc-03033af4c1f68904bbecf8aaa95b58d285847c5c.tar.gz |
2009-04-19 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c/32061
PR c++/36954
* doc/invoke.texi: Add -Wlogical-op to -Wextra.
* common.opt (Wlogical-op): Move from here...
* c.opt (Wlogical-op): ... to here.
* c-typeck.c (parser_build_binary_op): Update call to
warn_logical_operator.
* c-opts.c (c_common_post_options): Enable warn_logical_op with
extra_warnings.
* c-common.c (warn_logical_op): Update.
* c-common.h (warn_logical_op): Update declaration.
cp/
* call.c (build_new_op): Save the original codes of operands
before folding.
testsuite/
* gcc.dg/pr32061.c: New.
* gcc.dg/Wlogical-op-1.c: Update.
* g++.dg/warn/Wlogical-op-1.C: Update.
* g++.dg/warn/pr36954.C: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146344 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c-common.c | 65 | ||||
-rw-r--r-- | gcc/c-common.h | 3 | ||||
-rw-r--r-- | gcc/c-opts.c | 2 | ||||
-rw-r--r-- | gcc/c-typeck.c | 5 | ||||
-rw-r--r-- | gcc/c.opt | 4 | ||||
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 28 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wlogical-op-1.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/pr36954.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wlogical-op-1.c | 50 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr32061.c | 10 |
15 files changed, 195 insertions, 66 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 066f16ca695..09f17e570e3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2009-04-19 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/32061 + PR c++/36954 + * doc/invoke.texi: Add -Wlogical-op to -Wextra. + * common.opt (Wlogical-op): Move from here... + * c.opt (Wlogical-op): ... to here. + * c-typeck.c (parser_build_binary_op): Update call to + warn_logical_operator. + * c-opts.c (c_common_post_options): Enable warn_logical_op with + extra_warnings. + * c-common.c (warn_logical_op): Update. + * c-common.h (warn_logical_op): Update declaration. + 2009-04-19 Eric Botcazou <ebotcazou@adacore.com> * tree.c (protected_set_expr_location): Fix formatting. diff --git a/gcc/c-common.c b/gcc/c-common.c index 77f7ebc4d62..735c8e0b5c4 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1712,38 +1712,43 @@ overflow_warning (tree value) } } - -/* Warn about use of a logical || / && operator being used in a - context where it is likely that the bitwise equivalent was intended - by the programmer. CODE is the TREE_CODE of the operator, ARG1 - and ARG2 the arguments. */ +/* Warn about uses of logical || / && operator in a context where it + is likely that the bitwise equivalent was intended by the + programmer. We have seen an expression in which CODE is a binary + operator used to combine expressions OP_LEFT and OP_RIGHT, which + before folding had CODE_LEFT and CODE_RIGHT. */ void -warn_logical_operator (enum tree_code code, tree arg1, tree - arg2) -{ - switch (code) - { - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_AND_EXPR: - if (!TREE_NO_WARNING (arg1) - && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) - && !CONSTANT_CLASS_P (arg1) - && TREE_CODE (arg2) == INTEGER_CST - && !integer_zerop (arg2)) - { - warning (OPT_Wlogical_op, - "logical %<%s%> with non-zero constant " - "will always evaluate as true", - ((code == TRUTH_ANDIF_EXPR) - || (code == TRUTH_AND_EXPR)) ? "&&" : "||"); - TREE_NO_WARNING (arg1) = true; - } - break; - default: - break; +warn_logical_operator (location_t location, enum tree_code code, + enum tree_code code_left, tree op_left, + enum tree_code ARG_UNUSED (code_right), tree op_right) +{ + if (code != TRUTH_ANDIF_EXPR + && code != TRUTH_AND_EXPR + && code != TRUTH_ORIF_EXPR + && code != TRUTH_OR_EXPR) + return; + + /* Warn if &&/|| are being used in a context where it is + likely that the bitwise equivalent was intended by the + programmer. That is, an expression such as op && MASK + where op should not be any boolean expression, nor a + constant, and mask seems to be a non-boolean integer constant. */ + if (!truth_value_p (code_left) + && INTEGRAL_TYPE_P (TREE_TYPE (op_left)) + && !CONSTANT_CLASS_P (op_left) + && !TREE_NO_WARNING (op_left) + && TREE_CODE (op_right) == INTEGER_CST + && !integer_zerop (op_right) + && !integer_onep (op_right)) + { + if (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR) + warning_at (location, OPT_Wlogical_op, "logical %<or%>" + " applied to non-boolean constant"); + else + warning_at (location, OPT_Wlogical_op, "logical %<and%>" + " applied to non-boolean constant"); + TREE_NO_WARNING (op_left) = true; } } diff --git a/gcc/c-common.h b/gcc/c-common.h index 061cbe3ad0c..723f8b5ef18 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -801,7 +801,8 @@ extern bool strict_aliasing_warning (tree, tree, tree); extern void warnings_for_convert_and_check (tree, tree, tree); extern tree convert_and_check (tree, tree); extern void overflow_warning (tree); -extern void warn_logical_operator (enum tree_code, tree, tree); +extern void warn_logical_operator (location_t, enum tree_code, + enum tree_code, tree, enum tree_code, tree); extern void check_main_parameter_types (tree decl); extern bool c_determine_visibility (tree); extern bool same_scalar_type_ignoring_signedness (tree, tree); diff --git a/gcc/c-opts.c b/gcc/c-opts.c index f61952289c8..ece4d7f8a4a 100644 --- a/gcc/c-opts.c +++ b/gcc/c-opts.c @@ -1080,6 +1080,8 @@ c_common_post_options (const char **pfilename) warn_override_init = extra_warnings; if (warn_ignored_qualifiers == -1) warn_ignored_qualifiers = extra_warnings; + if (warn_logical_op == -1) + warn_logical_op = extra_warnings; /* -Wpointer-sign is disabled by default, but it is enabled if any of -Wall or -pedantic are given. */ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 77eafbff009..821f4ce13a6 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2925,8 +2925,9 @@ parser_build_binary_op (location_t location, enum tree_code code, if (warn_parentheses) warn_about_parentheses (code, code1, arg1.value, code2, arg2.value); - if (TREE_CODE_CLASS (code1) != tcc_comparison) - warn_logical_operator (code, arg1.value, arg2.value); + if (warn_logical_op) + warn_logical_operator (input_location, code, + code1, arg1.value, code2, arg2.value); /* Warn about comparisons against string literals, with the exception of testing for equality or inequality of a string literal with NULL. */ diff --git a/gcc/c.opt b/gcc/c.opt index 2a1b74076cb..b3e7dd7db18 100644 --- a/gcc/c.opt +++ b/gcc/c.opt @@ -284,6 +284,10 @@ Winvalid-pch C ObjC C++ ObjC++ Warning Warn about PCH files that are found but not used +Wlogical-op +C ObjC C++ ObjC++ Var(warn_logical_op) Init(-1) Warning +Warn when a logical operator is suspiciously always evaluating to true or false + Wlong-long C ObjC C++ ObjC++ Var(warn_long_long) Init(1) Warning Do not warn about using \"long long\" when -pedantic diff --git a/gcc/common.opt b/gcc/common.opt index 20dd071cd7c..c0f6b9e6d09 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -128,10 +128,6 @@ Wlarger-than= Common RejectNegative Joined UInteger Warning -Wlarger-than=<number> Warn if an object is larger than <number> bytes -Wlogical-op -Common Warning Var(warn_logical_op) -Warn when a logical operator is suspicously always evaluating to true or false - Wunsafe-loop-optimizations Common Var(warn_unsafe_loop_optimizations) Warning Warn if the loop cannot be optimized due to nontrivial assumptions. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bfa05e545d8..259aa8e7a9d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2009-04-19 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/32061 + PR c++/36954 + * call.c (build_new_op): Save the original codes of operands + before folding. + 2009-04-18 Kazu Hirata <kazu@codesourcery.com> * cp-tree.h: Remove the prototype for insert_block. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index f6c24b69086..feb3004517f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3897,11 +3897,12 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, tree result = NULL_TREE; bool result_valid_p = false; enum tree_code code2 = NOP_EXPR; + enum tree_code code_orig_arg1 = ERROR_MARK; + enum tree_code code_orig_arg2 = ERROR_MARK; conversion *conv; void *p; bool strict_p; bool any_viable_p; - bool expl_eq_arg1 = false; if (error_operand_p (arg1) || error_operand_p (arg2) @@ -3935,8 +3936,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, case TRUTH_ANDIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: - if (COMPARISON_CLASS_P (arg1)) - expl_eq_arg1 = true; + /* These are saved for the sake of warn_logical_operator. */ + code_orig_arg1 = TREE_CODE (arg1); + code_orig_arg2 = TREE_CODE (arg2); + default: break; } @@ -4140,8 +4143,16 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, if (conv->kind == ck_ref_bind) conv = conv->u.next; arg1 = convert_like (conv, arg1, complain); + if (arg2) { + /* We need to call warn_logical_operator before + converting arg2 to a boolean_type. */ + if (complain & tf_warning) + warn_logical_operator (input_location, code, + code_orig_arg1, arg1, + code_orig_arg2, arg2); + conv = cand->convs[1]; if (conv->kind == ck_ref_bind) conv = conv->u.next; @@ -4155,12 +4166,6 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, arg3 = convert_like (conv, arg3, complain); } - if (!expl_eq_arg1) - { - if (complain & tf_warning) - warn_logical_operator (code, arg1, arg2); - expl_eq_arg1 = true; - } } } @@ -4185,8 +4190,9 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, case TRUTH_ORIF_EXPR: case TRUTH_AND_EXPR: case TRUTH_OR_EXPR: - if (!expl_eq_arg1) - warn_logical_operator (code, arg1, arg2); + warn_logical_operator (input_location, code, + code_orig_arg1, arg1, code_orig_arg2, arg2); + /* Fall through. */ case PLUS_EXPR: case MINUS_EXPR: case MULT_EXPR: diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 3c49a8d81b0..e1dd0e0ad46 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2804,6 +2804,7 @@ name is still supported, but the newer name is more descriptive.) @gccoptlist{-Wclobbered @gol -Wempty-body @gol -Wignored-qualifiers @gol +-Wlogical-op @gol -Wmissing-field-initializers @gol -Wmissing-parameter-type @r{(C only)} @gol -Wold-style-declaration @r{(C only)} @gol @@ -3790,7 +3791,8 @@ programmer intended to use @code{strcmp}. This warning is enabled by @opindex Wno-logical-op Warn about suspicious uses of logical operators in expressions. This includes using logical operators in contexts where a -bit-wise operator is likely to be expected. +bit-wise operator is likely to be expected. This warning is enabled by +@option{-Wextra}. @item -Waggregate-return @opindex Waggregate-return diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c87827bd08b..361d93de4dd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2009-04-19 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/32061 + PR c++/36954 + * gcc.dg/pr32061.c: New. + * gcc.dg/Wlogical-op-1.c: Update. + * g++.dg/warn/Wlogical-op-1.C: Update. + * g++.dg/warn/pr36954.C: New. + 2009-04-18 Joseph Myers <joseph@codesourcery.com> PR c/27676 diff --git a/gcc/testsuite/g++.dg/warn/Wlogical-op-1.C b/gcc/testsuite/g++.dg/warn/Wlogical-op-1.C index f67ab89f867..61d4a9dae23 100644 --- a/gcc/testsuite/g++.dg/warn/Wlogical-op-1.C +++ b/gcc/testsuite/g++.dg/warn/Wlogical-op-1.C @@ -28,20 +28,39 @@ extern testenum testa(); void foo() { - if ( f && b2 ) // { dg-warning "always evaluate as" } + if ( f && b2 ) // { dg-warning "logical" } do_something(1); - if ( c && b2 ) // { dg-warning "always evaluate as" } + if ( c && b2 ) // { dg-warning "logical" } do_something(2); - if ( b2 && c == a ) // { dg-bogus "always evaluate as" } + if ( b2 && c == a ) // { dg-bogus "logical" } do_something(101); if ( 1 && c ) - do_something(102); // { dg-bogus "always evaluate as" } - if ( t2 && b2 ) // { dg-bogus "always evaluate as" } + do_something(102); // { dg-bogus "logical" } + if ( t2 && b2 ) // { dg-bogus "logical" } do_something(103); - if ( true && c == a ) // { dg-bogus "always evaluate as" } + if ( true && c == a ) // { dg-bogus "logical" } do_something(104); - if ( b2 && true ) // { dg-bogus "always evaluate as" } + if ( b2 && true ) // { dg-bogus "logical" } do_something(105); } + +void bar() +{ + if ( f || b2 ) // { dg-warning "logical" } + do_something(1); + if ( c || b2 ) // { dg-warning "logical" } + do_something(2); + + if ( b2 || c == a ) // { dg-bogus "logical" } + do_something(101); + if ( 1 || c ) + do_something(102); // { dg-bogus "logical" } + if ( t2 || b2 ) // { dg-bogus "logical" } + do_something(103); + if ( true || c == a ) // { dg-bogus "logical" } + do_something(104); + if ( b2 || true ) // { dg-bogus "logical" } + do_something(105); +} diff --git a/gcc/testsuite/g++.dg/warn/pr36954.C b/gcc/testsuite/g++.dg/warn/pr36954.C new file mode 100644 index 00000000000..92cea2f3876 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr36954.C @@ -0,0 +1,23 @@ +// PR c++/36954 +// { dg-do compile } +// { dg-options "-Wlogical-op -Wextra -Wall" } + +template<class C> void Test() +{ + if ((1 == 2) || (true)) { + } + + if ((1 == 2) || (!false)) { + } + + if (false || true) { + } +} + + + +int main() { + if ((1 == 2) || (true)) { + } +} + diff --git a/gcc/testsuite/gcc.dg/Wlogical-op-1.c b/gcc/testsuite/gcc.dg/Wlogical-op-1.c index d9687bf09a2..2cbb9806e03 100644 --- a/gcc/testsuite/gcc.dg/Wlogical-op-1.c +++ b/gcc/testsuite/gcc.dg/Wlogical-op-1.c @@ -14,34 +14,64 @@ extern int testa(); void foo() { - if ( testa() && b ) /* { dg-warning "always evaluate as" } */ + if ( testa() && b ) /* { dg-warning "logical" } */ (void)testa(); - if ( c && b ) /* { dg-warning "always evaluate as" } */ + if ( c && b ) /* { dg-warning "logical" } */ (void)testa(); - if ( c && 0x42 ) /* { dg-warning "always evaluate as" } */ + if ( c && 0x42 ) /* { dg-warning "logical" } */ (void)testa(); - if ( c && 0x42 ) /* { dg-warning "always evaluate as" } */ + if ( c && 0x80 >>6) /* { dg-warning "logical" } */ + (void)testa(); + + + if ( b && c == a ) /* { dg-bogus "logical" } */ + (void)testa(); + + if ( 1 && c ) /* { dg-bogus "logical" } */ + (void)testa(); + + if ( t2 && b ) /* { dg-bogus "logical" } */ + (void)testa(); + + if ( 0 && c == a ) /* { dg-bogus "logical" } */ + (void)testa(); + + if ( b && 1 ) /* { dg-bogus "logical" } */ + (void)testa(); +} + + +void bar() +{ + if ( testa() || b ) /* { dg-warning "logical" } */ + (void)testa(); + + if ( c || b ) /* { dg-warning "logical" } */ + (void)testa(); + + if ( c || 0x42 ) /* { dg-warning "logical" } */ (void) testa(); - if ( c && 0x80 >>6) /* { dg-warning "always evaluate as" } */ + if ( c || 0x80 >>6) /* { dg-warning "logical" } */ (void)testa(); - if ( b && c == a ) /* { dg-bogus "always evaluate as" } */ + if ( b || c == a ) /* { dg-bogus "logical" } */ (void)testa(); - if ( 1 && c ) /* { dg-bogus "always evaluate as" } */ + if ( 1 || c ) /* { dg-bogus "logical" } */ (void)testa(); - if ( t2 && b ) /* { dg-bogus "always evaluate as" } */ + if ( t2 || b ) /* { dg-bogus "logical" } */ (void)testa(); - if ( 0 && c == a ) /* { dg-bogus "always evaluate as" } */ + if ( 0 || c == a ) /* { dg-bogus "logical" } */ (void)testa(); - if ( b && 1 ) /* { dg-bogus "always evaluate as" } */ + if ( b || 1 ) /* { dg-bogus "logical" } */ (void)testa(); } + diff --git a/gcc/testsuite/gcc.dg/pr32061.c b/gcc/testsuite/gcc.dg/pr32061.c new file mode 100644 index 00000000000..dc1a916f1bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr32061.c @@ -0,0 +1,10 @@ +/* PR c/32061 + { dg-do compile } + { dg-options "-Wlogical-op -Wall -Wextra" } +*/ +#define FORCE 1 +#define FLAG 1 +int func (int resp, int flags) +{ + return (resp && (FORCE || (FLAG & flags))); +} |