2017-08-22 00:32:57 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 %s
|
2017-07-26 03:23:23 +08:00
|
|
|
|
|
|
|
void clang_analyzer_numTimesReached();
|
2017-08-28 18:34:50 +08:00
|
|
|
void clang_analyzer_warnIfReached();
|
2017-07-26 03:23:23 +08:00
|
|
|
|
|
|
|
int getNum();
|
|
|
|
void foo(int &);
|
|
|
|
// Testing for loops.
|
|
|
|
int simple_unroll1() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{9}}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_unroll2() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{9}}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
2017-08-19 18:24:52 +08:00
|
|
|
|
|
|
|
for (int j = 0; j <= 9; ++j) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
a[j] = 42;
|
|
|
|
}
|
|
|
|
|
2017-07-26 03:23:23 +08:00
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_no_unroll1() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
foo(i);
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_no_unroll2() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
i += getNum();
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_no_unroll3() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
2017-08-28 18:34:50 +08:00
|
|
|
for (int i = 0; i < 9; i++) {
|
2017-07-26 03:23:23 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
(void)&i;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_no_unroll4() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
int &j = i;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_no_unroll5() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
int &j{i};
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-08-28 18:34:50 +08:00
|
|
|
int make_new_branches_loop_cached() {
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
if(getNum()){
|
|
|
|
(void) i; // Since this Stmt does not change the State the analyzer
|
|
|
|
// won't make a new execution path but reuse the earlier nodes.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clang_analyzer_warnIfReached(); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int make_new_branches_loop_uncached() {
|
|
|
|
int l = 2;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
if(getNum()){
|
|
|
|
++l;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
clang_analyzer_warnIfReached(); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int make_new_branches_loop_uncached2() {
|
|
|
|
int l = 2;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
if(getNum()){
|
|
|
|
++l;
|
|
|
|
}
|
|
|
|
(void)&i; // This ensures that the loop won't be unrolled.
|
|
|
|
}
|
|
|
|
clang_analyzer_warnIfReached(); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-08-19 18:24:52 +08:00
|
|
|
int escape_before_loop_no_unroll1() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
int &j = i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int escape_before_loop_no_unroll2() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
int *p = &i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int escape_before_loop_no_unroll3() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int i;
|
|
|
|
foo(i);
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-26 03:23:23 +08:00
|
|
|
int nested_outer_unrolled() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int j = 0;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{1}}
|
|
|
|
for (j = 0; j < 9; ++j) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
2017-07-26 03:23:23 +08:00
|
|
|
a[j] = 22;
|
2017-08-28 18:34:50 +08:00
|
|
|
(void) &j; // ensures that the inner loop won't be unrolled
|
2017-07-26 03:23:23 +08:00
|
|
|
}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nested_inner_unrolled() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int j = 0;
|
|
|
|
for (int i = 0; i < getNum(); i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{4}}
|
|
|
|
for (j = 0; j < 8; ++j) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{32}}
|
|
|
|
a[j] = 22;
|
|
|
|
}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nested_both_unrolled() {
|
|
|
|
int a[9];
|
|
|
|
int k = 42;
|
|
|
|
int j = 0;
|
|
|
|
for (int i = 0; i < 7; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{7}}
|
|
|
|
for (j = 0; j < 6; ++j) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{42}}
|
|
|
|
a[j] = 22;
|
|
|
|
}
|
|
|
|
a[i] = 42;
|
|
|
|
}
|
|
|
|
int b = 22 / (k - 42); // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_known_bound_loop() {
|
|
|
|
for (int i = 2; i < 12; i++) {
|
|
|
|
// This function is inlined in nested_inlined_unroll1()
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{90}}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int simple_unknown_bound_loop() {
|
|
|
|
for (int i = 2; i < getNum(); i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nested_inlined_unroll1() {
|
|
|
|
int k;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{9}}
|
|
|
|
k = simple_known_bound_loop(); // no reevaluation without inlining
|
|
|
|
}
|
|
|
|
int a = 22 / k; // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nested_inlined_no_unroll1() {
|
|
|
|
int k;
|
|
|
|
for (int i = 0; i < 9; i++) {
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{15}}
|
|
|
|
k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well
|
2017-07-26 03:23:23 +08:00
|
|
|
}
|
|
|
|
int a = 22 / k; // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-22 00:32:57 +08:00
|
|
|
|
|
|
|
|
|
|
|
int recursion_unroll1(bool b) {
|
|
|
|
int k = 2;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{13}}
|
|
|
|
if(i == 0 && b) // Splits the state in the first iteration but the recursion
|
|
|
|
// call will be unrolled anyway since the condition is known there.
|
2017-08-22 00:32:57 +08:00
|
|
|
recursion_unroll1(false);
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{14}}
|
2017-08-22 00:32:57 +08:00
|
|
|
}
|
|
|
|
int a = 22 / k; // no-warning
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int recursion_unroll2(bool b) {
|
|
|
|
int k = 0;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{9}}
|
2017-08-22 00:32:57 +08:00
|
|
|
if(i == 0 && b)
|
|
|
|
recursion_unroll2(false);
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{9}}
|
2017-08-22 00:32:57 +08:00
|
|
|
}
|
|
|
|
int a = 22 / k; // expected-warning {{Division by zero}}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int recursion_unroll3(bool b) {
|
|
|
|
int k = 2;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
if(i == 4 && b) {
|
|
|
|
recursion_unroll3(false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{10}}
|
|
|
|
}
|
|
|
|
int a = 22 / k;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int recursion_unroll4(bool b) {
|
|
|
|
int k = 2;
|
|
|
|
for (int i = 0; i < 5; i++) {
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{13}}
|
2017-08-22 00:32:57 +08:00
|
|
|
if(i == 0 && b) {
|
|
|
|
recursion_unroll4(false);
|
|
|
|
continue;
|
|
|
|
}
|
2017-08-28 18:34:50 +08:00
|
|
|
clang_analyzer_numTimesReached(); // expected-warning {{13}}
|
2017-08-22 00:32:57 +08:00
|
|
|
}
|
|
|
|
int a = 22 / k;
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-28 18:21:24 +08:00
|
|
|
|
|
|
|
int loop_exit_while_empty_loop_stack() {
|
|
|
|
if (getNum())
|
|
|
|
for (int i = 1; i < 8; i++)
|
|
|
|
;
|
|
|
|
return 0;
|
|
|
|
}
|
2017-08-28 18:34:50 +08:00
|
|
|
|