aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2017-01-20 12:02:50 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2017-01-20 12:02:50 +0000
commit2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2 (patch)
tree39d4b3ac7435621b91ed6c263d0a91106c3b2153 /gcc/fold-const.c
parent6e9e35e127fe5d487d5be35dd740da9ec79595ff (diff)
downloadgcc-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.c55
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