summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c22
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-gimplify.c86
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull2.C9
5 files changed, 45 insertions, 84 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 33f28845fe7..a22485fcbd6 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-01-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/68767
+ * c-common.c (check_function_arguments_recurse): Fold the whole
+ COND_EXPR, not just the condition.
+
2016-01-18 Tom de Vries <tom@codesourcery.com>
* c-omp.c (c_oacc_split_loop_clauses): Don't copy OMP_CLAUSE_REDUCTION,
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 0bfa1f6879e..1a2c21b8939 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9765,15 +9765,19 @@ check_function_arguments_recurse (void (*callback)
if (TREE_CODE (param) == COND_EXPR)
{
- tree cond = fold_for_warn (TREE_OPERAND (param, 0));
- /* Check both halves of the conditional expression. */
- if (!integer_zerop (cond))
- check_function_arguments_recurse (callback, ctx,
- TREE_OPERAND (param, 1), param_num);
- if (!integer_nonzerop (cond))
- check_function_arguments_recurse (callback, ctx,
- TREE_OPERAND (param, 2), param_num);
- return;
+ /* Simplify to avoid warning for an impossible case. */
+ param = fold_for_warn (param);
+ if (TREE_CODE (param) == COND_EXPR)
+ {
+ /* Check both halves of the conditional expression. */
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 1),
+ param_num);
+ check_function_arguments_recurse (callback, ctx,
+ TREE_OPERAND (param, 2),
+ param_num);
+ return;
+ }
}
(*callback) (ctx, param, param_num);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6b7e81b0733..0ae29124658 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2016-01-18 Jason Merrill <jason@redhat.com>
+
+ PR c++/68767
+ * cp-gimplify.c (cp_fold) [COND_EXPR]: Simplify. Do fold COND_EXPR.
+ (contains_label_1, contains_label_p): Remove.
+
2016-01-16 Patrick Palka <ppalka@gcc.gnu.org>
PR c++/69091
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index c0ee8e43466..e151753b3e4 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1851,38 +1851,6 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
&& DECL_OMP_PRIVATIZED_MEMBER (decl);
}
-/* Callback for walk_tree, looking for LABEL_EXPR. Return *TP if it is
- a LABEL_EXPR; otherwise return NULL_TREE. Do not check the subtrees
- of GOTO_EXPR. */
-
-static tree
-contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
-{
- switch (TREE_CODE (*tp))
- {
- case LABEL_EXPR:
- return *tp;
-
- case GOTO_EXPR:
- *walk_subtrees = 0;
-
- /* ... fall through ... */
-
- default:
- return NULL_TREE;
- }
-}
-
-/* Return whether the sub-tree ST contains a label which is accessible from
- outside the sub-tree. */
-
-static bool
-contains_label_p (tree st)
-{
- return
- walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE;
-}
-
/* Perform folding on expression X. */
tree
@@ -2110,54 +2078,22 @@ cp_fold (tree x)
case VEC_COND_EXPR:
case COND_EXPR:
+ /* Don't bother folding a void condition, since it can't produce a
+ constant value. Also, some statement-level uses of COND_EXPR leave
+ one of the branches NULL, so folding would crash. */
+ if (VOID_TYPE_P (TREE_TYPE (x)))
+ return x;
+
loc = EXPR_LOCATION (x);
op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
-
- if (TREE_SIDE_EFFECTS (op0))
- break;
-
op1 = cp_fold (TREE_OPERAND (x, 1));
op2 = cp_fold (TREE_OPERAND (x, 2));
- if (TREE_CODE (op0) == INTEGER_CST)
- {
- tree un;
-
- if (integer_zerop (op0))
- {
- un = op1;
- r = op2;
- }
- else
- {
- un = op2;
- r = op1;
- }
-
- if ((!TREE_SIDE_EFFECTS (un) || !contains_label_p (un))
- && (! VOID_TYPE_P (TREE_TYPE (r)) || VOID_TYPE_P (x)))
- {
- if (CAN_HAVE_LOCATION_P (r)
- && EXPR_LOCATION (r) != loc
- && !(TREE_CODE (r) == SAVE_EXPR
- || TREE_CODE (r) == TARGET_EXPR
- || TREE_CODE (r) == BIND_EXPR))
- {
- r = copy_node (r);
- SET_EXPR_LOCATION (r, loc);
- }
- x = r;
- }
-
- break;
- }
-
- if (VOID_TYPE_P (TREE_TYPE (x)))
- break;
-
- x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
-
- if (code != COND_EXPR)
+ if (op0 != TREE_OPERAND (x, 0)
+ || op1 != TREE_OPERAND (x, 1)
+ || op2 != TREE_OPERAND (x, 2))
+ x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+ else
x = fold (x);
break;
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull2.C b/gcc/testsuite/g++.dg/warn/Wnonnull2.C
new file mode 100644
index 00000000000..6757437de12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull2.C
@@ -0,0 +1,9 @@
+// PR c++/68767
+// { dg-options "-Wnonnull" }
+
+extern int len (const char*) __attribute__ ((__nonnull__ (1)));
+
+int f (int x)
+{
+ return len ((x ? "x" : 0) ? (x ? "x" : 0) : "x");
+}