aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-07-27 12:40:45 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-07-27 12:40:45 +0000
commit05b28fd6f91016151e758c2414d7245a54512c99 (patch)
treea50a804e0d3bacf0015564dabec36d9c9121f14d /gcc/c-family
parent0fd357f27d55de9d05662ebce1f166974891f52e (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/c-family/c-common.c64
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c.opt4
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()