Bug 35669

Summary: NULL (__null) not considered different from 0 with C++
Product: gcc Reporter: Lubos Lunak <l.lunak>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: enhancement CC: bangerth, d, echristo, gcc-bugs, gcc, harald, jason, manu, mark, martindorey, pcordes
Priority: P3 Keywords: diagnostic
Version: 4.3.0   
Target Milestone: 4.5.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2010-02-16 17:10:54

Description Lubos Lunak 2008-03-22 20:05:51 UTC
When compiling with g++, the various error checking gained from using NULL instead of plain 0 for the null pointer does not work. For example

$ cat a.c
#include <stdio.h>

void foo( int a )
    {
    printf( "INT\n" );
    }

int main()
    {
    foo( NULL );
    foo( 0 );
    int a = NULL;
    return 0;
    }

$ gcc -Wall a.c
a.c: In function ‘main’:
a.c:10: warning: passing argument 1 of ‘foo’ makes integer from pointer without a cast
a.c:12: warning: initialization makes integer from pointer without a cast
a.c:12: warning: unused variable ‘a’

$ g++ -Wall a.c
a.c: In function ‘int main()’:
a.c:12: warning: unused variable ‘a’

As can be seen, compiling as C++ does not detect the mistakes in the code. The compiler uses __null though, as can be seen in preprocessed code:

$ g++ -Wall -E a.c | tail
    {
    printf( "INT\n" );
    }

int main()
    {
    foo( __null );
    foo( 0 );
    int a = __null;
    }

$ gcc -v
Using built-in specs.
Target: i586-suse-linux
Configured with: ../configure --prefix=/usr --with-local-prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.3 --enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --with-slibdir=/lib --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --program-suffix=-4.3 --enable-version-specific-runtime-libs --enable-linux-futex --without-system-libunwind --with-cpu=generic --build=i586-suse-linux
Thread model: posix
gcc version 4.3.0 (SUSE Linux)

The problem already exists with gcc 4.2.1, but gcc 4.1.2 (specifically "gcc version 4.1.2 20070115 (prerelease) (SUSE Linux)") works fine and reports:

$ g++ -Wall a.c
a.c: In function ‘int main()’:
a.c:10: warning: passing NULL to non-pointer argument 1 of ‘void foo(int)’
a.c:12: warning: converting to non-pointer type ‘int’ from NULL
a.c:12: warning: unused variable ‘a’
Comment 1 Richard Biener 2008-03-22 21:11:08 UTC
Because a null pointer constant is an integral constant expression, thus the
warning is wrong.  See PRs 5310 and 24745.  You have to use -Wconversion to
get the warning back.
Comment 2 Lubos Lunak 2008-03-22 23:15:30 UTC
When you say the warning is wrong, you presumably mean "passing argument 1 of ‘foo’ makes integer from pointer without a cast", but this bugreport is about (the absence of) "passing NULL to non-pointer argument 1 of ‘void foo(int)’", which is a valid warning. I think nobody in their right mind would try to feed NULL to foo(int), they should use 0 if they want an integer - why would NULL be __null then instead of 0?

Using -Wconversion helps with getting the warning, but it also causes warnings for normal common things like foo(2*0.5). While foo(NULL) is almost certainly a bug somewhere (and I saw such one for real myself), foo(2*0.5) is quite common, almost always harmless, and would require making the code more ugly by using explicit casts.

