[PATCH] D12358: [Analyzer] Widening loops which do not exit
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 13 14:31:45 PDT 2015
dcoughlin added a comment.
> There is a loss of precision for loops that need to be executed exactly maxBlockVisitOnPath times, as the loop body is executed with the widened state instead of the last iteration.
I think this is an acceptable loss of precision because, in general, it is unlikely that a concrete-bounded loop will be executed *exactly* maxBlockVisitOnPath times. You could add special syntactic checks to try to detect this, but I think it is unlikely to make much different in practice.
================
Comment at: lib/StaticAnalyzer/Core/LoopWidening.cpp:64
@@ +63,3 @@
+ }
+ return PrevState->invalidateRegions(Regions, getLoopCondition(LoopStmt),
+ BlockCount, LCtx, false, nullptr,
----------------
Passing `true` here instead of `false` for `CausedByPointerEscape` should fix the false alarm. This will cause invalidation to tell the MallocChecker that the pointer has escaped and so shouldn't be treated as a leak.
================
Comment at: test/Analysis/loop-widening.c:3
@@ +2,3 @@
+
+extern void clang_analyzer_eval(_Bool);
+extern void clang_analyzer_warnIfReached();
----------------
There seems to be some weirdness when using `_Bool` in the prototype (vs. int). It adds an extra `!= 0` to symbolic expressions, which can result in clang_analyzer_eval() yielding `UNKNOWN` when using `extern void clang_analyze_eval(int)` would print `TRUE` or `FALSE`.
We should track this down and fix it, but for now I think it is better to use `extern void clang_analyze_eval(int)`.
================
Comment at: test/Analysis/loop-widening.c:13
@@ +12,3 @@
+ int x = 1;
+ // Check loop isn't widened by checking x isn't invalidated
+ for (i = 0; i < 1; ++i) {}
----------------
This is clever.
================
Comment at: test/Analysis/loop-widening.c:111
@@ +110,3 @@
+ }
+ if (i < 50) {
+ clang_analyzer_warnIfReached(); // no-warning
----------------
After changing the `clang_analyzer_eval()` prototype to take an int, you can use `clang_analyzer_eval(i >= 50); // expected-warning {{TRUE}}`.
================
Comment at: test/Analysis/loop-widening.c:158
@@ +157,3 @@
+ clang_analyzer_eval(h_ptr); // expected-warning {{UNKNOWN}}
+ free(h_ptr);
+}
----------------
I think it would be good to add some nested loop tests. For example:
```
void nested1() {
int i = 0, j = 0;
for (i = 0; i < 10; i++) {
clang_analyzer_eval(i < 10); // expected-warning {{TRUE}}
for (j = 0; j < 2; j++) {
clang_analyzer_eval(j < 2); // expected-warning {{TRUE}}
}
clang_analyzer_eval(j >= 2); // expected-warning {{TRUE}}
}
clang_analyzer_eval(i >= 10); // expected-warning {{TRUE}}
}
void nested2() {
int i = 0, j = 0;
for (i = 0; i < 2; i++) {
clang_analyzer_eval(i < 2); // expected-warning {{TRUE}}
for (j = 0; j < 10; j++) {
clang_analyzer_eval(j < 10); // expected-warning {{TRUE}}
}
clang_analyzer_eval(j >= 10); // expected-warning {{TRUE}}
}
clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
}
```
http://reviews.llvm.org/D12358
More information about the cfe-commits
mailing list