https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98646
--- Comment #12 from Martin Sebor <msebor at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #10) > So, the problem is IMHO that the warning about passing NULL to this is > misplaced, it shouldn't be done in the FEs, but later when there was at > least some chance of dead code removal. That would be a hack. First, the this argument to a member function is just like a plain argument to an ordinary nonnull function, so they all should be treated the same. Second, there already is code in tree-ssa-ccp.c to handle -Wnonnull, so nothing needs to be moved. The -Wnonnull code could be removed from the front end, but that would considerably compromise the warning: passing null pointers to inline member functions would cease to be diagnosed. See for example the effect on the code below. In C++ that wouldn't be a good deal. $ cat u.C && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout u.C struct S { int i; void f () { i = 0; }; void g (); }; void f (void) { S *p = 0; p->f (); // missing warning } void g (void) { S *p = 0; p->g (); // -Wnonnull (good) } ;; Function f (_Z1fv, funcdef_no=1, decl_uid=2357, cgraph_uid=2, symbol_order=1) (executed once) void f () { <bb 2> [local count: 1073741824]: MEM[(struct S *)0B].i ={v} 0; __builtin_trap (); } u.C: In function ‘void g()’: u.C:16:8: warning: ‘this’ pointer null [-Wnonnull] 16 | p->g (); // -Wnonnull (good) | ~~~~~^~ u.C:4:8: note: in a call to non-static member function ‘void S::g()’ 4 | void g (); | ^ ;; Function g (_Z1gv, funcdef_no=2, decl_uid=2360, cgraph_uid=3, symbol_order=2) void g () { <bb 2> [local count: 1073741824]: S::g (0B); [tail call] return; } Also, removing the -Wnonnull handling from the FE wouldn't actually solve the reported problem. It would just paper over it because the middle end warning doesn't consider PHIs yet. If/when it's enhanced to consider them the warning would come back again as is plain to see in the dump for the test case from comment #11: $ cat pr98646.C && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout pr98646.C struct A { virtual ~A (); }; struct B { virtual ~B (); B* f (); }; struct C: A, B { virtual ~C (); void g () const; }; void f (B *p) { static_cast<C*>(p->f ())->g (); // bogus -Wnonnull } ;; Function f (_Z1fP1B, funcdef_no=0, decl_uid=2430, cgraph_uid=1, symbol_order=0) Removing basic block 5 void f (struct B * p) { struct C * iftmp.0_1; struct B * _5; struct C * iftmp.0_6; <bb 2> [local count: 1073741824]: _5 = B::f (p_3(D)); if (_5 != 0B) goto <bb 3>; [70.00%] else goto <bb 4>; [30.00%] <bb 3> [local count: 751619281]: iftmp.0_6 = _5 + 18446744073709551608; <bb 4> [local count: 1073741824]: # iftmp.0_1 = PHI <iftmp.0_6(3), _5(2)> C::g (iftmp.0_1); [tail call] <<< should get a warning: pointer may be null return; } We can see that already today by running the analyzer on the test case: pr98646.C: In function ‘void f(B*)’: pr98646.C:8:31: warning: use of NULL where non-null expected [CWE-476] [-Wanalyzer-null-argument] 8 | static_cast<C*>(p->f ())->g (); // bogus -Wnonnull | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ ‘void f(B*)’: events 1-3 | | pr98646.C:4:38: note: argument 'this' of ‘void C::g() const’ must be non-null 4 | struct C: A, B { virtual ~C (); void g () const; }; | ^ Which is why, if we want to avoid these warnings, we need the front end to annotate the implicit COND_EXPR somehow. It could be done by setting TREE_NO_WARNING but I'd worry about it getting lost or unintentionally suppressing important warnings. Adding a special internal function instead and expanding it after the first -Wnonnull handler would be better.