With -Waddress (implied by -Wall), I get the following warning when I use the test a == 0 where a is an array: the address of 'a' will never be NULL. This behavior is undocumented and inconsistent (see below). Here's a testcase: int main (void) { char a[1], *b; b = a; if (a == 0) return 1; else if (a == (void *) 0) return 2; else if (b == 0) return 3; else if (b == (void *) 0) return 4; return 0; } gcc warns only for a == 0 (and this is OK to use 0 instead of (void *) 0 because it is a valid form for a null pointer constant). Moreover this is very similar to code like if (1) ... or code given in bug 12963, for which gcc no longer emits warnings: indeed such kind of correct and useful code is typically used in macros.
if (a == 0) return 1; else if (a == (void *) 0) Those two should warn about being address being zero. "a" decays to a pointer type and really &a[0]. -- Pinski
Andrew, how could we detect that it is a decayed array? I think we would like to warn for if (a == (void *) 0) but not for if ((void *)a == 0) or even if possible not for if (&a[0] == 0) Vincent, this warning was added on purpose, because probably someone requested it. I don't see that it is very different from the documented case of using the address of a function in a conditional. You should be able to work-around the macro case by casting the array to (char *) or perhaps casting to (void *) ? That said, we would like to not warn within macros for a wide range of warnings but we don't have the infrastructure to do that yet.
(In reply to comment #2) > this warning was added on purpose, because probably someone requested it. I > don't see that it is very different from the documented case of using the > address of a function in a conditional. The documentation should be improved anyway (the word "suspicious" is very subjective). > You should be able to work-around the macro case by casting the array to (char > *) or perhaps casting to (void *) ? Yes, this makes sense. Perhaps this should be documented. > That said, we would like to not warn within > macros for a wide range of warnings but we don't have the infrastructure to do > that yet. How about something like __extension__, e.g. __no_warnings__ would disable the warnings for the following statement or expression? If expression, one could still use __no_warnings__ with ({ ... }). Keywords for individual warnings or warning groups would even be better. At the same time, it would be nice to have some macro defined, declaring that such a keyword is available (that would be much better than testing the GCC version).
(In reply to comment #3) > > The documentation should be improved anyway (the word "suspicious" is very > subjective). > Please propose a patch. > > You should be able to work-around the macro case by casting the array to (char > > *) or perhaps casting to (void *) ? > > Yes, this makes sense. Perhaps this should be documented. Is it working? I meant to say "ideally" one should be able to do this but I don't think it is working right now (and probably there are not testcases testing this). > > How about something like __extension__, e.g. __no_warnings__ would disable the > warnings for the following statement or expression? If expression, one could There was a patch floating around in gcc-patches to implement that but since GCC location info is far from perfect (especially on macro expansions), I think it won't work well in practice. Moreover, the preferred way is to use the existing diagnostic pragmas. http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
Under Debian, I can no longer reproduce the problem with GCC 4.5.2: $ gcc-4.5 -Wall warn-nulladdress.c $ gcc-4.5 -Waddress warn-nulladdress.c $ gcc-4.4 -Wall warn-nulladdress.c warn-nulladdress.c: In function ‘main’: warn-nulladdress.c:14: warning: the address of ‘a’ will never be NULL $ gcc-4.4 -Waddress warn-nulladdress.c warn-nulladdress.c: In function ‘main’: warn-nulladdress.c:14: warning: the address of ‘a’ will never be NULL So, I assume that it has been fixed anyway. Do you confirm?
(In reply to comment #5) > > So, I assume that it has been fixed anyway. Do you confirm? I think the intention is to warn, at least for a == (void *)0, since the address of a cannot be zero or null. So I would say that this is a regression.
(In reply to comment #6) > I think the intention is to warn, at least for a == (void *)0, since the > address of a cannot be zero or null. So I would say that this is a regression. But this is valid in C, and in practice, such a test can occur in macro expansions: a macro can check whether some pointer is null before doing something with it. There shouldn't be a warning in such a case.
(In reply to comment #7) > (In reply to comment #6) > > I think the intention is to warn, at least for a == (void *)0, since the > > address of a cannot be zero or null. So I would say that this is a regression. > > But this is valid in C, and in practice, such a test can occur in macro > expansions: a macro can check whether some pointer is null before doing > something with it. There shouldn't be a warning in such a case. Every warning warns about something valid in C, otherwise it would be an error not a warning.
(In reply to comment #8) > Every warning warns about something valid in C, otherwise it would be an error > not a warning. No, for instance: int main(void) { int i; return i; } This is undefined behavior and detected by GCC, but one gets only a warning: tst.c: In function ‘main’: tst.c:4: warning: ‘i’ is used uninitialized in this function Compare to a == 0 in the above testcase, which has a well-defined behavior.
(In reply to comment #9) > This is undefined behavior and detected by GCC, but one gets only a warning: I am not going to waste time discussing the fine-points of what is a valid C program. If you don't want this warning, please contribute a testcase to gcc-patches@gcc.gnu.org, so this warning won't reappear in the future: http://gcc.gnu.org/wiki/HowToPrepareATestcase Otherwise, someone will come who thinks that this should be warned and they will "fix it".
(In reply to comment #10) > If you don't want this warning, please contribute a testcase to > gcc-patches@gcc.gnu.org, so this warning won't reappear in the future: Done: http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00624.html
Author: jsm28 Date: Fri Apr 1 19:36:23 2011 New Revision: 171850 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=171850 Log: 2011-04-01 Vincent Lefevre <vincent+gcc@vinc17.org> PR c/36299 * gcc.dg/Waddress.c: New test. Added: trunk/gcc/testsuite/gcc.dg/Waddress.c Modified: trunk/gcc/testsuite/ChangeLog
So fixed.