[PATCH] Move the -Wnonnull compare against NULL warning from FEs to early uninit under -Wnonnull-compare (PR c/69835)
Jakub Jelinek
jakub@redhat.com
Tue Feb 16 15:29:00 GMT 2016
Hi!
As has been reported today on gcc@, the new -Wnonnull warning addition
warns even about nonnull parameters that were changed (or could be changed)
in the function. IMHO the nonnull attribute only talks about the value of
the parameter upon entry to the function, if you assign something else
to the argument afterwards and test that for NULL or non-NULL, it is like
any other variable.
But, we don't have the infrastructure to detect this in the FE, so this
patch moves the warning soon after we go into SSA form.
As -Wnonnull is a C/C++/ObjC/ObjC++ only warning, I've added a new
-Wnonnull-compare switch for it too (and enable it for C/C++/ObjC/ObjC++
from -Wall).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2016-02-16 Jakub Jelinek <jakub@redhat.com>
PR c/69835
* common.opt (Wnonnull-compare): New warning.
* doc/invoke.texi (-Wnonnull): Remove text about comparison
of arguments against NULL.
(-Wnonnull-compare): Document.
* tree-ssa-uninit.c (warn_uninitialized_vars): Add warn_nonnull_cmp
argument, if true, warn about SSA_NAME (D) of nonnull_arg_p
comparisons against NULL pointers.
(pass_late_warn_uninitialized::execute): Adjust caller.
(execute_early_warn_uninitialized): Likewise.
(gate_early_warn_uninitialized): New function.
(pass_early_warn_uninitialized::gate): Call it instead of
gate_warn_uninitialized.
c-family/
* c.opt (Wnonnull-compare): Enable for -Wall.
c/
* c-typeck.c (build_binary_op): Revert 2015-09-09 change.
cp/
* typeck.c (cp_build_binary_op): Revert 2015-09-09 change.
testsuite/
* c-c++-common/nonnull-1.c: Use -Wnonnull-compare instead of
-Wnonnull in dg-options.
* c-c++-common/nonnull-2.c: New test.
--- gcc/common.opt.jj 2016-01-27 19:47:35.000000000 +0100
+++ gcc/common.opt 2016-02-16 11:52:42.641623690 +0100
@@ -616,6 +616,10 @@ Wlarger-than=
Common RejectNegative Joined UInteger Warning
-Wlarger-than=<number> Warn if an object is larger than <number> bytes.
+Wnonnull-compare
+Var(warn_nonnull_compare) Warning
+Warn if comparing pointer parameter with nonnull attribute with NULL.
+
Wnull-dereference
Common Var(warn_null_dereference) Warning
Warn if dereferencing a NULL pointer may lead to erroneous or undefined behavior.
--- gcc/doc/invoke.texi.jj 2016-02-08 18:39:16.000000000 +0100
+++ gcc/doc/invoke.texi 2016-02-16 12:31:42.037232875 +0100
@@ -276,7 +276,8 @@ Objective-C and Objective-C++ Dialects}.
-Wmain -Wmaybe-uninitialized -Wmemset-transposed-args @gol
-Wmisleading-indentation -Wmissing-braces @gol
-Wmissing-field-initializers -Wmissing-include-dirs @gol
--Wno-multichar -Wnonnull -Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} @gol
+-Wno-multichar -Wnonnull -Wnonnull-compare @gol
+-Wnormalized=@r{[}none@r{|}id@r{|}nfc@r{|}nfkc@r{]} @gol
-Wnull-dereference -Wodr -Wno-overflow -Wopenmp-simd @gol
-Woverride-init-side-effects -Woverlength-strings @gol
-Wpacked -Wpacked-bitfield-compat -Wpadded @gol
@@ -3537,6 +3538,7 @@ Options} and @ref{Objective-C and Object
-Wmissing-braces @r{(only for C/ObjC)} @gol
-Wnarrowing @r{(only for C++)} @gol
-Wnonnull @gol
+-Wnonnull-compare @gol
-Wopenmp-simd @gol
-Wparentheses @gol
-Wpointer-sign @gol
@@ -3795,12 +3797,18 @@ formats that may yield only a two-digit
Warn about passing a null pointer for arguments marked as
requiring a non-null value by the @code{nonnull} function attribute.
-Also warns when comparing an argument marked with the @code{nonnull}
-function attribute against null inside the function.
-
@option{-Wnonnull} is included in @option{-Wall} and @option{-Wformat}. It
can be disabled with the @option{-Wno-nonnull} option.
+@item -Wnonnull-compare
+@opindex Wnonnull-compare
+@opindex Wno-nonnull-compare
+Warn when comparing an argument marked with the @code{nonnull}
+function attribute against null inside the function.
+
+@option{-Wnonnull-compare} is included in @option{-Wall}. It
+can be disabled with the @option{-Wno-nonnull-compare} option.
+
@item -Wnull-dereference
@opindex Wnull-dereference
@opindex Wno-null-dereference
--- gcc/tree-ssa-uninit.c.jj 2016-01-13 13:28:41.000000000 +0100
+++ gcc/tree-ssa-uninit.c 2016-02-16 12:50:30.390619823 +0100
@@ -171,7 +171,8 @@ warn_uninit (enum opt_code wc, tree t, t
}
static unsigned int
-warn_uninitialized_vars (bool warn_possibly_uninitialized)
+warn_uninitialized_vars (bool warn_possibly_uninitialized,
+ bool warn_nonnull_cmp)
{
gimple_stmt_iterator gsi;
basic_block bb;
@@ -190,6 +191,60 @@ warn_uninitialized_vars (bool warn_possi
if (is_gimple_debug (stmt))
continue;
+ if (warn_nonnull_cmp)
+ {
+ tree op0 = NULL_TREE, op1 = NULL_TREE;
+ location_t loc = gimple_location (stmt);
+ if (gimple_code (stmt) == GIMPLE_COND)
+ switch (gimple_cond_code (stmt))
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ op0 = gimple_cond_lhs (stmt);
+ op1 = gimple_cond_rhs (stmt);
+ break;
+ default:
+ break;
+ }
+ else if (is_gimple_assign (stmt))
+ switch (gimple_assign_rhs_code (stmt))
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ op0 = gimple_assign_rhs1 (stmt);
+ op1 = gimple_assign_rhs2 (stmt);
+ break;
+ case COND_EXPR:
+ switch (TREE_CODE (gimple_assign_rhs1 (stmt)))
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ op1 = gimple_assign_rhs1 (stmt);
+ loc = EXPR_LOC_OR_LOC (op1, loc);
+ op0 = TREE_OPERAND (op1, 0);
+ op1 = TREE_OPERAND (op1, 1);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (op0
+ && TREE_CODE (op0) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (op0)
+ && TREE_CODE (SSA_NAME_VAR (op0)) == PARM_DECL
+ && (POINTER_TYPE_P (TREE_TYPE (op0))
+ || TREE_CODE (TREE_TYPE (op0)) == OFFSET_TYPE)
+ && nonnull_arg_p (SSA_NAME_VAR (op0))
+ && (POINTER_TYPE_P (TREE_TYPE (op0))
+ ? integer_zerop (op1) : integer_minus_onep (op1)))
+ warning_at (gimple_location (stmt), OPT_Wnonnull_compare,
+ "nonnull argument %qD compared to NULL",
+ SSA_NAME_VAR (op0));
+ }
+
/* We only do data flow with SSA_NAMEs, so that's all we
can warn about. */
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, op_iter, SSA_OP_USE)
@@ -2416,7 +2471,7 @@ pass_late_warn_uninitialized::execute (f
/* Re-do the plain uninitialized variable check, as optimization may have
straightened control flow. Do this first so that we don't accidentally
get a "may be" warning when we'd have seen an "is" warning later. */
- warn_uninitialized_vars (/*warn_possibly_uninitialized=*/1);
+ warn_uninitialized_vars (/*warn_possibly_uninitialized=*/true, false);
timevar_push (TV_TREE_UNINIT);
@@ -2478,6 +2533,14 @@ make_pass_late_warn_uninitialized (gcc::
}
+static bool
+gate_early_warn_uninitialized (void)
+{
+ return (warn_uninitialized
+ || warn_maybe_uninitialized
+ || warn_nonnull_compare);
+}
+
static unsigned int
execute_early_warn_uninitialized (void)
{
@@ -2488,7 +2551,8 @@ execute_early_warn_uninitialized (void)
optimization we need to warn here about "may be uninitialized". */
calculate_dominance_info (CDI_POST_DOMINATORS);
- warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize);
+ warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize,
+ warn_nonnull_compare);
/* Post-dominator information can not be reliably updated. Free it
after the use. */
@@ -2521,7 +2585,7 @@ public:
{}
/* opt_pass methods: */
- virtual bool gate (function *) { return gate_warn_uninitialized (); }
+ virtual bool gate (function *) { return gate_early_warn_uninitialized (); }
virtual unsigned int execute (function *)
{
return execute_early_warn_uninitialized ();
--- gcc/c-family/c.opt.jj 2016-02-08 18:39:17.000000000 +0100
+++ gcc/c-family/c.opt 2016-02-16 12:30:00.299641823 +0100
@@ -677,6 +677,10 @@ Wnonnull
C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall)
;
+Wnonnull-compare
+C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall)
+;
+
Wnormalized
C ObjC C++ ObjC++ Warning Alias(Wnormalized=,nfc,none)
;
--- gcc/c/c-typeck.c.jj 2016-02-12 10:23:50.000000000 +0100
+++ gcc/c/c-typeck.c 2016-02-16 11:40:08.474048701 +0100
@@ -11086,11 +11086,6 @@ build_binary_op (location_t location, en
short_compare = 1;
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
- if (warn_nonnull
- && TREE_CODE (op0) == PARM_DECL && nonnull_arg_p (op0))
- warning_at (location, OPT_Wnonnull,
- "nonnull argument %qD compared to NULL", op0);
-
if (TREE_CODE (op0) == ADDR_EXPR
&& decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
{
@@ -11111,11 +11106,6 @@ build_binary_op (location_t location, en
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
- if (warn_nonnull
- && TREE_CODE (op1) == PARM_DECL && nonnull_arg_p (op1))
- warning_at (location, OPT_Wnonnull,
- "nonnull argument %qD compared to NULL", op1);
-
if (TREE_CODE (op1) == ADDR_EXPR
&& decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
{
--- gcc/cp/typeck.c.jj 2016-02-12 10:23:50.000000000 +0100
+++ gcc/cp/typeck.c 2016-02-16 11:40:37.783643278 +0100
@@ -4514,11 +4514,6 @@ cp_build_binary_op (location_t location,
|| (code0 == POINTER_TYPE
&& TYPE_PTR_P (type1) && integer_zerop (op1)))
{
- if (warn_nonnull
- && TREE_CODE (op0) == PARM_DECL && nonnull_arg_p (op0))
- warning_at (location, OPT_Wnonnull,
- "nonnull argument %qD compared to NULL", op0);
-
if (TYPE_PTR_P (type1))
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
@@ -4558,11 +4553,6 @@ cp_build_binary_op (location_t location,
|| (code1 == POINTER_TYPE
&& TYPE_PTR_P (type0) && integer_zerop (op0)))
{
- if (warn_nonnull
- && TREE_CODE (op1) == PARM_DECL && nonnull_arg_p (op1))
- warning_at (location, OPT_Wnonnull,
- "nonnull argument %qD compared to NULL", op1);
-
if (TYPE_PTR_P (type0))
result_type = composite_pointer_type (type0, type1, op0, op1,
CPO_COMPARISON, complain);
--- gcc/testsuite/c-c++-common/nonnull-1.c.jj 2015-10-11 19:11:06.000000000 +0200
+++ gcc/testsuite/c-c++-common/nonnull-1.c 2016-02-16 12:38:53.917256278 +0100
@@ -1,7 +1,7 @@
/* Test for the bad usage of "nonnull" function attribute parms. */
/* */
/* { dg-do compile } */
-/* { dg-options "-Wnonnull" } */
+/* { dg-options "-Wnonnull-compare" } */
#include <stddef.h>
#include <stdlib.h>
--- gcc/testsuite/c-c++-common/nonnull-2.c.jj 2016-02-16 12:52:17.149142596 +0100
+++ gcc/testsuite/c-c++-common/nonnull-2.c 2016-02-16 12:56:29.904645198 +0100
@@ -0,0 +1,26 @@
+/* Test for the bad usage of "nonnull" function attribute parms. */
+/* { dg-do compile } */
+/* { dg-options "-Wnonnull-compare" } */
+
+void bar (char **);
+
+__attribute__((nonnull (1, 3))) int
+foo (char *cp1, char *cp2, char *cp3, char *cp4)
+{
+ if (cp1 == (char *) 0) /* { dg-warning "nonnull argument" "cp1 compared to NULL" } */
+ return 1;
+
+ cp1 = cp2;
+ if (cp1 == (char *) 0) /* { dg-bogus "nonnull argument" } */
+ return 2;
+
+ if (!cp4) /* { dg-bogus "nonnull argument" } */
+ return 3;
+
+ char **p = &cp3;
+ bar (p);
+ if (cp3 == (char *) 0) /* { dg-bogus "nonnull argument" } */
+ return 4;
+
+ return 5;
+}
Jakub
More information about the Gcc-patches
mailing list