xref: /aosp_15_r20/external/clang/test/Analysis/loop-widening.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-max-loop 4 -analyzer-config widen-loops=true -verify %s
2*67e74705SXin Li 
3*67e74705SXin Li void clang_analyzer_eval(int);
4*67e74705SXin Li void clang_analyzer_warnIfReached();
5*67e74705SXin Li 
6*67e74705SXin Li typedef __typeof(sizeof(int)) size_t;
7*67e74705SXin Li void *malloc(size_t);
8*67e74705SXin Li void free(void *);
9*67e74705SXin Li 
loop_which_iterates_limit_times_not_widened()10*67e74705SXin Li void loop_which_iterates_limit_times_not_widened() {
11*67e74705SXin Li   int i;
12*67e74705SXin Li   int x = 1;
13*67e74705SXin Li   // Check loop isn't widened by checking x isn't invalidated
14*67e74705SXin Li   for (i = 0; i < 1; ++i) {}
15*67e74705SXin Li   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
16*67e74705SXin Li   for (i = 0; i < 2; ++i) {}
17*67e74705SXin Li   clang_analyzer_eval(x == 1); // expected-warning {{TRUE}}
18*67e74705SXin Li   for (i = 0; i < 3; ++i) {}
19*67e74705SXin Li   // FIXME loss of precision as a result of evaluating the widened loop body
20*67e74705SXin Li   //       *instead* of the last iteration.
21*67e74705SXin Li   clang_analyzer_eval(x == 1); // expected-warning {{UNKNOWN}}
22*67e74705SXin Li }
23*67e74705SXin Li 
24*67e74705SXin Li int a_global;
25*67e74705SXin Li 
loop_evaluated_before_widening()26*67e74705SXin Li void loop_evaluated_before_widening() {
27*67e74705SXin Li   int i;
28*67e74705SXin Li   a_global = 1;
29*67e74705SXin Li   for (i = 0; i < 10; ++i) {
30*67e74705SXin Li     if (i == 2) {
31*67e74705SXin Li       // True before widening then unknown after.
32*67e74705SXin Li       clang_analyzer_eval(a_global == 1); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}}
33*67e74705SXin Li     }
34*67e74705SXin Li   }
35*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
36*67e74705SXin Li }
37*67e74705SXin Li 
warnings_after_loop()38*67e74705SXin Li void warnings_after_loop() {
39*67e74705SXin Li   int i;
40*67e74705SXin Li   for (i = 0; i < 10; ++i) {}
41*67e74705SXin Li   char *m = (char*)malloc(12);
42*67e74705SXin Li } // expected-warning {{Potential leak of memory pointed to by 'm'}}
43*67e74705SXin Li 
for_loop_exits()44*67e74705SXin Li void for_loop_exits() {
45*67e74705SXin Li   int i;
46*67e74705SXin Li   for (i = 0; i < 10; ++i) {}
47*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
48*67e74705SXin Li }
49*67e74705SXin Li 
while_loop_exits()50*67e74705SXin Li void while_loop_exits() {
51*67e74705SXin Li   int i = 0;
52*67e74705SXin Li   while (i < 10) {++i;}
53*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
54*67e74705SXin Li }
55*67e74705SXin Li 
do_while_loop_exits()56*67e74705SXin Li void do_while_loop_exits() {
57*67e74705SXin Li   int i = 0;
58*67e74705SXin Li   do {++i;} while (i < 10);
59*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
60*67e74705SXin Li }
61*67e74705SXin Li 
loop_body_is_widened()62*67e74705SXin Li void loop_body_is_widened() {
63*67e74705SXin Li   int i = 0;
64*67e74705SXin Li   while (i < 100) {
65*67e74705SXin Li     if (i > 10) {
66*67e74705SXin Li       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
67*67e74705SXin Li     }
68*67e74705SXin Li     ++i;
69*67e74705SXin Li   }
70*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
71*67e74705SXin Li }
72*67e74705SXin Li 
invariably_infinite_loop()73*67e74705SXin Li void invariably_infinite_loop() {
74*67e74705SXin Li   int i = 0;
75*67e74705SXin Li   while (1) { ++i; }
76*67e74705SXin Li   clang_analyzer_warnIfReached(); // no-warning
77*67e74705SXin Li }
78*67e74705SXin Li 
invariably_infinite_break_loop()79*67e74705SXin Li void invariably_infinite_break_loop() {
80*67e74705SXin Li   int i = 0;
81*67e74705SXin Li   while (1) {
82*67e74705SXin Li     ++i;
83*67e74705SXin Li     int x = 1;
84*67e74705SXin Li     if (!x) break;
85*67e74705SXin Li   }
86*67e74705SXin Li   clang_analyzer_warnIfReached(); // no-warning
87*67e74705SXin Li }
88*67e74705SXin Li 
reachable_break_loop()89*67e74705SXin Li void reachable_break_loop() {
90*67e74705SXin Li   int i = 0;
91*67e74705SXin Li   while (1) {
92*67e74705SXin Li     ++i;
93*67e74705SXin Li     if (i == 100) break;
94*67e74705SXin Li   }
95*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
96*67e74705SXin Li }
97*67e74705SXin Li 
condition_constrained_true_in_loop()98*67e74705SXin Li void condition_constrained_true_in_loop() {
99*67e74705SXin Li   int i = 0;
100*67e74705SXin Li   while (i < 50) {
101*67e74705SXin Li     clang_analyzer_eval(i < 50); // expected-warning {{TRUE}}
102*67e74705SXin Li     ++i;
103*67e74705SXin Li   }
104*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
105*67e74705SXin Li }
106*67e74705SXin Li 
condition_constrained_false_after_loop()107*67e74705SXin Li void condition_constrained_false_after_loop() {
108*67e74705SXin Li   int i = 0;
109*67e74705SXin Li   while (i < 50) {
110*67e74705SXin Li     ++i;
111*67e74705SXin Li   }
112*67e74705SXin Li   clang_analyzer_eval(i >= 50); // expected-warning {{TRUE}}
113*67e74705SXin Li   clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
114*67e74705SXin Li }
115*67e74705SXin Li 
multiple_exit_test()116*67e74705SXin Li void multiple_exit_test() {
117*67e74705SXin Li   int x = 0;
118*67e74705SXin Li   int i = 0;
119*67e74705SXin Li   while (i < 50) {
120*67e74705SXin Li     if (x) {
121*67e74705SXin Li       i = 10;
122*67e74705SXin Li       break;
123*67e74705SXin Li     }
124*67e74705SXin Li     ++i;
125*67e74705SXin Li   }
126*67e74705SXin Li   // Reachable by 'normal' exit
127*67e74705SXin Li   if (i == 50) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
128*67e74705SXin Li   // Reachable by break point
129*67e74705SXin Li   if (i == 10) clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
130*67e74705SXin Li   // Not reachable
131*67e74705SXin Li   if (i < 10) clang_analyzer_warnIfReached(); // no-warning
132*67e74705SXin Li   if (i > 10 && i < 50) clang_analyzer_warnIfReached(); // no-warning
133*67e74705SXin Li }
134*67e74705SXin Li 
pointer_doesnt_leak_from_loop()135*67e74705SXin Li void pointer_doesnt_leak_from_loop() {
136*67e74705SXin Li   int *h_ptr = (int *) malloc(sizeof(int));
137*67e74705SXin Li   for (int i = 0; i < 2; ++i) {}
138*67e74705SXin Li   for (int i = 0; i < 10; ++i) {} // no-warning
139*67e74705SXin Li   free(h_ptr);
140*67e74705SXin Li }
141*67e74705SXin Li 
142*67e74705SXin Li int g_global;
143*67e74705SXin Li 
unknown_after_loop(int s_arg)144*67e74705SXin Li void unknown_after_loop(int s_arg) {
145*67e74705SXin Li   g_global = 0;
146*67e74705SXin Li   s_arg = 1;
147*67e74705SXin Li   int s_local = 2;
148*67e74705SXin Li   int *h_ptr = malloc(sizeof(int));
149*67e74705SXin Li 
150*67e74705SXin Li   for (int i = 0; i < 10; ++i) {}
151*67e74705SXin Li 
152*67e74705SXin Li   clang_analyzer_eval(g_global); // expected-warning {{UNKNOWN}}
153*67e74705SXin Li   clang_analyzer_eval(s_arg); // expected-warning {{UNKNOWN}}
154*67e74705SXin Li   clang_analyzer_eval(s_local); // expected-warning {{UNKNOWN}}
155*67e74705SXin Li   clang_analyzer_eval(h_ptr == 0); // expected-warning {{UNKNOWN}}
156*67e74705SXin Li   free(h_ptr);
157*67e74705SXin Li }
158*67e74705SXin Li 
variable_bound_exiting_loops_widened(int x)159*67e74705SXin Li void variable_bound_exiting_loops_widened(int x) {
160*67e74705SXin Li   int i = 0;
161*67e74705SXin Li   int t = 1;
162*67e74705SXin Li   while (i < x) {
163*67e74705SXin Li     ++i;
164*67e74705SXin Li   }
165*67e74705SXin Li   clang_analyzer_eval(t == 1); // expected-warning {{TRUE}} // expected-warning {{UNKNOWN}}
166*67e74705SXin Li }
167*67e74705SXin Li 
nested_loop_outer_widen()168*67e74705SXin Li void nested_loop_outer_widen() {
169*67e74705SXin Li   int i = 0, j = 0;
170*67e74705SXin Li   for (i = 0; i < 10; i++) {
171*67e74705SXin Li     clang_analyzer_eval(i < 10); // expected-warning {{TRUE}}
172*67e74705SXin Li     for (j = 0; j < 2; j++) {
173*67e74705SXin Li       clang_analyzer_eval(j < 2); // expected-warning {{TRUE}}
174*67e74705SXin Li     }
175*67e74705SXin Li     clang_analyzer_eval(j >= 2); // expected-warning {{TRUE}}
176*67e74705SXin Li   }
177*67e74705SXin Li   clang_analyzer_eval(i >= 10); // expected-warning {{TRUE}}
178*67e74705SXin Li }
179*67e74705SXin Li 
nested_loop_inner_widen()180*67e74705SXin Li void nested_loop_inner_widen() {
181*67e74705SXin Li   int i = 0, j = 0;
182*67e74705SXin Li   for (i = 0; i < 2; i++) {
183*67e74705SXin Li     clang_analyzer_eval(i < 2); // expected-warning {{TRUE}}
184*67e74705SXin Li     for (j = 0; j < 10; j++) {
185*67e74705SXin Li       clang_analyzer_eval(j < 10); // expected-warning {{TRUE}}
186*67e74705SXin Li     }
187*67e74705SXin Li     clang_analyzer_eval(j >= 10); // expected-warning {{TRUE}}
188*67e74705SXin Li   }
189*67e74705SXin Li   clang_analyzer_eval(i >= 2); // expected-warning {{TRUE}}
190*67e74705SXin Li }
191