File: track-control-dependency-conditions.cpp

package info (click to toggle)
llvm-toolchain-9 1%3A9.0.1-16
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 882,436 kB
  • sloc: cpp: 4,167,636; ansic: 714,256; asm: 457,610; python: 155,927; objc: 65,094; sh: 42,856; lisp: 26,908; perl: 7,786; pascal: 7,722; makefile: 6,881; ml: 5,581; awk: 3,648; cs: 2,027; xml: 888; javascript: 381; ruby: 156
file content (316 lines) | stat: -rw-r--r-- 10,590 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
// RUN: %clang_analyze_cc1 %s \
// RUN:   -verify=expected,tracking \
// RUN:   -analyzer-config track-conditions=true \
// RUN:   -analyzer-output=text \
// RUN:   -analyzer-checker=core

// RUN: not %clang_analyze_cc1 -verify %s \
// RUN:   -analyzer-checker=core \
// RUN:   -analyzer-config track-conditions-debug=true \
// RUN:   2>&1 | FileCheck %s -check-prefix=CHECK-INVALID-DEBUG

// CHECK-INVALID-DEBUG: (frontend): invalid input for analyzer-config option
// CHECK-INVALID-DEBUG-SAME:        'track-conditions-debug', that expects
// CHECK-INVALID-DEBUG-SAME:        'track-conditions' to also be enabled
//
// RUN: %clang_analyze_cc1 %s \
// RUN:   -verify=expected,tracking,debug \
// RUN:   -analyzer-config track-conditions=true \
// RUN:   -analyzer-config track-conditions-debug=true \
// RUN:   -analyzer-output=text \
// RUN:   -analyzer-checker=core

// RUN: %clang_analyze_cc1 %s -verify \
// RUN:   -analyzer-output=text \
// RUN:   -analyzer-checker=core

