1 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=false %s > %t 2>&1
2 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,WARNINGS %s
3 // RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -analyzer-config cfg-temporary-dtors=true -std=c++11 -analyzer-config cfg-rich-constructors=true %s > %t 2>&1
4 // RUN: FileCheck --input-file=%t -check-prefixes=CHECK,ANALYZER %s
5 
6 // This file tests how we construct two different flavors of the Clang CFG -
7 // the CFG used by the Sema analysis-based warnings and the CFG used by the
8 // static analyzer. The difference in the behavior is checked via FileCheck
9 // prefixes (WARNINGS and ANALYZER respectively). When introducing new analyzer
10 // flags, no new run lines should be added - just these flags would go to the
11 // respective line depending on where is it turned on and where is it turned
12 // off. Feel free to add tests that test only one of the CFG flavors if you're
13 // not sure how the other flavor is supposed to work in your case.
14 
15 // CHECK-LABEL: void checkWrap(int i)
16 // CHECK: ENTRY
17 // CHECK-NEXT: Succs (1): B1
18 // CHECK: [B1]
19 // CHECK: Succs (21): B2 B3 B4 B5 B6 B7 B8 B9
20 // CHECK: B10 B11 B12 B13 B14 B15 B16 B17 B18 B19
21 // CHECK: B20 B21 B0
22 // CHECK: [B0 (EXIT)]
23 // CHECK-NEXT: Preds (21): B2 B3 B4 B5 B6 B7 B8 B9
24 // CHECK-NEXT: B10 B11 B12 B13 B14 B15 B16 B17 B18 B19
25 // CHECK-NEXT: B20 B21 B1
26 void checkWrap(int i) {
27   switch(i) {
28     case 0: break;
29     case 1: break;
30     case 2: break;
31     case 3: break;
32     case 4: break;
33     case 5: break;
34     case 6: break;
35     case 7: break;
36     case 8: break;
37     case 9: break;
38     case 10: break;
39     case 11: break;
40     case 12: break;
41     case 13: break;
42     case 14: break;
43     case 15: break;
44     case 16: break;
45     case 17: break;
46     case 18: break;
47     case 19: break;
48   }
49 }
50 
51 // CHECK-LABEL: void checkDeclStmts()
52 // CHECK: ENTRY
53 // CHECK-NEXT: Succs (1): B1
54 // CHECK: [B1]
55 // CHECK-NEXT:   1: int i;
56 // CHECK-NEXT:   2: int j;
57 // CHECK-NEXT:   3: 1
58 // CHECK-NEXT:   4: int k = 1;
59 // CHECK-NEXT:   5: int l;
60 // CHECK-NEXT:   6: 2
61 // CHECK-NEXT:   7: int m = 2;
62 // WARNINGS-NEXT: (CXXConstructExpr, struct standalone)
63 // ANALYZER-NEXT: (CXXConstructExpr, [B1.9], struct standalone)
64 // CHECK-NEXT:   9: struct standalone myStandalone;
65 // WARNINGS-NEXT: (CXXConstructExpr, struct (anonymous struct at {{.*}}))
66 // ANALYZER-NEXT: (CXXConstructExpr, [B1.11], struct (anonymous struct at {{.*}}))
67 // CHECK-NEXT:  11: struct (anonymous struct at {{.*}}) myAnon;
68 // WARNINGS-NEXT: (CXXConstructExpr, struct named)
69 // ANALYZER-NEXT: (CXXConstructExpr, [B1.13], struct named)
70 // CHECK-NEXT:  13: struct named myNamed;
71 // CHECK-NEXT:   Preds (1): B2
72 // CHECK-NEXT:   Succs (1): B0
73 void checkDeclStmts() {
74   int i, j;
75   int k = 1, l, m = 2;
76 
77   struct standalone { int x, y; };
78   struct standalone myStandalone;
79 
80   struct { int x, y; } myAnon;
81 
82   struct named { int x, y; } myNamed;
83 
84   static_assert(1, "abc");
85 }
86 
87 // CHECK-LABEL: void F(EmptyE e)
88 // CHECK: ENTRY
89 // CHECK-NEXT: Succs (1): B1
90 // CHECK: [B1]
91 // CHECK-NEXT:   1: e
92 // CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, LValueToRValue, enum EmptyE)
93 // CHECK-NEXT:   3: [B1.2] (ImplicitCastExpr, IntegralCast, int)
94 // CHECK-NEXT:   T: switch [B1.3]
95 // CHECK-NEXT:   Preds (1): B2
96 // CHECK-NEXT:   Succs (1): B0
97 // CHECK: [B0 (EXIT)]
98 // CHECK-NEXT:   Preds (1): B1
99 enum EmptyE {};
100 void F(EmptyE e) {
101   switch (e) {}
102 }
103 
104 // CHECK-LABEL: void testBuiltinSize()
105 // CHECK: ENTRY
106 // CHECK-NEXT: Succs (1): B1
107 // CHECK: [B1]
108 // CHECK-NEXT:   1: __builtin_object_size
109 // CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int) noexcept)
110 // CHECK-NEXT:   3: [B1.2](dummy(), 0)
111 // CHECK-NEXT:   4: (void)[B1.3] (CStyleCastExpr, ToVoid, void)
112 // CHECK-NEXT:   Preds (1): B2
113 // CHECK-NEXT:   Succs (1): B0
114 // CHECK: [B0 (EXIT)]
115 // CHECK-NEXT:   Preds (1): B1
116 void testBuiltinSize() {
117   extern int *dummy();
118   (void)__builtin_object_size(dummy(), 0);
119 }
120 
121 
122 class A {
123 public:
124   A() {}
125   ~A() {}
126 };
127 
128 // CHECK-LABEL: void test_deletedtor()
129 // CHECK: [B2 (ENTRY)]
130 // CHECK-NEXT:   Succs (1): B1
131 // CHECK: [B1]
132 // CHECK-NEXT:   1:  CFGNewAllocator(A *)
133 // WARNINGS-NEXT:   2:  (CXXConstructExpr, class A)
134 // ANALYZER-NEXT:   2:  (CXXConstructExpr, [B1.3], class A)
135 // CHECK-NEXT:   3: new A([B1.2])
136 // CHECK-NEXT:   4: A *a = new A();
137 // CHECK-NEXT:   5: a
138 // CHECK-NEXT:   6: [B1.5] (ImplicitCastExpr, LValueToRValue, class A *)
139 // CHECK-NEXT:   7: [B1.6]->~A() (Implicit destructor)
140 // CHECK-NEXT:   8: delete [B1.6]
141 // CHECK-NEXT:   Preds (1): B2
142 // CHECK-NEXT:   Succs (1): B0
143 // CHECK: [B0 (EXIT)]
144 // CHECK-NEXT:   Preds (1): B1
145 void test_deletedtor() {
146   A *a = new A();
147   delete a;
148 }
149 
150 // CHECK-LABEL: void test_deleteArraydtor()
151 // CHECK: [B2 (ENTRY)]
152 // CHECK-NEXT:   Succs (1): B1
153 // CHECK: [B1]
154 // CHECK-NEXT:   1: 5
155 // CHECK-NEXT:   2: CFGNewAllocator(A *)
156 // WARNINGS-NEXT:   3:  (CXXConstructExpr, class A [5])
157 // ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], class A [5])
158 // CHECK-NEXT:   4: new A {{\[\[}}B1.1]]
159 // CHECK-NEXT:   5: A *a = new A [5];
160 // CHECK-NEXT:   6: a
161 // CHECK-NEXT:   7: [B1.6] (ImplicitCastExpr, LValueToRValue, class A *)
162 // CHECK-NEXT:   8: [B1.7]->~A() (Implicit destructor)
163 // CHECK-NEXT:   9: delete [] [B1.7]
164 // CHECK-NEXT:   Preds (1): B2
165 // CHECK-NEXT:   Succs (1): B0
166 // CHECK: [B0 (EXIT)]
167 // CHECK-NEXT:   Preds (1): B1
168 void test_deleteArraydtor() {
169   A *a = new A[5];
170   delete[] a;
171 }
172 
173 
174 namespace NoReturnSingleSuccessor {
175   struct A {
176     A();
177     ~A();
178   };
179 
180   struct B : public A {
181     B();
182     ~B() __attribute__((noreturn));
183   };
184 
185 // CHECK-LABEL: int test1(int *x)
186 // CHECK: 1: 1
187 // CHECK-NEXT: 2: return
188 // CHECK-NEXT: ~B() (Implicit destructor)
189 // CHECK-NEXT: Preds (1)
190 // CHECK-NEXT: Succs (1): B0
191   int test1(int *x) {
192     B b;
193     if (x)
194       return 1;
195   }
196 
197 // CHECK-LABEL: int test2(int *x)
198 // CHECK: 1: 1
199 // CHECK-NEXT: 2: return
200 // CHECK-NEXT: destructor
201 // CHECK-NEXT: Preds (1)
202 // CHECK-NEXT: Succs (1): B0
203   int test2(int *x) {
204     const A& a = B();
205     if (x)
206       return 1;
207   }
208 }
209 
210 // Test CFG support for "extending" an enum.
211 // CHECK-LABEL: int test_enum_with_extension(enum MyEnum value)
212 // CHECK:  [B7 (ENTRY)]
213 // CHECK-NEXT:    Succs (1): B2
214 // CHECK:  [B1]
215 // CHECK-NEXT:    1: x
216 // CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
217 // CHECK-NEXT:    3: return [B1.2];
218 // CHECK-NEXT:    Preds (5): B3 B4 B5 B6 B2(Unreachable)
219 // CHECK-NEXT:    Succs (1): B0
220 // CHECK:  [B2]
221 // CHECK-NEXT:    1: 0
222 // CHECK-NEXT:    2: int x = 0;
223 // CHECK-NEXT:    3: value
224 // CHECK-NEXT:    4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum)
225 // CHECK-NEXT:    5: [B2.4] (ImplicitCastExpr, IntegralCast, int)
226 // CHECK-NEXT:    T: switch [B2.5]
227 // CHECK-NEXT:    Preds (1): B7
228 // CHECK-NEXT:    Succs (5): B3 B4 B5 B6 B1(Unreachable)
229 // CHECK:  [B3]
230 // CHECK-NEXT:   case D:
231 // CHECK-NEXT:    1: 4
232 // CHECK-NEXT:    2: x
233 // CHECK-NEXT:    3: [B3.2] = [B3.1]
234 // CHECK-NEXT:    T: break;
235 // CHECK-NEXT:    Preds (1): B2
236 // CHECK-NEXT:    Succs (1): B1
237 // CHECK:  [B4]
238 // CHECK-NEXT:   case C:
239 // CHECK-NEXT:    1: 3
240 // CHECK-NEXT:    2: x
241 // CHECK-NEXT:    3: [B4.2] = [B4.1]
242 // CHECK-NEXT:    T: break;
243 // CHECK-NEXT:    Preds (1): B2
244 // CHECK-NEXT:    Succs (1): B1
245 // CHECK:  [B5]
246 // CHECK-NEXT:   case B:
247 // CHECK-NEXT:    1: 2
248 // CHECK-NEXT:    2: x
249 // CHECK-NEXT:    3: [B5.2] = [B5.1]
250 // CHECK-NEXT:    T: break;
251 // CHECK-NEXT:    Preds (1): B2
252 // CHECK-NEXT:    Succs (1): B1
253 // CHECK:  [B6]
254 // CHECK-NEXT:   case A:
255 // CHECK-NEXT:    1: 1
256 // CHECK-NEXT:    2: x
257 // CHECK-NEXT:    3: [B6.2] = [B6.1]
258 // CHECK-NEXT:    T: break;
259 // CHECK-NEXT:    Preds (1): B2
260 // CHECK-NEXT:    Succs (1): B1
261 // CHECK:  [B0 (EXIT)]
262 // CHECK-NEXT:    Preds (1): B1
263 enum MyEnum { A, B, C };
264 static const enum MyEnum D = (enum MyEnum) 32;
265 
266 int test_enum_with_extension(enum MyEnum value) {
267   int x = 0;
268   switch (value) {
269     case A: x = 1; break;
270     case B: x = 2; break;
271     case C: x = 3; break;
272     case D: x = 4; break;
273   }
274   return x;
275 }
276 
277 // CHECK-LABEL: int test_enum_with_extension_default(enum MyEnum value)
278 // CHECK:  [B7 (ENTRY)]
279 // CHECK-NEXT:    Succs (1): B2
280 // CHECK:  [B1]
281 // CHECK-NEXT:    1: x
282 // CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
283 // CHECK-NEXT:    3: return [B1.2];
284 // CHECK-NEXT:    Preds (4): B3 B4 B5 B6
285 // CHECK-NEXT:    Succs (1): B0
286 // CHECK:  [B2]
287 // CHECK-NEXT:    1: 0
288 // CHECK-NEXT:    2: int x = 0;
289 // CHECK-NEXT:    3: value
290 // CHECK-NEXT:    4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum)
291 // CHECK-NEXT:    5: [B2.4] (ImplicitCastExpr, IntegralCast, int)
292 // CHECK-NEXT:    T: switch [B2.5]
293 // CHECK-NEXT:    Preds (1): B7
294 // CHECK-NEXT:    Succs (4): B4 B5 B6 B3(Unreachable)
295 // CHECK:  [B3]
296 // CHECK-NEXT:   default:
297 // CHECK-NEXT:    1: 4
298 // CHECK-NEXT:    2: x
299 // CHECK-NEXT:    3: [B3.2] = [B3.1]
300 // CHECK-NEXT:    T: break;
301 // CHECK-NEXT:    Preds (1): B2(Unreachable)
302 // CHECK-NEXT:    Succs (1): B1
303 // CHECK:  [B4]
304 // CHECK-NEXT:   case C:
305 // CHECK-NEXT:    1: 3
306 // CHECK-NEXT:    2: x
307 // CHECK-NEXT:    3: [B4.2] = [B4.1]
308 // CHECK-NEXT:    T: break;
309 // CHECK-NEXT:    Preds (1): B2
310 // CHECK-NEXT:    Succs (1): B1
311 // CHECK:  [B5]
312 // CHECK-NEXT:   case B:
313 // CHECK-NEXT:    1: 2
314 // CHECK-NEXT:    2: x
315 // CHECK-NEXT:    3: [B5.2] = [B5.1]
316 // CHECK-NEXT:    T: break;
317 // CHECK-NEXT:    Preds (1): B2
318 // CHECK-NEXT:    Succs (1): B1
319 // CHECK:  [B6]
320 // CHECK-NEXT:   case A:
321 // CHECK-NEXT:    1: 1
322 // CHECK-NEXT:    2: x
323 // CHECK-NEXT:    3: [B6.2] = [B6.1]
324 // CHECK-NEXT:    T: break;
325 // CHECK-NEXT:    Preds (1): B2
326 // CHECK-NEXT:    Succs (1): B1
327 // CHECK:  [B0 (EXIT)]
328 // CHECK-NEXT:    Preds (1): B1
329 int test_enum_with_extension_default(enum MyEnum value) {
330   int x = 0;
331   switch (value) {
332     case A: x = 1; break;
333     case B: x = 2; break;
334     case C: x = 3; break;
335     default: x = 4; break;
336   }
337   return x;
338 }
339 
340 
341 // CHECK-LABEL: void test_placement_new()
342 // CHECK:  [B2 (ENTRY)]
343 // CHECK-NEXT:  Succs (1): B1
344 // CHECK:  [B1]
345 // CHECK-NEXT:  1: int buffer[16];
346 // CHECK-NEXT:  2: buffer
347 // CHECK-NEXT:  3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *)
348 // CHECK-NEXT:  4: [B1.3] (ImplicitCastExpr, BitCast, void *)
349 // CHECK-NEXT:  5: CFGNewAllocator(MyClass *)
350 // WARNINGS-NEXT:  6:  (CXXConstructExpr, class MyClass)
351 // ANALYZER-NEXT:  6:  (CXXConstructExpr, [B1.7], class MyClass)
352 // CHECK-NEXT:  7: new ([B1.4]) MyClass([B1.6])
353 // CHECK-NEXT:  8: MyClass *obj = new (buffer) MyClass();
354 // CHECK-NEXT:  Preds (1): B2
355 // CHECK-NEXT:  Succs (1): B0
356 // CHECK: [B0 (EXIT)]
357 // CHECK-NEXT:  Preds (1): B1
358 
359 extern void* operator new (unsigned long sz, void* v);
360 extern void* operator new[] (unsigned long sz, void* ptr);
361 
362 class MyClass {
363 public:
364   MyClass() {}
365   ~MyClass() {}
366 };
367 
368 void test_placement_new() {
369   int buffer[16];
370   MyClass* obj = new (buffer) MyClass();
371 }
372 
373 // CHECK-LABEL: void test_placement_new_array()
374 // CHECK:  [B2 (ENTRY)]
375 // CHECK-NEXT:  Succs (1): B1
376 // CHECK: [B1]
377 // CHECK-NEXT:  1: int buffer[16];
378 // CHECK-NEXT:  2: buffer
379 // CHECK-NEXT:  3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *)
380 // CHECK-NEXT:  4: [B1.3] (ImplicitCastExpr, BitCast, void *)
381 // CHECK-NEXT:  5: 5
382 // CHECK-NEXT:  6: CFGNewAllocator(MyClass *)
383 // WARNINGS-NEXT:  7:  (CXXConstructExpr, class MyClass [5])
384 // ANALYZER-NEXT:  7:  (CXXConstructExpr, [B1.8], class MyClass [5])
385 // CHECK-NEXT:  8: new ([B1.4]) MyClass {{\[\[}}B1.5]]
386 // CHECK-NEXT:  9: MyClass *obj = new (buffer) MyClass [5];
387 // CHECK-NEXT:  Preds (1): B2
388 // CHECK-NEXT:  Succs (1): B0
389 // CHECK: [B0 (EXIT)]
390 // CHECK-NEXT:  Preds (1): B1
391 
392 void test_placement_new_array() {
393   int buffer[16];
394   MyClass* obj = new (buffer) MyClass[5];
395 }
396 
397 
398 // CHECK-LABEL: void test_lifetime_extended_temporaries()
399 // CHECK: [B1]
400 struct LifetimeExtend { LifetimeExtend(int); ~LifetimeExtend(); };
401 struct Aggregate { const LifetimeExtend a; const LifetimeExtend b; };
402 struct AggregateRef { const LifetimeExtend &a; const LifetimeExtend &b; };
403 void test_lifetime_extended_temporaries() {
404   // CHECK: LifetimeExtend(1);
405   // CHECK-NEXT: : 1
406   // CHECK-NEXT: ~LifetimeExtend()
407   // CHECK-NOT: ~LifetimeExtend()
408   {
409     const LifetimeExtend &l = LifetimeExtend(1);
410     1;
411   }
412   // CHECK: LifetimeExtend(2)
413   // CHECK-NEXT: ~LifetimeExtend()
414   // CHECK-NEXT: : 2
415   // CHECK-NOT: ~LifetimeExtend()
416   {
417     // No life-time extension.
418     const int &l = (LifetimeExtend(2), 2);
419     2;
420   }
421   // CHECK: LifetimeExtend(3)
422   // CHECK-NEXT: : 3
423   // CHECK-NEXT: ~LifetimeExtend()
424   // CHECK-NOT: ~LifetimeExtend()
425   {
426     // The last one is lifetime extended.
427     const LifetimeExtend &l = (3, LifetimeExtend(3));
428     3;
429   }
430   // CHECK: LifetimeExtend(4)
431   // CHECK-NEXT: ~LifetimeExtend()
432   // CHECK-NEXT: ~LifetimeExtend()
433   // CHECK-NEXT: : 4
434   // CHECK-NOT: ~LifetimeExtend()
435   {
436     Aggregate a{LifetimeExtend(4), LifetimeExtend(4)};
437     4;
438   }
439   // CHECK: LifetimeExtend(5)
440   // CHECK-NEXT: : 5
441   // FIXME: We want to emit the destructors of the lifetime
442   // extended variables here.
443   // CHECK-NOT: ~LifetimeExtend()
444   {
445     AggregateRef a{LifetimeExtend(5), LifetimeExtend(5)};
446     5;
447   }
448   // FIXME: Add tests for lifetime extension via subobject
449   // references (LifetimeExtend().some_member).
450 }
451 
452 
453 // CHECK-LABEL: template<> int *PR18472<int>()
454 // CHECK: [B2 (ENTRY)]
455 // CHECK-NEXT:   Succs (1): B1
456 // CHECK: [B1]
457 // CHECK-NEXT:   1: 0
458 // CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, NullToPointer, PR18472_t)
459 // CHECK-NEXT:   3: (PR18472_t)[B1.2] (CStyleCastExpr, NoOp, PR18472_t)
460 // CHECK-NEXT:   4: CFGNewAllocator(int *)
461 // CHECK-NEXT:   5: new (([B1.3])) int
462 // CHECK-NEXT:   6: return [B1.5];
463 // CHECK-NEXT:   Preds (1): B2
464 // CHECK-NEXT:   Succs (1): B0
465 // CHECK: [B0 (EXIT)]
466 // CHECK-NEXT:   Preds (1): B1
467 
468 extern "C" typedef int *PR18472_t;
469 void *operator new (unsigned long, PR18472_t);
470 template <class T> T *PR18472() {
471   return new (((PR18472_t) 0)) T;
472 }
473 void PR18472_helper() {
474   PR18472<int>();
475 }
476 
477