[Bug tree-optimization/126378] New: spurious -Wnonnull "'this' pointer is null" at -O2 for pointer guarded by preceding null checks (regression from 10.x)

abeck at valvesoftware dot com via Gcc-bugs <[email protected]>
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.