1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -analyzer-config unroll-loops=true,cfg-loopexit=true -verify -std=c++11 %s
2 
3 void clang_analyzer_numTimesReached();
4 void clang_analyzer_warnIfReached();
5 
6 int getNum();
7 void foo(int &);
8 
9 int simple_unroll1() {
10   int a[9];
11   int k = 42;
12   for (int i = 0; i < 9; i++) {
13     clang_analyzer_numTimesReached(); // expected-warning {{9}}
14     a[i] = 42;
15   }
16   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
17   return 0;
18 }
19 
20 int simple_unroll2() {
21   int a[9];
22   int k = 42;
23   int i;
24   for (i = 0; i < 9; i++) {
25     clang_analyzer_numTimesReached(); // expected-warning {{9}}
26     a[i] = 42;
27   }
28 
29   for (int j = 0; j <= 9; ++j) {
30     clang_analyzer_numTimesReached(); // expected-warning {{10}}
31     a[j] = 42;
32   }
33 
34   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
35   return 0;
36 }
37 
38 int simple_no_unroll1() {
39   int a[9];
40   int k = 42;
41   for (int i = 0; i < 9; i++) {
42     clang_analyzer_numTimesReached(); // expected-warning {{4}}
43     a[i] = 42;
44     foo(i);
45   }
46   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
47   return 0;
48 }
49 
50 int simple_no_unroll2() {
51   int a[9];
52   int k = 42;
53   int i;
54   for (i = 0; i < 9; i++) {
55     clang_analyzer_numTimesReached(); // expected-warning {{4}}
56     a[i] = 42;
57     i += getNum();
58   }
59   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
60   return 0;
61 }
62 
63 int simple_no_unroll3() {
64   int a[9];
65   int k = 42;
66   for (int i = 0; i < 9; i++) {
67     clang_analyzer_numTimesReached(); // expected-warning {{4}}
68     a[i] = 42;
69     (void)&i;
70   }
71   int b = 22 / (k - 42); // no-warning
72   return 0;
73 }
74 
75 int simple_no_unroll4() {
76   int a[9];
77   int k = 42;
78   int i;
79   for (i = 0; i < 9; i++) {
80     clang_analyzer_numTimesReached(); // expected-warning {{4}}
81     a[i] = 42;
82     int &j = i;
83   }
84   int b = 22 / (k - 42); // no-warning
85   return 0;
86 }
87 
88 int simple_no_unroll5() {
89   int a[9];
90   int k = 42;
91   int i;
92   for (i = 0; i < 9; i++) {
93     clang_analyzer_numTimesReached(); // expected-warning {{4}}
94     a[i] = 42;
95     int &j{i};
96   }
97   int b = 22 / (k - 42); // no-warning
98   return 0;
99 }
100 
101 int make_new_branches_loop_cached() {
102   for (int i = 0; i < 8; i++) {
103     clang_analyzer_numTimesReached(); // expected-warning {{4}}
104     if(getNum()){
105         (void) i; // Since this Stmt does not change the State the analyzer
106                   // won't make a new execution path but reuse the earlier nodes.
107       }
108   }
109   clang_analyzer_warnIfReached(); // no-warning
110   return 0;
111 }
112 
113 int make_new_branches_loop_uncached() {
114   int l = 2;
115   for (int i = 0; i < 8; i++) {
116     clang_analyzer_numTimesReached(); // expected-warning {{10}}
117     if(getNum()){
118       ++l;
119     }
120   }
121   clang_analyzer_warnIfReached(); // no-warning
122   return 0;
123 }
124 
125 int make_new_branches_loop_uncached2() {
126   int l = 2;
127   for (int i = 0; i < 8; i++) {
128     clang_analyzer_numTimesReached(); // expected-warning {{10}}
129     if(getNum()){
130       ++l;
131     }
132     (void)&i; // This ensures that the loop won't be unrolled.
133   }
134   clang_analyzer_warnIfReached(); // no-warning
135   return 0;
136 }
137 
138 
139 int escape_before_loop_no_unroll1() {
140   int a[9];
141   int k = 42;
142   int i;
143   int &j = i;
144   for (i = 0; i < 9; i++) {
145     clang_analyzer_numTimesReached(); // expected-warning {{4}}
146     a[i] = 42;
147   }
148   int b = 22 / (k - 42); // no-warning
149   return 0;
150 }
151 
152 int escape_before_loop_no_unroll2() {
153   int a[9];
154   int k = 42;
155   int i;
156   int *p = &i;
157   for (i = 0; i < 9; i++) {
158     clang_analyzer_numTimesReached(); // expected-warning {{4}}
159     a[i] = 42;
160   }
161   int b = 22 / (k - 42); // no-warning
162   return 0;
163 }
164 
165 int escape_before_loop_no_unroll3() {
166   int a[9];
167   int k = 42;
168   int i;
169   foo(i);
170   for (i = 0; i < 9; i++) {
171     clang_analyzer_numTimesReached(); // expected-warning {{4}}
172     a[i] = 42;
173   }
174   int b = 22 / (k - 42); // no-warning
175   return 0;
176 }
177 
178 int nested_outer_unrolled() {
179   int a[9];
180   int k = 42;
181   int j = 0;
182   for (int i = 0; i < 9; i++) {
183     clang_analyzer_numTimesReached(); // expected-warning {{1}}
184     for (j = 0; j < 9; ++j) {
185       clang_analyzer_numTimesReached(); // expected-warning {{4}}
186       a[j] = 22;
187       (void) &j; // ensures that the inner loop won't be unrolled
188     }
189     a[i] = 42;
190   }
191   int b = 22 / (k - 42); // no-warning
192   return 0;
193 }
194 
195 int nested_inner_unrolled() {
196   int a[9];
197   int k = 42;
198   int j = 0;
199   for (int i = 0; i < getNum(); i++) {
200     clang_analyzer_numTimesReached(); // expected-warning {{4}}
201     for (j = 0; j < 8; ++j) {
202       clang_analyzer_numTimesReached(); // expected-warning {{32}}
203       a[j] = 22;
204     }
205     a[i] = 42;
206   }
207   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
208   return 0;
209 }
210 
211 int nested_both_unrolled() {
212   int a[9];
213   int k = 42;
214   int j = 0;
215   for (int i = 0; i < 7; i++) {
216     clang_analyzer_numTimesReached(); // expected-warning {{7}}
217     for (j = 0; j < 6; ++j) {
218       clang_analyzer_numTimesReached(); // expected-warning {{42}}
219       a[j] = 22;
220     }
221     a[i] = 42;
222   }
223   int b = 22 / (k - 42); // expected-warning {{Division by zero}}
224   return 0;
225 }
226 
227 int simple_known_bound_loop() {
228   for (int i = 2; i < 12; i++) {
229     // This function is inlined in nested_inlined_unroll1()
230     clang_analyzer_numTimesReached(); // expected-warning {{90}}
231   }
232   return 0;
233 }
234 
235 int simple_unknown_bound_loop() {
236   for (int i = 2; i < getNum(); i++) {
237     clang_analyzer_numTimesReached(); // expected-warning {{10}}
238   }
239   return 0;
240 }
241 
242 int nested_inlined_unroll1() {
243   int k;
244   for (int i = 0; i < 9; i++) {
245     clang_analyzer_numTimesReached(); // expected-warning {{9}}
246     k = simple_known_bound_loop();    // no reevaluation without inlining
247   }
248   int a = 22 / k; // expected-warning {{Division by zero}}
249   return 0;
250 }
251 
252 int nested_inlined_no_unroll1() {
253   int k;
254   for (int i = 0; i < 9; i++) {
255     clang_analyzer_numTimesReached(); // expected-warning {{15}}
256     k = simple_unknown_bound_loop();  // reevaluation without inlining, splits the state as well
257   }
258   int a = 22 / k; // no-warning
259   return 0;
260 }
261 
262 int recursion_unroll1(bool b) {
263   int k = 2;
264   for (int i = 0; i < 5; i++) {
265     clang_analyzer_numTimesReached(); // expected-warning {{13}}
266     if(i == 0 && b) // Splits the state in the first iteration but the recursion
267                     // call will be unrolled anyway since the condition is known there.
268       recursion_unroll1(false);
269     clang_analyzer_numTimesReached(); // expected-warning {{14}}
270   }
271   int a = 22 / k; // no-warning
272   return 0;
273 }
274 
275 int recursion_unroll2(bool b) {
276   int k = 0;
277   for (int i = 0; i < 5; i++) {
278     clang_analyzer_numTimesReached(); // expected-warning {{9}}
279     if(i == 0 && b)
280       recursion_unroll2(false);
281     clang_analyzer_numTimesReached(); // expected-warning {{9}}
282   }
283   int a = 22 / k; // expected-warning {{Division by zero}}
284   return 0;
285 }
286 
287 int recursion_unroll3(bool b) {
288   int k = 2;
289   for (int i = 0; i < 5; i++) {
290     clang_analyzer_numTimesReached(); // expected-warning {{10}}
291     if (i == 4 && b) {
292       recursion_unroll3(false);
293       break;
294     }
295     clang_analyzer_numTimesReached(); // expected-warning {{10}}
296   }
297   int a = 22 / k;
298   return 0;
299 }
300 
301 int recursion_unroll4(bool b) {
302   int k = 2;
303   for (int i = 0; i < 5; i++) {
304     clang_analyzer_numTimesReached(); // expected-warning {{13}}
305     if(i == 0 && b) {
306       recursion_unroll4(false);
307       continue;
308     }
309     clang_analyzer_numTimesReached(); // expected-warning {{13}}
310   }
311   int a = 22 / k;
312   return 0;
313 }
314 
315 int loop_exit_while_empty_loop_stack() {
316   if (getNum())
317     for (int i = 1; i < 8; i++)
318       ;
319   return 0;
320 }
321 
322 int num_steps_on_limit() {
323   for (int i = 0; i < 128; i++) {
324     clang_analyzer_numTimesReached(); // expected-warning {{128}}
325   }
326   clang_analyzer_numTimesReached(); // expected-warning {{1}}
327   return 0;
328 }
329 
330 int num_steps_over_limit1() {
331   for (int i = 0; i < 129; i++) {
332     clang_analyzer_numTimesReached(); // expected-warning {{4}}
333   }
334   return 0;
335 }
336 
337 int num_steps_on_limit2() {
338   for (int i = 0; i < 2; i++) {
339     for (int j = 0; j < 64; j++) {
340       clang_analyzer_numTimesReached(); // expected-warning {{128}}
341     }
342   }
343   return 0;
344 }
345 
346 int num_steps_over_limit2() {
347   for (int i = 0; i < 2; i++) {
348     clang_analyzer_numTimesReached(); // expected-warning {{1}}
349     for (int j = 0; j <= 64; j++) {
350       clang_analyzer_numTimesReached(); // expected-warning {{4}}
351     }
352   }
353   return 0;
354 }
355 
356 int num_steps_on_limit3() {
357   for (int i = 0; i < getNum(); i++) {
358     clang_analyzer_numTimesReached(); // expected-warning {{4}}
359     for (int j = 0; j < 32; j++) {
360       clang_analyzer_numTimesReached(); // expected-warning {{128}}
361     }
362   }
363   return 0;
364 }
365 
366 int num_steps_over_limit3() {
367   for (int i = 0; i < getNum(); i++) {
368     clang_analyzer_numTimesReached(); // expected-warning {{1}}
369     for (int j = 0; j < 33; j++) {
370       clang_analyzer_numTimesReached(); // expected-warning {{4}}
371     }
372   }
373   return 0;
374 }
375 
376