From f479b43da091fd3ede525b7832cd69a22fb49f9a Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 2 Dec 2015 14:04:48 -0500 Subject: [PATCH] Do constant folding in warn_* functions. gcc/c-family/ * c-common.c (fold_for_warn): New. (warn_logical_operator, warn_tautological_cmp) (check_function_arguments_recurse, maybe_warn_bool_compare): Use it. gcc/cp/ * call.c (build_new_op_1): Don't fold arguments to warn_logical_operator or maybe_warn_bool_compare. From-SVN: r231198 --- gcc/c-family/ChangeLog | 4 +++ gcc/c-family/c-common.c | 44 +++++++++++++++++++++------ gcc/cp/ChangeLog | 3 ++ gcc/cp/call.c | 11 +++---- gcc/testsuite/g++.dg/warn/Wnonnull1.C | 7 +++++ 5 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wnonnull1.C diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e32635fe5b1..8aef600be70 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,5 +1,9 @@ 2015-12-02 Jason Merrill + * c-common.c (fold_for_warn): New. + (warn_logical_operator, warn_tautological_cmp) + (check_function_arguments_recurse, maybe_warn_bool_compare): Use it. + * c-common.c (c_disable_warnings, c_enable_warnings, c_fully_fold) (c_fully_fold_internal, decl_constant_value_for_optimization): Move to c/c-fold.c. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 40f86e3ab55..a8122b30309 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1094,6 +1094,19 @@ fix_string_type (tree value) return value; } +/* Fold X for consideration by one of the warning functions when checking + whether an expression has a constant value. */ + +static tree +fold_for_warn (tree x) +{ + if (c_dialect_cxx ()) + return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL); + else + /* The C front-end has already folded X appropriately. */ + return x; +} + /* Print a warning if a constant expression had overflow in folding. Invoke this function on every expression that the language requires to be a constant expression. @@ -1207,6 +1220,9 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, programmer. That is, an expression such as op && MASK where op should not be any boolean expression, nor a constant, and mask seems to be a non-boolean integer constant. */ + if (TREE_CODE (op_right) == CONST_DECL) + /* An enumerator counts as a constant. */ + op_right = DECL_INITIAL (op_right); if (!truth_value_p (code_left) && INTEGRAL_TYPE_P (TREE_TYPE (op_left)) && !CONSTANT_CLASS_P (op_left) @@ -1227,7 +1243,8 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, /* We do not warn for constants because they are typical of macro expansions that test for features. */ - if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right)) + if (CONSTANT_CLASS_P (fold_for_warn (op_left)) + || CONSTANT_CLASS_P (fold_for_warn (op_right))) return; /* This warning only makes sense with logical operands. */ @@ -1347,7 +1364,8 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs) /* We do not warn for constants because they are typical of macro expansions that test for features, sizeof, and similar. */ - if (CONSTANT_CLASS_P (fold (lhs)) || CONSTANT_CLASS_P (fold (rhs))) + if (CONSTANT_CLASS_P (fold_for_warn (lhs)) + || CONSTANT_CLASS_P (fold_for_warn (rhs))) return; /* Don't warn for e.g. @@ -9701,11 +9719,14 @@ 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. */ - check_function_arguments_recurse (callback, ctx, - TREE_OPERAND (param, 1), param_num); - check_function_arguments_recurse (callback, ctx, - TREE_OPERAND (param, 2), param_num); + 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; } @@ -11984,9 +12005,14 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0, if (TREE_CODE_CLASS (code) != tcc_comparison) return; - tree cst = (TREE_CODE (op0) == INTEGER_CST) - ? op0 : (TREE_CODE (op1) == INTEGER_CST) ? op1 : NULL_TREE; - if (!cst) + tree f, cst; + if (f = fold_for_warn (op0), + TREE_CODE (f) == INTEGER_CST) + cst = op0 = f; + else if (f = fold_for_warn (op1), + TREE_CODE (f) == INTEGER_CST) + cst = op1 = f; + else return; if (!integer_zerop (cst) && !integer_onep (cst)) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d1fe8f4fd1d..6d344ffdf3c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2015-12-02 Jason Merrill + * call.c (build_new_op_1): Don't fold arguments to + warn_logical_operator or maybe_warn_bool_compare. + * cp-gimplify.c (cp_fold_maybe_rvalue, cp_fold_rvalue): New. (c_fully_fold): Use cp_fold_rvalue. (cp_fold): Use them for rvalue operands. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 8cdda6200e1..117dd7991ff 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5687,8 +5687,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, decaying an enumerator to its value. */ if (complain & tf_warning) warn_logical_operator (loc, code, boolean_type_node, - code_orig_arg1, fold (arg1), - code_orig_arg2, fold (arg2)); + code_orig_arg1, arg1, + code_orig_arg2, arg2); arg2 = convert_like (conv, arg2, complain); } @@ -5726,8 +5726,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, case TRUTH_OR_EXPR: if (complain & tf_warning) warn_logical_operator (loc, code, boolean_type_node, - code_orig_arg1, fold (arg1), - code_orig_arg2, fold (arg2)); + code_orig_arg1, arg1, + code_orig_arg2, arg2); /* Fall through. */ case GT_EXPR: case LT_EXPR: @@ -5738,8 +5738,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, if ((complain & tf_warning) && ((code_orig_arg1 == BOOLEAN_TYPE) ^ (code_orig_arg2 == BOOLEAN_TYPE))) - maybe_warn_bool_compare (loc, code, fold (arg1), - fold (arg2)); + maybe_warn_bool_compare (loc, code, arg1, arg2); if (complain & tf_warning && warn_tautological_compare) warn_tautological_cmp (loc, code, arg1, arg2); /* Fall through. */ diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull1.C b/gcc/testsuite/g++.dg/warn/Wnonnull1.C new file mode 100644 index 00000000000..0f610f449c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wnonnull1.C @@ -0,0 +1,7 @@ +// { dg-options -Wnonnull } + +void g(void *) __attribute__ ((nonnull (1))); +void f(void *p) +{ + g(1 == 1 ? p : 0); +}