namespace example_1 {
int flag;
bool coin();

void foo() {
  flag = coin(); // tracking-note{{Value assigned to 'flag'}}
}

void test() {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
  flag = 1;

  foo(); // TODO: Add nodes here about flag's value being invalidated.
  if (flag) // expected-note   {{Assuming 'flag' is 0}}
            // expected-note@-1{{Taking false branch}}
    x = new int;

  foo(); // tracking-note{{Calling 'foo'}}
         // tracking-note@-1{{Returning from 'foo'}}

  if (flag) // expected-note   {{Assuming 'flag' is not equal to 0}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}

    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace example_1

namespace example_2 {
int flag;
bool coin();

void foo() {
  flag = coin(); // tracking-note{{Value assigned to 'flag'}}
}

void test() {
  int *x = 0;
  flag = 1;

  foo();
  if (flag) // expected-note   {{Assuming 'flag' is 0}}
            // expected-note@-1{{Taking false branch}}
    x = new int;

  x = 0; // expected-note{{Null pointer value stored to 'x'}}

  foo(); // tracking-note{{Calling 'foo'}}
         // tracking-note@-1{{Returning from 'foo'}}

  if (flag) // expected-note   {{Assuming 'flag' is not equal to 0}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}

    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace example_2

namespace global_variable_invalidation {
int flag;
bool coin();

void foo() {
  // coin() could write bar, do it's invalidated.
  flag = coin(); // tracking-note{{Value assigned to 'flag'}}
                 // tracking-note@-1{{Value assigned to 'bar'}}
}

int bar;

void test() {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
  flag = 1;

  foo(); // tracking-note{{Calling 'foo'}}
         // tracking-note@-1{{Returning from 'foo'}}

  if (bar) // expected-note   {{Assuming 'bar' is not equal to 0}}
           // expected-note@-1{{Taking true branch}}
           // debug-note@-2{{Tracking condition 'bar'}}
    if (flag) // expected-note   {{Assuming 'flag' is not equal to 0}}
              // expected-note@-1{{Taking true branch}}
              // debug-note@-2{{Tracking condition 'flag'}}

      *x = 5; // expected-warning{{Dereference of null pointer}}
              // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace global_variable_invalidation

namespace variable_declaration_in_condition {
bool coin();

bool foo() {
  return coin(); // tracking-note{{Returning value}}
}

int bar;

void test() {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}

  if (int flag = foo()) // tracking-note{{Calling 'foo'}}
                        // tracking-note@-1{{Returning from 'foo'}}
                        // tracking-note@-2{{'flag' initialized here}}
                        // debug-note@-3{{Tracking condition 'flag'}}
                        // expected-note@-4{{Assuming 'flag' is not equal to 0}}
                        // expected-note@-5{{Taking true branch}}

    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace variable_declaration_in_condition

namespace conversion_to_bool {
bool coin();

struct ConvertsToBool {
  operator bool() const { return coin(); } // tracking-note{{Returning value}}
};

void test() {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}

  if (ConvertsToBool())
    // tracking-note@-1 {{Calling 'ConvertsToBool::operator bool'}}
    // tracking-note@-2{{Returning from 'ConvertsToBool::operator bool'}}
    // debug-note@-3{{Tracking condition 'ConvertsToBool()'}}
    // expected-note@-4{{Assuming the condition is true}}
    // expected-note@-5{{Taking true branch}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}

} // end of namespace variable_declaration_in_condition

namespace unimportant_returning_value_note {
bool coin();

bool flipCoin() { return coin(); } // tracking-note{{Returning value}}

void i(int *ptr) {
  if (ptr) // expected-note{{Assuming 'ptr' is null}}
           // expected-note@-1{{Taking false branch}}
    ;
  if (!flipCoin())
    // tracking-note@-1{{Calling 'flipCoin'}}
    // tracking-note@-2{{Returning from 'flipCoin'}}
    // debug-note@-3{{Tracking condition '!flipCoin()'}}
    // expected-note@-4{{Assuming the condition is true}}
    // expected-note@-5{{Taking true branch}}
    *ptr = 5; // expected-warning{{Dereference of null pointer}}
              // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace unimportant_returning_value_note

namespace important_returning_value_note {
bool coin();

bool flipCoin() {
  if (coin()) // tracking-note{{Assuming the condition is false}}
              // tracking-note@-1{{Taking false branch}}
              // debug-note@-2{{Tracking condition 'coin()'}}
    return true;
  return coin(); // tracking-note{{Returning value}}
}

void i(int *ptr) {
  if (ptr) // expected-note{{Assuming 'ptr' is null}}
           // expected-note@-1{{Taking false branch}}
    ;
  if (!flipCoin())
    // tracking-note@-1{{Calling 'flipCoin'}}
    // tracking-note@-2{{Returning from 'flipCoin'}}
    // debug-note@-3{{Tracking condition '!flipCoin()'}}
    // expected-note@-4{{Assuming the condition is true}}
    // expected-note@-5{{Taking true branch}}
    *ptr = 5; // expected-warning{{Dereference of null pointer}}
              // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace important_returning_value_note

namespace tracked_condition_is_only_initialized {
int getInt();

void f() {
  int flag = getInt(); // tracking-note{{'flag' initialized here}}
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
  if (flag) // expected-note{{Assuming 'flag' is not equal to 0}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace tracked_condition_is_only_initialized

namespace tracked_condition_written_in_same_stackframe {
int flag;
int getInt();

void f(int y) {
  y = 1; // tracking-note{{The value 1 is assigned to 'y'}}
  flag = y; // tracking-note{{The value 1 is assigned to 'flag'}}

  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}
  if (flag) // expected-note{{'flag' is 1}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace tracked_condition_written_in_same_stackframe

namespace tracked_condition_written_in_nested_stackframe {
int flag;
int getInt();

void foo() {
  int y;
  y = 1; // tracking-note{{The value 1 is assigned to 'y'}}
  flag = y; // tracking-note{{The value 1 is assigned to 'flag'}}

}

void f(int y) {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}

  foo(); // tracking-note{{Calling 'foo'}}
         // tracking-note@-1{{Returning from 'foo'}}

  if (flag) // expected-note{{'flag' is 1}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}
} // end of namespace tracked_condition_written_in_nested_stackframe

namespace collapse_point_not_in_condition {

[[noreturn]] void halt();

void assert(int b) {
  if (!b) // tracking-note{{Assuming 'b' is not equal to 0}}
          // tracking-note@-1{{Taking false branch}}
    halt();
}

void f(int flag) {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}

  assert(flag); // tracking-note{{Calling 'assert'}}
                // tracking-note@-1{{Returning from 'assert'}}

  if (flag) // expected-note{{'flag' is not equal to 0}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}

} // end of namespace collapse_point_not_in_condition

namespace unimportant_write_before_collapse_point {

[[noreturn]] void halt();

void assert(int b) {
  if (!b) // tracking-note{{Assuming 'b' is not equal to 0}}
          // tracking-note@-1{{Taking false branch}}
    halt();
}
int getInt();

void f(int flag) {
  int *x = 0; // expected-note{{'x' initialized to a null pointer value}}

  flag = getInt(); // tracking-note{{Value assigned to 'flag'}}
  assert(flag); // tracking-note{{Calling 'assert'}}
                // tracking-note@-1{{Returning from 'assert'}}

  if (flag) // expected-note{{'flag' is not equal to 0}}
            // expected-note@-1{{Taking true branch}}
            // debug-note@-2{{Tracking condition 'flag'}}
    *x = 5; // expected-warning{{Dereference of null pointer}}
            // expected-note@-1{{Dereference of null pointer}}
}

} // end of namespace unimportant_write_before_collapse_point