Some AST nodes that stands for implicit initialization is shared. The analyzer will do the same evaluation on the same nodes resulting in the same state. The analyzer will "cache out", i.e. it thinks that it visited an already existing node in the exploded graph. This is not true in this case and we lose coverage.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Ahaa. Ahaa. Okay.
So the AST is like
| |-DeclStmt 0x7f9f3b8932e0 <line:6:3, col:43> | | `-VarDecl 0x7f9f3b892f50 <col:3, col:42> col:7 used a 'int [5]' cinit | | `-InitListExpr 0x7f9f3b893268 <col:14, col:42> 'int [5]' | | |-array_filler: ImplicitValueInitExpr 0x7f9f3b8932d0 <<invalid sloc>> 'int' | | |-IntegerLiteral 0x7f9f3b893118 <col:41> 'int' 4 | | |-ImplicitValueInitExpr 0x7f9f3b8932d0 <<invalid sloc>> 'int' | | |-IntegerLiteral 0x7f9f3b893078 <col:31> 'int' 15 | | |-ImplicitValueInitExpr 0x7f9f3b8932d0 <<invalid sloc>> 'int' | | `-IntegerLiteral 0x7f9f3b892fd8 <col:21> 'int' 29
And the CFG is like
[B1] 1: 4 2: [B1.4] 3: 15 4: /*implicit*/(int)0 5: 29 6: {[4] = [B1.5], [2] = [B1.3], [0] = [B1.1]} 7: int a[5] = {[4] = 29, [2] = 15, [0] = 4};
And you're trying to avoid agglutinating program points for [B1.2] and [B1.4].
Can we simply erase the implicit initializers from the CFG? Under an option, of course. We ignore them in the static analyzer anyway (like all constants).
We could do a custom program point just for this problem (which includes the index as part of its identity), but it's kinda underwhelming to build a whole new program point that always does nothing.
One way to criticize the current solution would be to put an InitListExpr in a loop and immediately discard it and see how states after different numbers of iterations no longer join together only because they have different NoCachingOutForConsts values.
Hmm loops. Right. So this solution is insufficient because it can prevent legitimate caching out in loops.
If we remove those initializers from the CFG wouldn't we loose the Pre/PostStmt callbacks? Is that acceptable? If not, we might need to create a new program point :(
I doubt we'll ever need these callbacks. I can't imagine any kind of analysis that would need them. Like, these statements have absolutely no effect on the runtime program state.
Thanks!!
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | ||
---|---|---|
1323–1328 | We already have a similar unreachable here :p |
We already have a similar unreachable here :p