https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126378
Bug ID: 126378
Summary: spurious -Wnonnull "'this' pointer is null" at -O2 for
pointer guarded by preceding null checks (regression
from 10.x)
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: abeck at valvesoftware dot com
Target Milestone: ---
The following test case produces a spurious -Wnonnull warning starting
with GCC 11 through current trunk. GCC 10.5 compiles it without a warning
at every optimization level. Trunk produces warning at -O2.
$ cat repro.cpp
struct C
{
// declaration-only == "in another TU"
int get();
};
int impl( C *p, int *q )
{
if ( !p && !q )
return 0;
// after this: p!=0 || q!=0
// get() only when q==0 => p!=0 here
return q ? *q : p->get();
}
int call( int *q )
{
// inlines impl with p==nullptr
return impl( nullptr, q );
}
$ g++ -O2 -c repro.cpp
In function 'int impl(C*, int*)',
inlined from 'int impl(C*, int*)' at repro.cpp:7:5,
inlined from 'int call(int*)' at repro.cpp:21:16:
repro.cpp:15:27: warning: 'this' pointer is null [-Wnonnull]
15 | return q ? *q : p->get();
| ~~~~~~^~
repro.cpp: In function 'int call(int*)':
repro.cpp:4:9: note: in a call to non-static member function 'int C::get()'
4 | int get();
| ^~~
p->get() is never evaluated with p == nullptr: the early return
establishes p != 0 || q != 0, and the call is only reached when q == 0.
The warning is emitted after impl() is inlined into call() with
p == nullptr.
Results by version and optimization level ("W" = warns):
-O0 -O1 -O2 -O3
10.5.0 - - - -
11.1.0 - - W W
12.5.0 - - W W
13.4.0 - - W W
14.1.0 - - W -
16.1.0 - - W -
17.0.0 - - W -
First observed with 11.1, as of 14.1.0 trunk no longer warns at -O3.
Related PRs:
PR 100086 - spurious -Wnonnull with __builtin_expect. Same pattern:
the warning is emitted for a call guarded by a preceding null check,
with the guard written using __builtin_expect instead of ?:.
PR 122083 - bogus -Wnonnull for call to memcmp with length determined
using <=> operator.
Compiler Explorer: https://godbolt.org/z/qrvEvxnd6