diff options
author | Marek Polacek <polacek@redhat.com> | 2015-07-27 12:40:45 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2015-07-27 12:40:45 +0000 |
commit | 05b28fd6f91016151e758c2414d7245a54512c99 (patch) | |
tree | a50a804e0d3bacf0015564dabec36d9c9121f14d /gcc/c-family | |
parent | 0fd357f27d55de9d05662ebce1f166974891f52e (diff) | |
download | gcc-05b28fd6f91016151e758c2414d7245a54512c99.zip gcc-05b28fd6f91016151e758c2414d7245a54512c99.tar.gz gcc-05b28fd6f91016151e758c2414d7245a54512c99.tar.bz2 |
re PR c++/66555 (Fails to warn for if (j == 0 && i == i))
PR c++/66555
PR c/54979
* c-common.c (find_array_ref_with_const_idx_r): New function.
(warn_tautological_cmp): New function.
* c-common.h (warn_tautological_cmp): Declare.
* c.opt (Wtautological-compare): New option.
* c-typeck.c (parser_build_binary_op): Call warn_tautological_cmp.
* call.c (build_new_op_1): Call warn_tautological_cmp.
* pt.c (tsubst_copy_and_build): Use sentinel to suppress tautological
compare warnings.
* doc/invoke.texi: Document -Wtautological-compare.
* c-c++-common/Wtautological-compare-1.c: New test.
From-SVN: r226242
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 64 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 4 |
4 files changed, 78 insertions, 0 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index caedf8e..4d2ed59 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2015-07-27 Marek Polacek <polacek@redhat.com> + + PR c++/66555 + PR c/54979 + * c-common.c (find_array_ref_with_const_idx_r): New function. + (warn_tautological_cmp): New function. + * c-common.h (warn_tautological_cmp): Declare. + * c.opt (Wtautological-compare): New option. + 2015-07-23 Marek Polacek <polacek@redhat.com> * c-ubsan.c (ubsan_instrument_division): Use unshare_expr throughout. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index c94596f..6a79b95 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1861,6 +1861,70 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, } } +/* Helper function for warn_tautological_cmp. Look for ARRAY_REFs + with constant indices. */ + +static tree +find_array_ref_with_const_idx_r (tree *expr_p, int *walk_subtrees, void *data) +{ + tree expr = *expr_p; + + if ((TREE_CODE (expr) == ARRAY_REF + || TREE_CODE (expr) == ARRAY_RANGE_REF) + && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST) + { + *(bool *) data = true; + *walk_subtrees = 0; + } + + return NULL_TREE; +} + +/* Warn if a self-comparison always evaluates to true or false. LOC + is the location of the comparison with code CODE, LHS and RHS are + operands of the comparison. */ + +void +warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs) +{ + if (TREE_CODE_CLASS (code) != tcc_comparison) + return; + + /* We do not warn for constants because they are typical of macro + expansions that test for features, sizeof, and similar. */ + if (CONSTANT_CLASS_P (lhs) || CONSTANT_CLASS_P (rhs)) + return; + + /* Don't warn for e.g. + HOST_WIDE_INT n; + ... + if (n == (long) n) ... + */ + if ((CONVERT_EXPR_P (lhs) || TREE_CODE (lhs) == NON_LVALUE_EXPR) + || (CONVERT_EXPR_P (rhs) || TREE_CODE (rhs) == NON_LVALUE_EXPR)) + return; + + if (operand_equal_p (lhs, rhs, 0)) + { + /* Don't warn about array references with constant indices; + these are likely to come from a macro. */ + bool found = false; + walk_tree_without_duplicates (&lhs, find_array_ref_with_const_idx_r, + &found); + if (found) + return; + const bool always_true = (code == EQ_EXPR || code == LE_EXPR + || code == GE_EXPR || code == UNLE_EXPR + || code == UNGE_EXPR || code == UNEQ_EXPR); + if (always_true) + warning_at (loc, OPT_Wtautological_compare, + "self-comparison always evaluates to true"); + else + warning_at (loc, OPT_Wtautological_compare, + "self-comparison always evaluates to false"); + } +} + /* Warn about logical not used on the left hand side operand of a comparison. This function assumes that the LHS is inside of TRUTH_NOT_EXPR. Do not warn if RHS is of a boolean type. */ diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index a198e79..f0640c7 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -812,6 +812,7 @@ extern bool warn_if_unused_value (const_tree, location_t); extern void warn_logical_operator (location_t, enum tree_code, tree, enum tree_code, tree, enum tree_code, tree); extern void warn_logical_not_parentheses (location_t, enum tree_code, tree); +extern void warn_tautological_cmp (location_t, enum tree_code, tree, tree); extern void check_main_parameter_types (tree decl); extern bool c_determine_visibility (tree); extern bool vector_types_compatible_elements_p (tree, tree); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index dc760d7..cb3af48 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -848,6 +848,10 @@ Wsystem-headers C ObjC C++ ObjC++ Warning ; Documented in common.opt +Wtautological-compare +C ObjC C++ ObjC++ Var(warn_tautological_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) +Warn if a comparison always evaluates to true or false + Wterminate C++ ObjC++ Warning Var(warn_terminate) Init(1) Warn if a throw expression will always result in a call to terminate() |