Do constant folding in warn_* functions.
authorJason Merrill <jason@redhat.com>
Wed, 2 Dec 2015 19:04:48 +0000 (14:04 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 2 Dec 2015 19:04:48 +0000 (14:04 -0500)
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
gcc/c-family/c-common.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/warn/Wnonnull1.C [new file with mode: 0644]

index e32635fe5b14e1e443c788118e5e25753b50e73d..8aef600be7074fe77c4564d0d3c115d17fb2cee4 100644 (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.
index 40f86e3ab55231da2c373d8a1306a1d66f333fa9..a8122b30309ee3b022dc47f595fb0b91ddf24681 100644 (file)
@@ -1094,6 +1094,19 @@ fix_string_type (tree value)
   return value;
 }
 \f
+/* 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))
index d1fe8f4fd1da9e7a5abb728522c866decf9ca446..6d344ffdf3c77bdb23c44188e872a3671033905a 100644 (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.
index 8cdda6200e18685556423403fe7e632b1037e7fd..117dd7991ff8f9b75eee3767c428e062de5c17ce 100644 (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.  */
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull1.C b/gcc/testsuite/g++.dg/warn/Wnonnull1.C
new file mode 100644 (file)
index 0000000..0f610f4
--- /dev/null
@@ -0,0 +1,7 @@
+// { dg-options -Wnonnull }
+
+void g(void *) __attribute__ ((nonnull (1)));
+void f(void *p)
+{
+  g(1 == 1 ? p : 0);
+}