]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: add Wzero-as-null-pointer-constant [PR117059]
authorMartin Uecker <uecker@tugraz.at>
Sat, 9 Nov 2024 09:48:52 +0000 (10:48 +0100)
committerMartin Uecker <uecker@gcc.gnu.org>
Wed, 13 Nov 2024 08:52:10 +0000 (09:52 +0100)
Add warnings for the use of zero as a null pointer constant to the C FE.

PR c/117059

gcc/c-family/ChangeLog:
* c.opt (Wzero-as-null-pointer-constant): Enable for C and ObjC.

gcc/c/ChangeLog:
* c-typeck.cc (parse_build_binary_op): Add warning.
(build_conditional_expr): Add warning.
(convert_for_assignment): Add warning.

gcc/ChangeLog:
* doc/invoke.texi (Wzero-as-null-pointer-constant): Adapt
description.

gcc/testsuite/ChangeLog:
* gcc.dg/Wzero-as-null-pointer-constant.c: New test.

Suggested-by: Alejandro Colomar <alx@kernel.org>
Acked-by: Alejandro Colomar <alx@kernel.org>
Reviewed-by: Joseph Myers <josmyers@redhat.com>
gcc/c-family/c.opt
gcc/c/c-typeck.cc
gcc/doc/invoke.texi
gcc/testsuite/gcc.dg/Wzero-as-null-pointer-constant.c [new file with mode: 0644]

index 47d6f083ffebea47ab55b7283f22235d5779b52f..3f80ec41da92173c5e4e1755a96070c36fae76c0 100644 (file)
@@ -1632,7 +1632,7 @@ C ObjC C++ ObjC++ Var(warn_xor_used_as_pow) Warning Init(1)
 Warn about xor operators where it appears the user meant exponentiation.
 
 Wzero-as-null-pointer-constant
-C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning
+C ObjC C++ ObjC++ Var(warn_zero_as_null_pointer_constant) Warning
 Warn when a literal '0' is used as null pointer.
 
 Wzero-length-bounds
index 201d75d2e9c947b50c4eb6e12170c159b516d2a2..ced58c2be84a43c95f920d85e5529294cddcdafa 100644 (file)
@@ -4600,6 +4600,25 @@ parser_build_binary_op (location_t location, enum tree_code code,
                "comparison with string literal results in unspecified "
                "behavior");
 
+  if (warn_zero_as_null_pointer_constant
+      && c_inhibit_evaluation_warnings == 0
+      && TREE_CODE_CLASS (code) == tcc_comparison)
+    {
+      if ((TREE_CODE (type1) == POINTER_TYPE
+          || TREE_CODE (type1) == NULLPTR_TYPE)
+         && TREE_CODE (type2) == INTEGER_TYPE
+         && null_pointer_constant_p (arg2.value))
+       warning_at (arg2.get_location(), OPT_Wzero_as_null_pointer_constant,
+                   "zero as null pointer constant");
+
+      if ((TREE_CODE (type2) == POINTER_TYPE
+          || TREE_CODE (type2) == NULLPTR_TYPE)
+         && TREE_CODE (type1) == INTEGER_TYPE
+         && null_pointer_constant_p (arg1.value))
+       warning_at (arg1.get_location(), OPT_Wzero_as_null_pointer_constant,
+                   "zero as null pointer constant");
+    }
+
   if (warn_array_compare
       && TREE_CODE_CLASS (code) == tcc_comparison
       && TREE_CODE (type1) == ARRAY_TYPE
@@ -5965,6 +5984,20 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
                    t1, t2);
     }
 
+  if (warn_zero_as_null_pointer_constant
+      && c_inhibit_evaluation_warnings == 0)
+    {
+      if ((code1 == POINTER_TYPE || code1 == NULLPTR_TYPE)
+         && code2 == INTEGER_TYPE && null_pointer_constant_p (orig_op2))
+       warning_at (op2_loc, OPT_Wzero_as_null_pointer_constant,
+                   "zero as null pointer constant");
+
+      if ((code2 == POINTER_TYPE || code2 == NULLPTR_TYPE)
+         && code1 == INTEGER_TYPE && null_pointer_constant_p (orig_op1))
+       warning_at (op1_loc, OPT_Wzero_as_null_pointer_constant,
+                   "zero as null pointer constant");
+    }
+
   /* Quickly detect the usual case where op1 and op2 have the same type
      after promotion.  */
   if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
