diff options
author | Marek Polacek <polacek@redhat.com> | 2017-01-20 12:02:50 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2017-01-20 12:02:50 +0000 |
commit | 2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2 (patch) | |
tree | 39d4b3ac7435621b91ed6c263d0a91106c3b2153 /gcc/fold-const.c | |
parent | 6e9e35e127fe5d487d5be35dd740da9ec79595ff (diff) | |
download | gcc-2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2.zip gcc-2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2.tar.gz gcc-2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2.tar.bz2 |
re PR c/64279 (Warning missing for "(cond) ? A : A" / if(cond) expr1; else expr1; // same expression in if and else branch)
PR c/64279
* c-common.h (do_warn_duplicated_branches_r): Declare.
* c-gimplify.c (c_genericize): Walk the function tree calling
do_warn_duplicated_branches_r.
* c-warn.c (expr_from_macro_expansion_r): New.
(do_warn_duplicated_branches): New.
(do_warn_duplicated_branches_r): New.
* c.opt (Wduplicated-branches): New option.
* c-typeck.c (build_conditional_expr): Warn about duplicated branches.
* call.c (build_conditional_expr_1): Warn about duplicated branches.
* semantics.c (finish_expr_stmt): Build statement using the proper
location.
* doc/invoke.texi: Document -Wduplicated-branches.
* fold-const.c (operand_equal_p): Handle MODIFY_EXPR, INIT_EXPR,
COMPOUND_EXPR, PREDECREMENT_EXPR, PREINCREMENT_EXPR,
POSTDECREMENT_EXPR, POSTINCREMENT_EXPR, CLEANUP_POINT_EXPR, EXPR_STMT,
STATEMENT_LIST, and RETURN_EXPR. For non-pure non-const functions
return 0 only when not OEP_LEXICOGRAPHIC.
(fold_build_cleanup_point_expr): Use the expression
location when building CLEANUP_POINT_EXPR.
* tree-core.h (enum operand_equal_flag): Add OEP_LEXICOGRAPHIC.
* tree.c (add_expr): Handle error_mark_node.
* c-c++-common/Wduplicated-branches-1.c: New test.
* c-c++-common/Wduplicated-branches-10.c: New test.
* c-c++-common/Wduplicated-branches-11.c: New test.
* c-c++-common/Wduplicated-branches-12.c: New test.
* c-c++-common/Wduplicated-branches-2.c: New test.
* c-c++-common/Wduplicated-branches-3.c: New test.
* c-c++-common/Wduplicated-branches-4.c: New test.
* c-c++-common/Wduplicated-branches-5.c: New test.
* c-c++-common/Wduplicated-branches-6.c: New test.
* c-c++-common/Wduplicated-branches-7.c: New test.
* c-c++-common/Wduplicated-branches-8.c: New test.
* c-c++-common/Wduplicated-branches-9.c: New test.
* c-c++-common/Wimplicit-fallthrough-7.c: Coalesce dg-warning.
* g++.dg/cpp0x/lambda/lambda-switch.C: Move dg-warning.
* g++.dg/ext/builtin-object-size3.C: Likewise.
* g++.dg/gomp/loop-1.C: Likewise.
* g++.dg/warn/Wduplicated-branches1.C: New test.
* g++.dg/warn/Wduplicated-branches2.C: New test.
From-SVN: r244705
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index cfd270c..5576d59 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2722,6 +2722,9 @@ combine_comparisons (location_t loc, If OEP_ADDRESS_OF is set, we are actually comparing addresses of objects, not values of expressions. + If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects + such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs. + Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on any operand with side effect. This is unnecesarily conservative in the case we know that arg0 and arg1 are in disjoint code paths (such as in @@ -3154,6 +3157,23 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) case BIT_INSERT_EXPR: return OP_SAME (0) && OP_SAME (1) && OP_SAME (2); + case MODIFY_EXPR: + case INIT_EXPR: + case COMPOUND_EXPR: + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + if (flags & OEP_LEXICOGRAPHIC) + return OP_SAME (0) && OP_SAME (1); + return 0; + + case CLEANUP_POINT_EXPR: + case EXPR_STMT: + if (flags & OEP_LEXICOGRAPHIC) + return OP_SAME (0); + return 0; + default: return 0; } @@ -3190,7 +3210,7 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) cef &= ECF_CONST | ECF_PURE; else cef &= ECF_CONST; - if (!cef) + if (!cef && !(flags & OEP_LEXICOGRAPHIC)) return 0; } @@ -3269,8 +3289,39 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) } return 1; } + else if (TREE_CODE (arg0) == STATEMENT_LIST + && (flags & OEP_LEXICOGRAPHIC)) + { + /* Compare the STATEMENT_LISTs. */ + tree_stmt_iterator tsi1, tsi2; + tree body1 = CONST_CAST_TREE (arg0); + tree body2 = CONST_CAST_TREE (arg1); + for (tsi1 = tsi_start (body1), tsi2 = tsi_start (body2); ; + tsi_next (&tsi1), tsi_next (&tsi2)) + { + /* The lists don't have the same number of statements. */ + if (tsi_end_p (tsi1) ^ tsi_end_p (tsi2)) + return 0; + if (tsi_end_p (tsi1) && tsi_end_p (tsi2)) + return 1; + if (!operand_equal_p (tsi_stmt (tsi1), tsi_stmt (tsi2), + OEP_LEXICOGRAPHIC)) + return 0; + } + } return 0; + case tcc_statement: + switch (TREE_CODE (arg0)) + { + case RETURN_EXPR: + if (flags & OEP_LEXICOGRAPHIC) + return OP_SAME_WITH_NULL (0); + return 0; + default: + return 0; + } + default: return 0; } @@ -13897,7 +13948,7 @@ fold_build_cleanup_point_expr (tree type, tree expr) return expr; } - return build1 (CLEANUP_POINT_EXPR, type, expr); + return build1_loc (EXPR_LOCATION (expr), CLEANUP_POINT_EXPR, type, expr); } /* Given a pointer value OP0 and a type TYPE, return a simplified version |