PR c++/24745: unpleasant warning for "if (NULL)"

Manuel López-Ibáñez lopezibanez@gmail.com
Sat Jan 20 09:20:00 GMT 2007


:ADDPATCH c++:

Currently the C++ front-end gives an unnamed, undocumented and
unconditional warning when using the NULL constant in arithmetic
operations. However, the logic implemented does not follow the
description given by the comments in the code. This patch fixes the
logic to follow exactly that description and it adds testcases to
check that we don't regress. It also moves the warning to
-Wpointer-arith and documents it.

In addition, -Wconversion gives a warning whenever the NULL constant
is converted to a non-pointer argument. However, this triggers
warnings for "if (NULL)" and "if (!NULL)", since NULL is converted to
boolean type. This patch prevents the warning when converting to
boolean.

Bootstrapped and regression tested with --enable-languages=all in
i686-pc-linux-gnu.

OK for mainline?


2007-01-20  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

  PR c++/24745
  * doc/invoke.texi (Wpointer-arith): Document warning.

cp/
  * typeck.c (build_binary_op): Fix logic for warning. Move warning to
-Wpointer-arith.
  * call.c (convert_like_real): Don't warn when converting to boolean type.

testsuite/
  * g++.dg/warn/null4.C: New.
-------------- next part --------------
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 120783)
+++ gcc/doc/invoke.texi	(working copy)
@@ -3129,7 +3129,8 @@ such assumptions.
 Warn about anything that depends on the ``size of'' a function type or
 of @code{void}.  GNU C assigns these types a size of 1, for
 convenience in calculations with @code{void *} pointers and pointers
-to functions.
+to functions.  In C++, warn also when an arithmetic operation involves
+@code{NULL}.  This warning is also enabled by @option{-pedantic}.
 
 @item -Wbad-function-cast @r{(C only)}
 @opindex Wbad-function-cast
Index: gcc/testsuite/g++.dg/warn/null4.C
===================================================================
--- gcc/testsuite/g++.dg/warn/null4.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/null4.C	(revision 0)
@@ -0,0 +1,29 @@
+// PR c++/24745 : warnings for NULL constant.
+// { dg-do compile  }
+// { dg-options "-Wpointer-arith -Wconversion " }
+
+#include <cstddef>
+
+int foo (void) 
+{
+  if (NULL == 1) return -1;   // { dg-warning "NULL used in arithmetic" } 
+  if (NULL > NULL) return -1; // { dg-warning "NULL used in arithmetic" } 
+  if (NULL < NULL) return -1; // { dg-warning "NULL used in arithmetic" } 
+  if (NULL >= 0) return -1;   // { dg-warning "NULL used in arithmetic" } 
+  if (NULL <= 0) return -1;   // { dg-warning "NULL used in arithmetic" } 
+  return 0;
+}
+
+int bar (void) 
+{
+  if (NULL) return -1;
+  if (!NULL) return -1;
+  if (!NULL == 1) return -1;
+  if (NULL || NULL) return -1;
+  if (!NULL && NULL) return -1;
+  if (NULL == NULL) return -1;
+  if (NULL != NULL) return -1;
+  if (NULL == 0) return -1;
+  if (NULL != 0) return -1;
+  return 0;
+}
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 120783)
+++ gcc/cp/typeck.c	(working copy)
@@ -3828,30 +3828,28 @@ build_binary_op (enum tree_code code, tr
 	}
     }
 
-  /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
-     Then the expression will be built.
-     It will be given type FINAL_TYPE if that is nonzero;
-     otherwise, it will be given type RESULT_TYPE.  */
-
   /* Issue warnings about peculiar, but valid, uses of NULL.  */
-  if (/* It's reasonable to use pointer values as operands of &&
+  if ((orig_op0 == null_node || orig_op1 == null_node)
+      /* It's reasonable to use pointer values as operands of &&
 	 and ||, so NULL is no exception.  */
-      !(code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
-      && (/* If OP0 is NULL and OP1 is not a pointer, or vice versa.  */
-	  (orig_op0 == null_node
-	   && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)
-	  /* Or vice versa.  */
-	  || (orig_op1 == null_node
-	      && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
-	  /* Or, both are NULL and the operation was not a comparison.  */
-	  || (orig_op0 == null_node && orig_op1 == null_node
-	      && code != EQ_EXPR && code != NE_EXPR)))
+      && code != TRUTH_ANDIF_EXPR && code != TRUTH_ORIF_EXPR 
+      && ( /* Both are NULL (or 0) and the operation was not a comparison.  */
+	  (null_ptr_cst_p (orig_op0) && null_ptr_cst_p (orig_op1) 
+	   && code != EQ_EXPR && code != NE_EXPR) 
+	  /* Or if one of OP0 or OP1 is not a pointer (null_node is not POINTER_TYPE).  */
+	  || (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE)
+	  || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)))
     /* Some sort of arithmetic operation involving NULL was
        performed.  Note that pointer-difference and pointer-addition
        have already been handled above, and so we don't end up here in
        that case.  */
-    warning (0, "NULL used in arithmetic");
+    warning (OPT_Wpointer_arith, "NULL used in arithmetic");
+  
 
+  /* If CONVERTED is zero, both args will be converted to type RESULT_TYPE.
+     Then the expression will be built.
+     It will be given type FINAL_TYPE if that is nonzero;
+     otherwise, it will be given type RESULT_TYPE.  */
   if (! converted)
     {
       if (TREE_TYPE (op0) != result_type)
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 120783)
+++ gcc/cp/call.c	(working copy)
@@ -4249,7 +4249,7 @@ convert_like_real (conversion *convs, tr
       tree t = non_reference (totype);
 
       /* Issue warnings about peculiar, but valid, uses of NULL.  */
-      if (ARITHMETIC_TYPE_P (t) && expr == null_node)
+      if (expr == null_node && TREE_CODE (t) != BOOLEAN_TYPE && ARITHMETIC_TYPE_P (t))
 	{
 	  if (fn)
 	    warning (OPT_Wconversion, "passing NULL to non-pointer argument %P of %qD",


More information about the Gcc-patches mailing list