https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108325
Bug ID: 108325 Summary: -Wanalyzer-null-dereference false positive with *f = 42 Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: analyzer Assignee: dmalcolm at gcc dot gnu.org Reporter: mengli.ming at outlook dot com Target Milestone: --- I got a false positive error when compiling the following program with gcc(trunk) `-O0 -fanalyzer` in https://godbolt.org/z/db7v3PGYe. In this case, the eval statement in line 16 gives two results, FALSE and UNKNOWN. The UNKNOWN here is a little odd, and then analyzer analyzes the codes inside the if statement, however, these are unreachable codes. Input: ``` #include "stdio.h" #include "stdbool.h" void __analyzer_eval(int); struct a { int b; } c() { struct a d = {1}; int e = 0; int *f = (int *)e; for (d.b = 0; e == 0; e++) { __analyzer_eval(true == ((!d.b) && e)); if ((!d.b) && e) { __analyzer_eval(true == ((!d.b) && e)); *f = 42; } } } void main() { c(); } ``` Output: ``` <source>: In function 'c': <source>:16:9: warning: FALSE 16 | __analyzer_eval(true == ((!d.b) && e)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:16:9: warning: UNKNOWN <source>:19:13: warning: TRUE 19 | __analyzer_eval(true == ((!d.b) && e)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:16:9: warning: FALSE 16 | __analyzer_eval(true == ((!d.b) && e)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:16:9: warning: FALSE <source>:16:9: warning: UNKNOWN <source>:19:13: warning: TRUE 19 | __analyzer_eval(true == ((!d.b) && e)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:16:9: warning: FALSE 16 | __analyzer_eval(true == ((!d.b) && e)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:20:16: warning: dereference of NULL 'f' [CWE-476] [-Wanalyzer-null-dereference] 20 | *f = 42; | ~~~^~~~ 'c': events 1-20 | | 12 | int *f = (int *)e; | | ^ | | | | | (1) 'f' is NULL | 13 | | 14 | for (d.b = 0; e == 0; e++) | | ~~~~~~ ~~~ | | | | | | | (11) ...to here | | (2) following 'true' branch (when 'e == 0')... | | (12) following 'true' branch (when 'e == 0')... | 15 | { | 16 | __analyzer_eval(true == ((!d.b) && e)); | | ~~~~~~~~~~~~~ | | | | | | | (4) following 'true' branch... | | | (5) ...to here | | | (6) following 'false' branch (when 'e == 0')... | | | (7) ...to here | | | (14) following 'true' branch... | | | (15) ...to here | | (3) ...to here | | (13) ...to here | 17 | if ((!d.b) && e) | | ~~~~~~~~~~~~ | | | | | | | (9) ...to here | | | (10) following 'false' branch (when 'e == 0')... | | | (17) ...to here | | (8) following 'true' branch... | | (16) following 'true' branch... | 18 | { | 19 | __analyzer_eval(true == ((!d.b) && e)); | | ~~~~~~~~~~~~~ | | | | | (18) following 'true' branch... | | (19) ...to here | 20 | *f = 42; | | ~~~~~~~ | | | | | (20) dereference of NULL 'f' | ``` I set it directly to 0 in the initialization of `d.b`, and then keep the semantics of the for loop executing only one time, and after making the following transformation (https://godbolt.org/z/nvePK1sdb), the NPD warning disappeared, and the eval statement in line 19 is not output. Thank you for taking the time to review these cases.