See reviews.llvm.org/M1 for evaluation, and lists.llvm.org/pipermail/cfe-dev/2018-January/056718.html for discussion.
Details
Diff Detail
- Repository
- rC Clang
Event Timeline
Switching to CFGBlocks made # of bug reports / % coverage slightly worse compared to the version using Stmt *, I am still confused as to why.
Removing StackFrameContext* from location identifier makes everything considerably worse.
@NoQ I think this version can go in.
I think you should add a test with foo() in else-branch as well, which has always passed, just to demonstrate that regardless of accidental if-branch analysis order we're doing the right thing.
More minor nits, but yeah, this is great :)
lib/StaticAnalyzer/Core/CoreEngine.cpp | ||
---|---|---|
137 | Does this invariant keep holding after we put the node here? Like, what if it wasn't traversed when we were putting it here, but while it's in the stack we've traversed it on a different path? Suggests: NormalPriorityStack, LowPriorityStack. Explaining that the latter contains beginnings of paths that were down-prioritized because they lead into blocks that we've already visited in this function. | |
145 | Capitalize? | |
157 | Essentially we assume that we made the right choice on the block edge and the node is now being explored for a good reason, and now that we went down this path, there's no need to downprioritize other elements in this block. |
lib/StaticAnalyzer/Core/CoreEngine.cpp | ||
---|---|---|
137 |
Surprisingly, it does: the key here is that we check exploration at the push-time, not at the pop-time. That is, the block is added to "reachable" not when we explore it, but when we put the corresponding node into queue. |
All right, so for now it is under the flag (-analyzer-config exploration_strategy=unexplored_first), it already makes a huge lot of sense, and it has tests, so i think we should land it now and flip the flag when we're ready.
It'd be great to have more direct tests for the exploration order, not just for the bugs. Probably dump CFG blocks in the traversal order, or even dump whole worklist snapshots for every analysis step - the latter seemed very useful while understanding the issue (we did it on the whiteboard, but i've no idea how huge would it be in practice, even if we still dump only CFG blocks of worklist units), because, as the original issue has demonstrated, even our simple DFS exploration may be completely counter-intuitive sometimes.
but i've no idea how huge would it be in practice
It's actually pretty small if we only do it for BlockEntrance edges.
Do you have any concrete ideas on how such dumping could be done? I could debug it by printing to llvm::errs(), but that's obviously not optimal.
I could use DEBUG(), but that's hacky, fragile, and would not even work in release builds.
I don't think I have good ideas left.
Does this invariant keep holding after we put the node here? Like, what if it wasn't traversed when we were putting it here, but while it's in the stack we've traversed it on a different path?
Suggests: NormalPriorityStack, LowPriorityStack. Explaining that the latter contains beginnings of paths that were down-prioritized because they lead into blocks that we've already visited in this function.