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
  • [Bug tree-optimization/126378]... abeck at valvesoftware dot com via Gcc-bugs

Reply via email to