4

I've written following code:

void foo(int& x)
{
  bool b1 = (&x) == nullptr;
  bool b2 = &x == nullptr;
  int* ptr = &x;
  bool b3 = ptr == nullptr;
}

For the code above, I'm getting following errors:

For b1 variable:

test.cpp:5:21: warning: nonnull argument ‘x’ compared to NULL [-Wnonnull-compare]

For b2 variable:

test.cpp:6:19: warning: the compiler can assume that the address of ‘x’ will never be NULL [-Waddress]

test.cpp:6:19: warning: nonnull argument ‘x’ compared to NULL [-Wnonnull-compare]

And no warning for b3.

I understand why compiler returned a warning, that 'x' will never be NULL. However I don't understand why this warning has been returned only for the b2, and not a b1.

Also, I don't really understand what does it mean, that '&x' is a nonnull argument. Does it mean, that pointer to reference is not of type T*, but it has a special type, which is cast-able to T*?

If it does matter, I use compiler g++ (GCC) 6.2.1

Thanks for all your hints.

Community
  • 1
  • 1
Marcin Kolny
  • 633
  • 7
  • 14
  • I don't have those warnings, have you tried swapping the line with b1 and the line with b2? – Dominique Lorre Sep 17 '16 at 18:37
  • 1
    I'm guessing that since this is just a helpful warning and isn't a common case, gcc doesn't have very advanced rules for producing the warning and it is confused by the extra level of indirection provided by the intermediate variable. – Michael McGuire Sep 17 '16 at 18:37
  • @DominiqueLorre yes, I've tried to swap them, but the same result. – Marcin Kolny Sep 17 '16 at 18:40
  • `g++ -c foo.cc -std=gnu++0x -Wall foo.cc: In function ‘void foo(int&)’: foo.cc:6:8: warning: unused variable ‘b1’ [-Wunused-variable] bool b1 = (&x) == nullptr; ^ foo.cc:7:8: warning: unused variable ‘b2’ [-Wunused-variable] bool b2 = &x == nullptr; ^ foo.cc:9:8: warning: unused variable ‘b3’ [-Wunused-variable] bool b3 = ptr == nullptr;` – Dominique Lorre Sep 17 '16 at 18:53
  • What's your g++ version? of course, I didn't post unused-variable warnings, since they're not related to the real problem – Marcin Kolny Sep 17 '16 at 18:58
  • gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 from Ubuntu 16 -- same for g++ – Dominique Lorre Sep 17 '16 at 19:01
  • Can you rephrase your question? You say you understand the warning, then you say you don't understand it. You day that `b1` yields a warning, then you say it doesnt. Which is it? And what's the question? – Barry Sep 17 '16 at 19:02
  • @Barry I said that I do understand only one warning, but the code causes 3 warnings. And I said, that b1 generates only one warning, but b2 - two warnings. – Marcin Kolny Sep 17 '16 at 19:05
  • @MarcinKolny Why does it matter that you get one warning for `b1` and two warnings for `b2`? You get the same, useful warning in both cases. – Barry Sep 17 '16 at 19:55
  • @Barry I just wanted to understand, why in one case, I'm getting two warnings, and in the other one - one warning. Also, why there are two type of warnings, which probably mean the same. – Marcin Kolny Sep 17 '16 at 21:30

1 Answers1

1

Reason for the extra message for b2: Because the left-hand-side of the '==' is the address of x - directly - the compiler can tell that one of the terms of the comparison is an immediately-evaluated pointer, and so can issue the warning. By contrast, the use of parentheses for b1 adds a level of indirection in the parse - 'outside' the parentheses, the compiler knows only that that is some expression which evaluates to a pointer. Since it is rare that a single item would be parenthesized this way in production code, the compiler writer wouldn't have thought it worth the effort to check if what was inside the parentheses was just a single term in order to issue the same message (assuming the compiler writer even noticed the issue).

PMar
  • 11
  • 1