Files
clang-p2996/clang/test/Analysis/loop-unrolling.cpp
Peter Szecsi 1496d188a0 [analyzer] LoopUnrolling: check the bitwidth of the used numbers (pr34943)
The loop unrolling feature aims to track the maximum possible steps a loop can
make. In order to implement this, it investigates the initial value of the 
counter variable and the bound number. (It has to be known.)
These numbers are used as llvm::APInts, however, it was not checked if their
bitwidths are the same which lead to some crashes.
This revision solves this problem by extending the "shorter" one (to the length
of the "longer" one).
For the detailed bug report, see: https://bugs.llvm.org/show_bug.cgi?id=34943

Differential Revision: https://reviews.llvm.org/D38922

llvm-svn: 316830
2017-10-28 12:19:08 +00:00

382 lines
8.7 KiB
C++

// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 %s
void clang_analyzer_numTimesReached();
void clang_analyzer_warnIfReached();
int getNum();
void foo(int &);
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;
}
for (int j = 0; j <= 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{10}}
a[j] = 42;
}
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;
for (int i = 0; i < 9; i++) {
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;
}
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;
}
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;
}
int nested_outer_unrolled() {
int a[9];
int k = 42;
int j = 0;
for (int i = 0; i < 9; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (j = 0; j < 9; ++j) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
a[j] = 22;
(void) &j; // ensures that the inner loop won't be unrolled
}
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++) {
clang_analyzer_numTimesReached(); // expected-warning {{15}}
k = simple_unknown_bound_loop(); // reevaluation without inlining, splits the state as well
}
int a = 22 / k; // no-warning
return 0;
}
int recursion_unroll1(bool b) {
int k = 2;
for (int i = 0; i < 5; i++) {
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.
recursion_unroll1(false);
clang_analyzer_numTimesReached(); // expected-warning {{14}}
}
int a = 22 / k; // no-warning
return 0;
}
int recursion_unroll2(bool b) {
int k = 0;
for (int i = 0; i < 5; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{9}}
if(i == 0 && b)
recursion_unroll2(false);
clang_analyzer_numTimesReached(); // expected-warning {{9}}
}
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++) {
clang_analyzer_numTimesReached(); // expected-warning {{13}}
if(i == 0 && b) {
recursion_unroll4(false);
continue;
}
clang_analyzer_numTimesReached(); // expected-warning {{13}}
}
int a = 22 / k;
return 0;
}
int loop_exit_while_empty_loop_stack() {
if (getNum())
for (int i = 1; i < 8; i++)
;
return 0;
}
int num_steps_on_limit() {
for (int i = 0; i < 128; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
clang_analyzer_numTimesReached(); // expected-warning {{1}}
return 0;
}
int num_steps_over_limit1() {
for (int i = 0; i < 129; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
return 0;
}
int num_steps_on_limit2() {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 64; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
}
return 0;
}
int num_steps_over_limit2() {
for (int i = 0; i < 2; i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (int j = 0; j <= 64; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
}
return 0;
}
int num_steps_on_limit3() {
for (int i = 0; i < getNum(); i++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
for (int j = 0; j < 32; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{128}}
}
}
return 0;
}
int num_steps_over_limit3() {
for (int i = 0; i < getNum(); i++) {
clang_analyzer_numTimesReached(); // expected-warning {{1}}
for (int j = 0; j < 33; j++) {
clang_analyzer_numTimesReached(); // expected-warning {{4}}
}
}
return 0;
}
void pr34943() {
for (int i = 0; i < 6L; ++i) {
clang_analyzer_numTimesReached(); // expected-warning {{6}}
}
}