The following has been reduced from Red Hat bug https://bugzilla.redhat.com/show_bug.cgi?id=1948775. In the original code the warning points to the this pointer in a call to a member function (which first became subject to the warning in GCC 11) but the same issue can be reproduced with any other nonnull function such as the call to __builtin_puts(0B) in the IL. Replacing the __builtin_expect call with a plain test avoids the warning, as does removing the indirection via AssertionResult. $ cat rhbz1948775.C && gcc -O2 -S -Wall -fdump-tree-post_ipa_warn=/dev/stdout rhbz1948775.C struct string { char *p; }; string GetMessage(); struct AssertionResult { AssertionResult (bool b) : b_(b) { } operator bool() const { return b_; } bool b_; }; struct AssertHelper { AssertHelper (const char*); void operator=(int); }; struct RefPtr { ~RefPtr() { if (__builtin_expect ((p != 0), 1)) __builtin_puts (p); } operator bool() const { return !!p; } char *p; }; RefPtr take (); void TestBody () { RefPtr emptyTake = take (); if (!AssertionResult (!emptyTake)) return AssertHelper(GetMessage().p) = 1; } ;; Function TestBody (_Z8TestBodyv, funcdef_no=8, decl_uid=2417, cgraph_uid=9, symbol_order=8) In destructor ‘RefPtr::~RefPtr()’, inlined from ‘void TestBody()’ at rhbz1948775.C:43:1: rhbz1948775.C:26:22: warning: argument 1 null where non-null expected [-Wnonnull] 26 | __builtin_puts (p); | ~~~~~~~~~~~~~~~^~~ rhbz1948775.C: In function ‘void TestBody()’: rhbz1948775.C:26:22: note: in a call to built-in function ‘int __builtin_puts(const char*)’ void TestBody () { struct RefPtr emptyTake; struct string D.2464; struct AssertHelper D.2492; bool _1; char * _2; char * _14; bool _15; char * _16; bool _17; long int _18; long int _19; long int _20; long int _21; char * _22; bool _23; long int _24; long int _25; <bb 2> [local count: 1073741824]: emptyTake = take (); [return slot optimization] _14 = emptyTake.p; _15 = _14 != 0B; _1 = _14 == 0B; if (_1 != 0) goto <bb 9>; [79.76%] else goto <bb 3>; [20.24%] <bb 3> [local count: 217325344]: D.2464 = GetMessage (); <bb 4> [local count: 217325344]: _2 = D.2464.p; AssertHelper::AssertHelper (&D.2492, _2); <bb 5> [local count: 217325344]: AssertHelper::operator= (&D.2492, 1); <bb 6> [local count: 217325344]: D.2492 ={v} {CLOBBER}; _16 = emptyTake.p; _17 = _16 != 0B; _18 = (long int) _17; _19 = _18; if (_19 != 0) goto <bb 7>; [90.00%] else goto <bb 8>; [10.00%] <bb 7> [local count: 195592809]: __builtin_puts (_16); <bb 8> [local count: 217325344]: emptyTake ={v} {CLOBBER}; emptyTake ={v} {CLOBBER}; goto <bb 12>; [100.00%] <bb 9> [local count: 856416481]: _20 = (long int) _15; _21 = _20; if (_21 != 0) goto <bb 10>; [90.00%] else goto <bb 11>; [10.00%] <bb 10> [local count: 770774832]: __builtin_puts (0B); <<< -Wnonnull <bb 11> [local count: 856416481]: emptyTake ={v} {CLOBBER}; emptyTake ={v} {CLOBBER}; <bb 12> [local count: 1073741824]: return; <bb 13> [count: 0]: <L8>: D.2492 ={v} {CLOBBER}; _22 = emptyTake.p; _23 = _22 != 0B; _24 = (long int) _23; _25 = _24; if (_25 != 0) goto <bb 14>; [0.00%] else goto <bb 15>; [0.00%] <bb 14> [count: 0]: __builtin_puts (_22); <bb 15> [count: 0]: emptyTake ={v} {CLOBBER}; resx 2 }
According to my bisection the warning first appeared in GCC 11, with g:fcae5121154d1c3382b056bcc2c563cedac28e74. Before then the post_ipa_warn dump looked like so: ;; Function TestBody (_Z8TestBodyv, funcdef_no=8, decl_uid=2406, cgraph_uid=9, symbol_order=8) TestBody () { struct RefPtr emptyTake; struct string D.2453; struct AssertHelper D.2481; bool _1; char * _2; char * _14; bool _15; char * _16; bool _17; long int _18; long int _19; long int _20; long int _21; char * _22; bool _23; long int _24; long int _25; <bb 2> [local count: 1073741824]: emptyTake = take (); [return slot optimization] _14 = emptyTake.p; _15 = _14 != 0B; _1 = _14 == 0B; if (_1 != 0) goto <bb 9>; [79.76%] else goto <bb 3>; [20.24%] <bb 3> [local count: 217325344]: D.2453 = GetMessage (); <bb 4> [local count: 217325344]: _2 = D.2453.p; AssertHelper::AssertHelper (&D.2481, _2); <bb 5> [local count: 217325344]: AssertHelper::operator= (&D.2481, 1); <bb 6> [local count: 217325344]: D.2481 ={v} {CLOBBER}; _16 = emptyTake.p; _17 = _16 != 0B; _18 = (long int) _17; _19 = _18; if (_19 != 0) goto <bb 7>; [90.00%] else goto <bb 8>; [10.00%] <bb 7> [local count: 195592809]: __builtin_puts (_16); <bb 8> [local count: 217325344]: emptyTake ={v} {CLOBBER}; emptyTake ={v} {CLOBBER}; goto <bb 12>; [100.00%] <bb 9> [local count: 856416481]: _20 = (long int) _15; _21 = _20; if (_21 != 0) goto <bb 10>; [90.00%] else goto <bb 11>; [10.00%] <bb 10> [local count: 770774832]: __builtin_puts (_14); <bb 11> [local count: 856416481]: emptyTake ={v} {CLOBBER}; emptyTake ={v} {CLOBBER}; <bb 12> [local count: 1073741824]: return; <bb 13> [count: 0]: <L8>: D.2481 ={v} {CLOBBER}; _22 = emptyTake.p; _23 = _22 != 0B; _24 = (long int) _23; _25 = _24; if (_25 != 0) goto <bb 14>; [0.00%] else goto <bb 15>; [0.00%] <bb 14> [count: 0]: __builtin_puts (_22); <bb 15> [count: 0]: emptyTake ={v} {CLOBBER}; resx 2 }
GCC 11.1 has been released, retargeting bugs to GCC 11.2.
GCC 11.2 is being released, retargeting bugs to GCC 11.3
The testcase no longer reproduces the issue with GCC 12 for me, GCC 11 still does. I wonder what fixed it.
(In reply to Richard Biener from comment #4) > The testcase no longer reproduces the issue with GCC 12 for me, GCC 11 still > does. I wonder what fixed it. Fixed with r12-1546-g786188e8b8cab47c.
GCC 11.3 is being released, retargeting bugs to GCC 11.4.
GCC 11.4 is being released, retargeting bugs to GCC 11.5.