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