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