Would it be possible to get a warning about an almost certain bug without many warnings about something almost certainly harmless?
Comment 3 Manuel López-Ibáñez 2008-03-23 14:07:26 UTC
(In reply to comment #2)
> 
> Using -Wconversion helps with getting the warning, but it also causes warnings
> for normal common things like foo(2*0.5). While foo(NULL) is almost certainly 

Hmm, 2*0.5 should be folded pretty early so Wconversion should see 1.0 which can be converted exactly to an integer (I think), so there should be no warning whatsoever. Are you sure you are using GCC 4.3? I cannot reproduce the warning.

As for this PR, the warning from the C front-end seems to be mandated by the standard (I say this because using -pedantic-errors gives an error instead, so it is a pedwarn, it would be nice to know where in the C standard this appears, to add a comment to the code for future reference). 

Perhaps the C++ standard does not mandate such warning. If the C++ standard actually mandated the warning, this would be a bug. Otherwise, whether this is worth warning or a nuisance is a matter of opinion.
Comment 4 Harald van Dijk 2008-03-23 18:59:30 UTC
(In reply to comment #3)
> As for this PR, the warning from the C front-end seems to be mandated by the
> standard (I say this because using -pedantic-errors gives an error instead, so
> it is a pedwarn, it would be nice to know where in the C standard this appears,
> to add a comment to the code for future reference). 

C allows NULL to be defined as 0 (or other integral constant expressions evaluating to 0), or as such an expression cast to void *. (C99 7.17p3 & 6.3.2.2p3.) GCC defines NULL as ((void *) 0) in C mode. An implicit conversion from ((void *) 0) to int is not allowed by either C or by C++. (C99 6.5.4p3.) If GCC defined NULL as 0 in C mode, which would be a different but equally legitimate definition, the code would have to be accepted.

> Perhaps the C++ standard does not mandate such warning.

The C++ standard also requires a diagnostic for an implicit conversion from ((void *) 0) to int. However, it does not allow ((void *) 0) as a null pointer constant, and requires an expression of integral type. This means implicit conversions from NULL to non-pointer types may legitimately be rejected in C, but not in C++.

> If the C++ standard
> actually mandated the warning, this would be a bug.

It doesn't.

> Otherwise, whether this is
> worth warning or a nuisance is a matter of opinion.

True. So, is there any example where use of NULL / __null in a non-pointer context is a good idea?
Comment 5 Manuel López-Ibáñez 2008-03-23 19:43:37 UTC
(In reply to comment #4)
> 
> > Otherwise, whether this is
> > worth warning or a nuisance is a matter of opinion.
> 
> True. So, is there any example where use of NULL / __null in a non-pointer
> context is a good idea?

Is there an example where it leads to bugs? I don't know why C++ doesn't follow C here, but there must be some reason, no?

On the other hand, it seems we *do* warn about it with -Wconversion. So, where do you want to move it? Check the list of GCC warnings: http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html 

I think this isn't worth discussing anymore, it just needs someone to be bothered enough by it to write a patch+testcases, bootstrap, run the regression testsuite and submit to gcc-patches.
Comment 6 Lubos Lunak 2008-03-23 20:16:02 UTC
> Hmm, 2*0.5 should be folded pretty early so Wconversion should see 1.0 which
> can be converted exactly to an integer (I think), so there should be no
> warning whatsoever. Are you sure you are using GCC 4.3? I cannot reproduce
> the warning.

I didn't realize gcc could optimize this example. It was just meant to be an example of passing any float to foo(int). Make that foo(M_PI*10), foo(1.2), foo(sin(bar)*100) or whatever. My point was that calling foo(int) as foo(var) with var being a float is quite common code, whereas foo(NULL) is a mistake (or brain-damage :) ). Therefore I'd like a way to get warned only about the latter but not the sooner, which -Wconversion is not. That is why I changed this to an enhancement after being told that -Wall not warning about foo(NULL) is not a bug.

> > True. So, is there any example where use of NULL / __null in a non-pointer
> > context is a good idea?
> 
> Is there an example where it leads to bugs?

Yes. Consider you have code like this:

void foo(void* bar); // a function somewhere
...
foo( NULL ); // you call it
...

Now consider you want to add an overload foo(int). Now everybody who called the original version as foo(0) is suddenly calling a different function, but I intentionally used NULL to express I'm passing a null pointer, so I expect at least a warning (and without all the stuff I'd get with -Wconversion). And this example is actually based on a real problem that I had to debug in KDE libraries.
Comment 7 Manuel López-Ibáñez 2008-03-23 22:17:44 UTC
(In reply to comment #6)
> Yes. Consider you have code like this:
> 
> void foo(void* bar); // a function somewhere
> ...
> foo( NULL ); // you call it
> ...
> 
> Now consider you want to add an overload foo(int). Now everybody who called the
> original version as foo(0) is suddenly calling a different function, but I
> intentionally used NULL to express I'm passing a null pointer, so I expect at
> least a warning (and without all the stuff I'd get with -Wconversion). And this
> example is actually based on a real problem that I had to debug in KDE
> libraries.
> 

manuel@gcc12:~$ cat test.c
#include <stdio.h>

void foo( void * a )
{
  printf ("I'm foo(void*)\n");
}

void foo( int a )
{
  printf ("I'm foo(int)\n");
}

int main()
{
  foo (__null);
  return 0;
}

manuel@gcc12:~$ /home/guerby/release/4.3.0/bin/g++ test.c -fpermissive -o test
test.c: In function 'int main()':
test.c:15: error: call of overloaded 'foo(NULL)' is ambiguous
test.c:3: note: candidates are: void foo(void*)
test.c:8: note:                 void foo(int)

Anyway, it is not me the one you have to convince, I cannot approve patches and I said already I don't care which option controls the warning as long as it makes some sense.
Comment 8 Peter Cordes 2009-02-12 17:56:45 UTC
Would it cause any problems for g++ to behave more like a C compiler when it comes to NULL?  e.g. I found this bug report after finding that kscope 1.9.1 didn't compile, because it expected NULL to match the void* version of an overloaded function.

locationlistmodel.cpp:204: error: call of overloaded ‘createIndex(int&, int&, NULL)’ is ambiguous

.../qabstractitemmodel.h:288: note: candidates are: QModelIndex QAbstractItemModel::createIndex(int, int, void*) const
.../qabstractitemmodel.h:290: note:                 QModelIndex QAbstractItemModel::createIndex(int, int, int) const
.../qabstractitemmodel.h:299: note:                 QModelIndex QAbstractItemModel::createIndex(int, int, quint32) const

This was in released alpha code (http://qt-apps.org/content/show.php?content=96992) so presumably it built ok on some compiler.  (Although maybe it used to just pick one of the int overloads, if that's what Lubos was talking about having to debug.)

 As a mostly C programmer, this just seems like something stupid in the standard, and the sort of behaviour you should only get with -std=c++0x, but not -std=gnu++0x.  As everyone else is saying, who in their right mind actually wants this behaviour?  And more importantly, would changing it ever make g++ actually mis-compile anything?  (not counting compiling stuff like kscope, or test.c below, where the result "should" be an error message, not a binary)

 Anyway, NULL should be a void*, damn it.  Yes, I'm a C programmer.
Comment 9 Martin Dorey 2009-04-28 20:00:39 UTC
(In reply to comment #1)
> Because a null pointer constant is an integral constant expression, thus the
> warning is wrong.

Are all integral constant expressions necessarily implicitly convertible to all integer types?  I'd have thought so but, having read the references I cite below, now I don't.

> See PRs 5310 and 24745.

Both of those seem reasonable.  They're addressed by http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654.  The cited paper is at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2656.htm.  Implicit conversion to bool is clearly mandated (PR 24745).  Explicit conversion to int is clearly mandated (PR 5310).  The situation regarding implicit conversion to non-bool integral types (this PR) is slightly less clear, but, quoting Jason Merrill in the accepted defect 654 [

    int n3 = expr ? nullptr : nullptr;    // error, nullptr_t can’t be converted to int

  Basically, I would like nullptr_t to act like a void* which is constrained to always be (void*)0.

].  I think that shows the intent of the upcoming Standard is to disallow implicit conversion from nullptr to other integral types, as an implicit conversion from (void*)0 to int would be disallowed.
Comment 10 Wolfgang Bangerth 2009-04-29 12:51:12 UTC
There is really nothing much that can be done within the current C++
standard. In C, NULL is defined as 
  (void*)0
which can be converted to any other pointer and so is clearly marked
as a pointer. The compiler can then warn when passing it to an integer
argument of a function.

In C++, we have [18.1/4] "The macro NULL is an implementation-defined C++ null
pointer  constant in this International Standard (_conv.ptr_).180)" and
footnote 180 specifically says:

  180) Possible definitions include 0 and 0L, but not (void*)0.

This is because void* is not implicitly convertible to any other pointer
type and so NULL could not be assigned to other pointers. As a consequence,
since NULL can not in an obvious way be a pointer, there is no obvious
warning that can be generated.

The situation will be different with the upcoming C++1x standard where there
is null_ptr.

W.
Comment 11 Lubos Lunak 2009-04-29 13:21:52 UTC
(In reply to comment #10)
> As a consequence, since NULL can not in an obvious way be a pointer, there is
> no obvious warning that can be generated.

 Of course there is. NULL with gcc is not 0, 0L or (void*)0, it is __null. And gcc can make __null be whatever it wants, can it not? The same way it can warn about converting __null to integer.

> The situation will be different with the upcoming C++1x standard where there
> is null_ptr.

 Gcc already in practice has null_ptr. It's called __null. What would be the point of __null otherwise, to have a really sophisticated way to write 0?
Comment 12 Martin Dorey 2009-04-29 16:47:14 UTC
(In reply to comment #10)
>  180) Possible definitions include 0 and 0L, but not (void*)0.

That doesn't forbid defining NULL as nullptr though clearly gcc is within the current Standard to effectively define it as 0.

> The situation will be different with the upcoming C++1x standard where there
> is null_ptr.

Yes, very different.  Per the accepted language defect and paper I cited here yesterday, in the upcoming standard, the compiler seems required to reject implicit conversion from NULL to int.  This PR then becomes a rejects-valid and an accepts-invalid bug, rather than an enhancement request for a warning.

void test() {
  if (__null); // Explicitly allowed in upcoming Standard (shouldn't warn, PR 24745)
  int a = __null; // Disallowed(?) by upcoming Standard (should error, PR 35699 (this PR))
  int b = (int)__null; // Explicitly allowed in upcoming Standard (shouldn't warn, PR 5310)
}

(In reply to comment #11)
>  What would be the point of __null otherwise...?

Good question.
Comment 13 Jonathan Wakely 2009-12-08 10:48:41 UTC
(In reply to comment #12)
> > The situation will be different with the upcoming C++1x standard where there
> > is null_ptr.
> 
> Yes, very different.  Per the accepted language defect and paper I cited here
> yesterday, in the upcoming standard, the compiler seems required to reject
> implicit conversion from NULL to int.  This PR then becomes a rejects-valid and
> an accepts-invalid bug, rather than an enhancement request for a warning.

I don't think that's true, implicit conversion from nullptr_t to int is forbidden, but 0 is still a valid definition of NULL so conversion from NULL to int is OK. And __null does not have type nullptr_t, changing it to have that type would break a lot of code




> void test() {
>   if (__null); // Explicitly allowed in upcoming Standard (shouldn't warn, PR
> 24745)
>   int a = __null; // Disallowed(?) by upcoming Standard (should error, PR 35699
> (this PR))
>   int b = (int)__null; // Explicitly allowed in upcoming Standard (shouldn't
> warn, PR 5310)
> }
> 
> (In reply to comment #11)
> >  What would be the point of __null otherwise...?
> 
> Good question.
> 

Comment 14 Martin Dorey 2009-12-21 20:02:34 UTC
> so [implicit] conversion from NULL to int is OK.

That's true where NULL is defined as 0 (or eg 0L), but that's not the only permitted definition of NULL.
Comment 15 Jonathan Wakely 2009-12-22 10:36:34 UTC
(In reply to comment #14)
> > so [implicit] conversion from NULL to int is OK.
> 
> That's true where NULL is defined as 0 (or eg 0L), but that's not the only
> permitted definition of NULL.

Nice selective quoting, you missed the part where I said "but 0 is still a valid definition of NULL" 

You claimed in comment 12 that the compiler will be *required* to reject conversions from NULL to int, which is patently not true if 0 or 0L is a valid definition of NULL.

Comment 16 Martin Dorey 2009-12-22 18:12:39 UTC
(In reply to comment #15)
> you missed the part where I said "but 0 is still a valid definition of NULL"

(I didn't quote it but I did explicitly agree with it.)

> You claimed in comment 12 that the compiler will be *required* to reject
> conversions from NULL to int, which is patently not true if 0 or 0L is a valid
> definition of NULL.

You're right.  My citations in comment #9 refer to nullptr, not NULL, and my examples in comment #12 refer to __null, not NULL.  In my prose for comment #12, however, I was wrongly assuming that NULL would be required to be nullptr in the new Standard.  Having read more of the current draft in response to your post of yesterday, I agree that such a change is not required.

This PR, then, is not an accepts-invalid.  It's an enhancement request to reinstate one of the warnings, about accidentally inappropriate use of NULL, that became disabled by default between gcc-4.1 and gcc-4.2.

Three warnings about NULL conversions were disabled by default in 4.2.  Per comment #1, this was because two of the warnings rejected code which ought to be allowed.  Per comment #9, that code which ought to be allowed is a valid use of nullptr.  However, 4.3 seems to have removed the two problematic warnings, even when -Wconversion is used.  That suggests that this PR could now be addressed, without regressing the two PRs cited in comment #1, by enabling the warning about this particular conversion by default, as it was in 4.1.  That would address the OP's example and discourage code that wouldn't compile with #define NULL nullptr.

Evidence for the new claim in the above paragraph:

martind@ithaki:~/playpen$ g++-4.1 -c -pedantic null-conversion.cpp 
null-conversion.cpp: In function ‘void test()’:
null-conversion.cpp:2: warning: converting to non-pointer type ‘bool’ from NULL
null-conversion.cpp:3: warning: converting to non-pointer type ‘int’ from NULL
null-conversion.cpp:4: warning: converting to non-pointer type ‘int’ from NULL
martind@ithaki:~/playpen$ 
martind@duezer:~/playpen$ g++-4.2 -c -pedantic null-conversion.cpp 
martind@duezer:~/playpen$ g++-4.2 -Wconversion -c -pedantic null-conversion.cpp
 
null-conversion.cpp: In function ‘void test()’:
null-conversion.cpp:2: warning: converting to non-pointer type ‘bool’ from NULL
null-conversion.cpp:3: warning: converting to non-pointer type ‘int’ from NULL
null-conversion.cpp:4: warning: converting to non-pointer type ‘int’ from NULL
martind@duezer:~/playpen$ 
martind@duezer:~/playpen$ g++-4.3 -c -pedantic null-conversion.cpp 
martind@duezer:~/playpen$ g++-4.3 -Wconversion -c -pedantic null-conversion.cpp 
null-conversion.cpp: In function ‘void test()’:
null-conversion.cpp:3: warning: converting to non-pointer type ‘int’ from NULL
martind@duezer:~/playpen$ 
Comment 17 Manuel López-Ibáñez 2010-02-14 20:18:52 UTC
(In reply to comment #16)
> 
> This PR, then, is not an accepts-invalid.  It's an enhancement request to
> reinstate one of the warnings, about accidentally inappropriate use of NULL,
> that became disabled by default between gcc-4.1 and gcc-4.2.

Which one? We are not going to warn for conversions to boolean and we are not going to warn for explicit conversions. And we are not going to warn by default, only with -Wconversion. So, please post a testcase as minimal and self-contained (with the smallest number of includes) as possible and point out exactly what you expect to happen.
Comment 18 Lubos Lunak 2010-02-14 21:47:08 UTC
(In reply to comment #17)
> Which one? We are not going to warn for conversions to boolean and we are not
> going to warn for explicit conversions.

 I don't see anybody asking for that.

> And we are not going to warn by default, only with -Wconversion.

 If you fail to see the difference between NULL being converted to integer being almost always a mistake and the flood of warnings caused by -Wcoversion to be almost almost harmless in real-world code, then you probably might as well not bother at all. A warning about something that's almost for sure a mistake being part of a flag that almost nobody uses is next to useless.

> So, please post a testcase as minimal and self-contained (with the smallest
> number of includes) as possible and point out
> exactly what you expect to happen.

Well, it's all in the original comment of this bugreport, but if you insist:

Testcase (a.c):

#include <stddef.h>
void foo( int a );
int main()
    {
    foo( NULL );
    foo( 0 );
    int a = NULL;
    return 0;
    }

Expected output (like 'gcc -Wall -c a.c' provides):

a.c: In function &#8216;main&#8217;:
a.c:5: warning: passing argument 1 of &#8216;foo&#8217; makes integer from pointer without a cast
a.c:2: note: expected &#8216;int&#8217; but argument is of type &#8216;void *&#8217;
a.c:7: warning: initialization makes integer from pointer without a cast
a.c:7: warning: unused variable &#8216;a&#8217;

Actual output (what 'g++ -Wall -c a.c' provides):

a.c: In function &#8216;int main()&#8217;:
a.c:7: warning: unused variable &#8216;a&#8217;

The warning about the unused variable is obviously irrelevant.
Comment 19 Manuel López-Ibáñez 2010-02-14 22:06:28 UTC
(In reply to comment #18)
> 
> Expected output (like 'gcc -Wall -c a.c' provides):

Since those warnings are already part of Wconversion, what you are asking is to move them to default or another option enabled by -Wall. Contrary to what I said above, I don't see any problem if this construct does not have any valid use. Such option, e.g., -Wconversion-nul could be enabled by -Wall (or by default) and -Wconversion, independently.

If you get a C++ maintainer to say that they would approve such patch, I will write it, test it and commit it for you.
Comment 20 Jason Merrill 2010-02-16 17:10:54 UTC
I would approve a patch to enable the warnings in conversion_null_warnings, and the similar warning in build_expr_type_conversion, by default.  That is, reverting revision 109847.  I don't know what Eric's rationale was for making the warning off by default, so I'll add him to the CC list.
Comment 21 Eric Christopher 2010-02-16 18:01:54 UTC
I remember that we originally ran into this warning in a huge number of places building OSX.  Now I'd agree that null checking would be something good to have, but there should be some way to turn it off if it's on by default.
Comment 22 Manuel López-Ibáñez 2010-02-16 18:05:59 UTC
Testing this:

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi (revision 156812)
+++ gcc/doc/invoke.texi (working copy)
@@ -3835,18 +3835,23 @@ like @code{unsigned ui = -1}; and conver
 ((int) x)} and @code{ui = (unsigned) -1}, or if the value is not
 changed by the conversion like in @code{abs (2.0)}.  Warnings about
 conversions between signed and unsigned integers can be disabled by
 using @option{-Wno-sign-conversion}.

-For C++, also warn for conversions between @code{NULL} and non-pointer
-types; confusing overload resolution for user-defined conversions; and
-conversions that will never use a type conversion operator:
-conversions to @code{void}, the same type, a base class or a reference
-to them. Warnings about conversions between signed and unsigned
-integers are disabled by default in C++ unless
+For C++, also warn for confusing overload resolution for user-defined
+conversions; and conversions that will never use a type conversion
+operator: conversions to @code{void}, the same type, a base class or a
+reference to them. Warnings about conversions between signed and
+unsigned integers are disabled by default in C++ unless
 @option{-Wsign-conversion} is explicitly enabled.

+@item -Wno-conversion-nul
+@opindex Wconversion-nul
+@opindex Wno-conversion-nul
+Do not warn for conversions between @code{NULL} and non-pointer
+types. @option{-Wconversion-nul} is enabled by default.
+
 @item -Wempty-body
 @opindex Wempty-body
 @opindex Wno-empty-body
 Warn if an empty body occurs in an @samp{if}, @samp{else} or @samp{do
 while} statement.  This warning is also enabled by @option{-Wextra}.
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c       (revision 156812)
+++ gcc/cp/call.c       (working copy)
@@ -4802,19 +4802,19 @@ conversion_null_warnings (tree totype, t

   /* Issue warnings about peculiar, but valid, uses of NULL.  */
   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",
+       warning (OPT_Wconversion_nul, "passing NULL to non-pointer argument %P of %qD",
                 argnum, fn);
       else
-       warning (OPT_Wconversion, "converting to non-pointer type %qT from NULL", t);
+       warning (OPT_Wconversion_nul, "converting to non-pointer type %qT from NULL", t);
     }

   /* Issue warnings if "false" is converted to a NULL pointer */
   else if (expr == boolean_false_node && fn && POINTER_TYPE_P (t))
-    warning (OPT_Wconversion,
+    warning (OPT_Wconversion_nul,
             "converting %<false%> to pointer type for argument %P of %qD",
             argnum, fn);
 }

 /* Perform the conversions in CONVS on the expression EXPR.  FN and
Index: gcc/cp/cvt.c
===================================================================
--- gcc/cp/cvt.c        (revision 156812)
+++ gcc/cp/cvt.c        (working copy)
@@ -1139,11 +1139,11 @@ build_expr_type_conversion (int desires,
   tree winner = NULL_TREE;

   if (expr == null_node
       && (desires & WANT_INT)
       && !(desires & WANT_NULL))
-    warning (OPT_Wconversion, "converting NULL to non-pointer type");
+    warning (OPT_Wconversion_nul, "converting NULL to non-pointer type");

   basetype = TREE_TYPE (expr);

   if (basetype == error_mark_node)
     return error_mark_node;
Index: gcc/c.opt
===================================================================
--- gcc/c.opt   (revision 156812)
+++ gcc/c.opt   (working copy)
@@ -169,10 +169,14 @@ Synonym for -Wcomment

 Wconversion
 C ObjC C++ ObjC++ Var(warn_conversion) Warning
 Warn for implicit type conversions that may change a value

+Wconversion-nul
+C++ ObjC++ Var(warn_conversion_nul) Init(1) Warning
+Warn for converting NULL from/to a non-pointer type
+
 Wsign-conversion
 C ObjC C++ ObjC++ Var(warn_sign_conversion) Init(-1)
 Warn for implicit type conversions between signed and unsigned integers

 Wctor-dtor-privacy
Comment 23 Eric Christopher 2010-02-16 18:09:24 UTC
That looks fine to me, though you'll probably want to use "null" instead of null in the command line option. :)
Comment 24 Manuel López-Ibáñez 2010-02-16 18:27:04 UTC
(In reply to comment #23)
> That looks fine to me, though you'll probably want to use "null" instead of
> null in the command line option. :)
> 

I guess you mean Wconversion-null instead of Wconversion-nul. Fine.

Any suggestions to give better location information in this warning? I guess the location of null_node is useless.
Comment 25 Jason Merrill 2010-02-16 18:43:48 UTC
Subject: Re:  NULL (__null) not considered different from 0
 with C++

On 02/16/2010 01:27 PM, manu at gcc dot gnu dot org wrote:
> I guess you mean Wconversion-null instead of Wconversion-nul. Fine.

OK with that change.

> Any suggestions to give better location information in this warning? I guess
> the location of null_node is useless.

No real suggestions; to avoid using input_location we'd need to track 
locations all the way through the overload resolution code.

I wonder if in 4.6 we want to start wrapping uses of shared nodes such 
as null_node or decls in order to retain location information.

Jason
Comment 26 Manuel López-Ibáñez 2010-02-20 21:32:19 UTC
Subject: Bug 35669

Author: manu
Date: Sat Feb 20 21:32:06 2010
New Revision: 156928

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=156928
Log:
2010-02-20  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	PR c++/35669
	* c.opt (Wconversion-null): New option.
	* doc/invoke.texi (Wconversion-null): Document.

cp/
	* call.c (conversion_null_warnings): Replace -Wconversion with
	-Wconversion-null.
	* cvt.c (build_expr_type_conversion): Likewise.

testsuite/
	* g++.dg/warn/Wconversion2.C: Replace -Wconversion with
	-Wconversion-null.
	* g++.dg/warn/Wconversion-null.C: New test.
	* g++.old-deja/g++.other/null1.C: Move to...
	* g++.dg/warn/Wconversion-null-2.C: ... here. Remove -Wconversion.

libstdc++-v3/	
	* testsuite/18_support/headers/cstddef/macros.cc: Add
	-Wno-conversion-null.

Added:
    trunk/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C   (contents, props changed)
      - copied, changed from r156925, trunk/gcc/testsuite/g++.old-deja/g++.other/null1.C
    trunk/gcc/testsuite/g++.dg/warn/Wconversion-null.C
Removed:
    trunk/gcc/testsuite/g++.old-deja/g++.other/null1.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c.opt
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cvt.c
    trunk/gcc/doc/invoke.texi
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/warn/Wconversion2.C
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/testsuite/18_support/headers/cstddef/macros.cc

Propchange: trunk/gcc/testsuite/g++.dg/warn/Wconversion-null-2.C
            ('svn:mergeinfo' added)


Comment 27 Manuel López-Ibáñez 2010-02-20 21:38:43 UTC
FIXED in GCC 4.5