@@ -8396,6 +8429,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
               || coder == NULLPTR_TYPE
               || coder == BITINT_TYPE))
     {
+      if (null_pointer_constant && c_inhibit_evaluation_warnings == 0
+         && coder == INTEGER_TYPE)
+       warning_at (location, OPT_Wzero_as_null_pointer_constant,
+                   "zero as null pointer constant");
+
       /* An explicit constant 0 or type nullptr_t can convert to a pointer,
         or one that results from arithmetic, even including a cast to
         integer type.  */
index 6c2c64410d4b601cf4b7c6c5e4da983663aa7ed2..aa979c3c2fd85b61bcb8a5c653256264519fc09c 100644 (file)
@@ -4750,9 +4750,8 @@ Enabled by default with @option{-std=c++20}.  Before
 
 @opindex Wzero-as-null-pointer-constant
 @opindex Wno-zero-as-null-pointer-constant
-@item -Wzero-as-null-pointer-constant @r{(C++ and Objective-C++ only)}
-Warn when a literal @samp{0} is used as null pointer constant.  This can
-be useful to facilitate the conversion to @code{nullptr} in C++11.
+@item -Wzero-as-null-pointer-constant
+Warn when a literal @samp{0} is used as null pointer constant.
 
 @opindex Waligned-new
 @opindex Wno-aligned-new
diff --git a/gcc/testsuite/gcc.dg/Wzero-as-null-pointer-constant.c b/gcc/testsuite/gcc.dg/Wzero-as-null-pointer-constant.c
new file mode 100644 (file)
index 0000000..b9cfbef
--- /dev/null
@@ -0,0 +1,107 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -Wzero-as-null-pointer-constant" } */
+
+#define NULL (void*)0
+
+void foo(void*);
+void baz(bool);
+
+void bar()
+{
+       foo(0);                         /* { dg-warning "zero as null pointer constant" } */
+       foo(NULL);
+       foo(nullptr);
+
+       int a = 0;
+
+       bool b = 0;
+       bool c = (void*)0;
+       bool d = NULL;
+       bool e = nullptr;
+
+       bool f = (bool)0;
+       bool g = (bool)(void*)0;
+       bool h = (bool)NULL;
+       bool i = (bool)nullptr;
+
+       baz(0);
+       baz((void*)0);
+       baz(NULL);
+       baz(nullptr);
+       baz((bool)0);
+       baz((bool)(void*)0);
+       baz((bool)NULL);
+       baz((bool)nullptr);
+
+       void *p = 0;                    /* { dg-warning "zero as null pointer constant" } */
+       void *r = NULL;
+       void *t = nullptr;
+       void *o = { };
+       void *q = { 0 };                /* { dg-warning "zero as null pointer constant" } */
+       void *s = { NULL };
+       void *u = { nullptr };
+       struct { void *q; } x = { 0 };  /* { dg-warning "zero as null pointer constant" } */
+       struct { void *q; } y = { NULL };
+       struct { void *q; } z = { nullptr };
+       struct { int a; void *b; } n = { 0 };
+       struct { int a; int b; void *c; } m = { 0, 0 };
+
+       1 ? 0 : 0;
+       1 ? i : 0;
+       1 ? 0 : p;                      /* { dg-warning "zero as null pointer constant" } */
+       1 ? p : 0;                      /* { dg-warning "zero as null pointer constant" } */
+       1 ? 0 : NULL;                   /* { dg-warning "zero as null pointer constant" } */
+       1 ? NULL : 0;                   /* { dg-warning "zero as null pointer constant" } */
+
+       0 ? 0 : 1;
+       (void*)0 ? 0 : 1;
+       NULL ? 0 : 1;
+       nullptr ? 0 : 1;
+
+       if (0 == 0);
+       if (i == 0);
+       if (p == 0);                    /* { dg-warning "zero as null pointer constant" } */
+       if (0 == p);                    /* { dg-warning "zero as null pointer constant" } */
+       if (NULL == 0);                 /* { dg-warning "zero as null pointer constant" } */
+       if (0 == NULL);                 /* { dg-warning "zero as null pointer constant" } */
+       if (0 == (void*)0);             /* { dg-warning "zero as null pointer constant" } */
+       if (0 == nullptr);              /* { dg-warning "zero as null pointer constant" } */
+       if (nullptr == 0);              /* { dg-warning "zero as null pointer constant" } */
+
+       if (0 != 0);
+       if (i != 0);
+       if (p != 0);                    /* { dg-warning "zero as null pointer constant" } */
+       if (0 != p);                    /* { dg-warning "zero as null pointer constant" } */
+       if (NULL != 0);                 /* { dg-warning "zero as null pointer constant" } */
+       if (0 != NULL);                 /* { dg-warning "zero as null pointer constant" } */
+       if (0 != (void*)0);             /* { dg-warning "zero as null pointer constant" } */
+       if (0 != nullptr);              /* { dg-warning "zero as null pointer constant" } */
+       if (nullptr != 0);              /* { dg-warning "zero as null pointer constant" } */
+
+       if (0);
+       if (NULL);
+       if ((void*)0);
+       if (nullptr);
+       if (!0);
+       if (!NULL);
+       if (!(void*)0);
+       if (!nullptr);
+
+       if (p);
+       p ? 0 : 1;
+       if (!p);
+       (!p) ? 0 : 1;
+
+       int *v;
+       if (v);
+       v ? 1 : 0;
+       if (!v);
+       (!v) ? 1 : 0;
+
+       bool j = p;
+       bool k = (bool)p;
+
+       baz(p);
+       baz((bool)p);
+}
+