@@ -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
@@ -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. */
@@ -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
new file mode 100644
@@ -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);
+}
+