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
This commit is contained in:
Jason Merrill 2015-12-02 14:04:48 -05:00 committed by Jason Merrill
parent 7426fcc84f
commit f479b43da0
5 changed files with 54 additions and 15 deletions

View File

@ -1,5 +1,9 @@
2015-12-02 Jason Merrill <jason@redhat.com>
* 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.

View File

@ -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))

View File

@ -1,5 +1,8 @@
2015-12-02 Jason Merrill <jason@redhat.com>
* 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.

View File

@ -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. */

View File

@ -0,0 +1,7 @@
// { dg-options -Wnonnull }
void g(void *) __attribute__ ((nonnull (1)));
void f(void *p)
{
g(1 == 1 ? p : 0);
}