diff options
Diffstat (limited to 'gcc/c-family/c-warn.c')
-rw-r--r-- | gcc/c-family/c-warn.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 4c0bdf9..b0f6da0 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -322,7 +322,8 @@ find_array_ref_with_const_idx_r (tree *expr_p, int *, void *) if ((TREE_CODE (expr) == ARRAY_REF || TREE_CODE (expr) == ARRAY_RANGE_REF) - && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST) + && (TREE_CODE (fold_for_warn (TREE_OPERAND (expr, 1))) + == INTEGER_CST)) return integer_type_node; return NULL_TREE; @@ -334,7 +335,7 @@ find_array_ref_with_const_idx_r (tree *expr_p, int *, void *) of this comparison. */ static void -warn_tautological_bitwise_comparison (location_t loc, tree_code code, +warn_tautological_bitwise_comparison (const op_location_t &loc, tree_code code, tree lhs, tree rhs) { if (code != EQ_EXPR && code != NE_EXPR) @@ -389,29 +390,64 @@ warn_tautological_bitwise_comparison (location_t loc, tree_code code, if (res == cstw) return; + binary_op_rich_location richloc (loc, lhs, rhs, false); if (code == EQ_EXPR) - warning_at (loc, OPT_Wtautological_compare, + warning_at (&richloc, OPT_Wtautological_compare, "bitwise comparison always evaluates to false"); else - warning_at (loc, OPT_Wtautological_compare, + warning_at (&richloc, OPT_Wtautological_compare, "bitwise comparison always evaluates to true"); } +/* Given LOC_A and LOC_B from macro expansions, return true if + they are "spelled the same" i.e. if they are both directly from + expansion of the same non-function-like macro. */ + +static bool +spelled_the_same_p (location_t loc_a, location_t loc_b) +{ + gcc_assert (from_macro_expansion_at (loc_a)); + gcc_assert (from_macro_expansion_at (loc_b)); + + const line_map_macro *map_a + = linemap_check_macro (linemap_lookup (line_table, loc_a)); + + const line_map_macro *map_b + = linemap_check_macro (linemap_lookup (line_table, loc_b)); + + if (map_a->macro == map_b->macro) + if (!cpp_fun_like_macro_p (map_a->macro)) + return true; + + return false; +} + /* 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) +warn_tautological_cmp (const op_location_t &loc, enum tree_code code, + tree lhs, tree rhs) { if (TREE_CODE_CLASS (code) != tcc_comparison) return; /* Don't warn for various macro expansions. */ - if (from_macro_expansion_at (loc) - || from_macro_expansion_at (EXPR_LOCATION (lhs)) - || from_macro_expansion_at (EXPR_LOCATION (rhs))) + if (from_macro_expansion_at (loc)) return; + bool lhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (lhs)); + bool rhs_in_macro = from_macro_expansion_at (EXPR_LOCATION (rhs)); + if (lhs_in_macro || rhs_in_macro) + { + /* Don't warn if exactly one is from a macro. */ + if (!(lhs_in_macro && rhs_in_macro)) + return; + + /* If both are in a macro, only warn if they're spelled the same. */ + if (!spelled_the_same_p (EXPR_LOCATION (lhs), EXPR_LOCATION (rhs))) + return; + } warn_tautological_bitwise_comparison (loc, code, lhs, rhs); @@ -446,11 +482,12 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs) const bool always_true = (code == EQ_EXPR || code == LE_EXPR || code == GE_EXPR || code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR); + binary_op_rich_location richloc (loc, lhs, rhs, false); if (always_true) - warning_at (loc, OPT_Wtautological_compare, + warning_at (&richloc, OPT_Wtautological_compare, "self-comparison always evaluates to true"); else - warning_at (loc, OPT_Wtautological_compare, + warning_at (&richloc, OPT_Wtautological_compare, "self-comparison always evaluates to false"); } } |