https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108028
--- Comment #3 from ming mengli <mengli.ming at outlook dot com> --- (In reply to David Malcolm from comment #1) > Thanks for filing this bug. > > There are several things going on here. > > (A): the analyzer is considering the function "f" as called standalone, as > well as the case where it's called from "main", rather than merely > considering it when it's called from "main". There are a few other bug > reports about that; it's not clear to me what we should do for this case; is > it expected that such functions are only ever called from main? > > The situation is clearer if we simply delete "main" from the reproducer. > With that, we see: > > 'f': events 1-3 > | > | 7 | if (p && (0 == q)) > | | ^ > | | | > | | (1) following 'true' branch... > | 8 | { > | 9 | __analyzer_eval(p && (0 == q)); > | | ~~~~~~~~~~~~~~~ > | | | > | | (2) ...to here > |...... > | 14 | *q = 1; > | | ~~~~~~ > | | | > | | (3) dereference of NULL '0' > | > > > (B) arguably the CFG event (1) to (2) is poorly worded; at (1) we have > "following 'true' branch...", which suggests it always follows the 'true' > branch, whereas it's merely considering what happens *if* we take the 'true' > branch. > > If it read: e.g.: > > 'f': events 1-3 > | > | 7 | if (p && (0 == q)) > | | ^ > | | | > | | (1) considering following 'true' branch (implying that > 'q' is NULL)... > | 8 | { > | 9 | __analyzer_eval(p && (0 == q)); > | | ~~~~~~~~~~~~~~~ > | | | > | | (2) ...to here > |...... > | 14 | *q = 1; > | | ~~~~~~ > | | | > | | (3) dereference of NULL '0' > | > > the analyzer would be more obviously correct and useful. > > Or even "considering when 'q' is NULL; following 'true' branch..." > > I've been experimenting with making the wording here clearer > (i): should make a distinction between when the analyzer chooses one of > several paths to consider, versus when the choice of execution path is > already determined by previous choices > (ii): would be nice to capture that q's nullness is the most interesting > property at the "if" statement with respect to the warning, and express that > to the user. > > > (C) The analyzer runs relatively late compared to most static analyzers, so > the optimization levels affect things. In particular, consider the gimple > IR seen by -fanalyzer for the assignment: > *q = 1; > in the block guarded by (0 == q). > > At -O1 we have: > *q_10(D) = 1; > but at -O2 it converts it to: > MEM[(int *)0B] = 1; > > Arguably it's a bug here that we only warn at -O2 and above; analyzing "f" > standalone, we ought to be complaining about the null dereference without > needing -O2. > (specifically, at -O2 -fanalyzer sees a deref of NULL, whereas at -O1 it > merely sees a deref of INIT_VAL(q), whilst knowing the constraint that > INIT_VAL(q) is NULL. > The __analyzer_eval results are also due to gimple IR differences caused by > the optimizer. > > Also, perhaps we should run earlier; I probably ought to file a bug about > that, it's a big can of worms. Thanks a lot for your explanation of this bug, it helps a lot. I think it's perfectly feasible to consider both cases for that such functions to be analyzed standalone and from the main function, sorry I didn't express myself clearly on that point. Feel free to let us know if we could do anything to help with these. We hope gcc static analyzer will get better.