Clang Project

clang_source_code/test/Analysis/cfg.cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=debug.DumpCFG -triple x86_64-apple-darwin12 -fheinous-gnu-extensions -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 -fheinous-gnu-extensions -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
26void 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
73void 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
88// CHECK-LABEL: void checkGCCAsmRValueOutput()
89// CHECK: [B2 (ENTRY)]
90// CHECK-NEXT: Succs (1): B1
91// CHECK: [B1]
92// CHECK-NEXT:   1: int arg
93// CHECK-NEXT:   2: arg
94// CHECK-NEXT:   3: (int)[B1.2] (CStyleCastExpr, NoOp, int)
95// CHECK-NEXT:   4: asm ("" : "=r" ([B1.3]));
96// CHECK-NEXT:   5: arg
97// CHECK-NEXT:   6: asm ("" : "=r" ([B1.5]));
98void checkGCCAsmRValueOutput() {
99  int arg;
100  __asm__("" : "=r"((int)arg));  // rvalue output operand
101  __asm__("" : "=r"(arg));       // lvalue output operand
102}
103
104
105// CHECK-LABEL: void F(EmptyE e)
106// CHECK: ENTRY
107// CHECK-NEXT: Succs (1): B1
108// CHECK: [B1]
109// CHECK-NEXT:   1: e
110// CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, LValueToRValue, enum EmptyE)
111// CHECK-NEXT:   3: [B1.2] (ImplicitCastExpr, IntegralCast, int)
112// CHECK-NEXT:   T: switch [B1.3]
113// CHECK-NEXT:   Preds (1): B2
114// CHECK-NEXT:   Succs (1): B0
115// CHECK: [B0 (EXIT)]
116// CHECK-NEXT:   Preds (1): B1
117enum EmptyE {};
118void F(EmptyE e) {
119  switch (e) {}
120}
121
122// CHECK-LABEL: void testBuiltinSize()
123// CHECK: ENTRY
124// CHECK-NEXT: Succs (1): B1
125// CHECK: [B1]
126// CHECK-NEXT:   1: __builtin_object_size
127// CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, BuiltinFnToFnPtr, unsigned long (*)(const void *, int) noexcept)
128// CHECK-NEXT:   3: [B1.2](dummy(), 0)
129// CHECK-NEXT:   4: (void)[B1.3] (CStyleCastExpr, ToVoid, void)
130// CHECK-NEXT:   Preds (1): B2
131// CHECK-NEXT:   Succs (1): B0
132// CHECK: [B0 (EXIT)]
133// CHECK-NEXT:   Preds (1): B1
134void testBuiltinSize() {
135  extern int *dummy();
136  (void)__builtin_object_size(dummy(), 0);
137}
138
139
140class A {
141public:
142  A() {}
143  ~A() {}
144};
145
146// CHECK-LABEL: void test_deletedtor()
147// CHECK: [B2 (ENTRY)]
148// CHECK-NEXT:   Succs (1): B1
149// CHECK: [B1]
150// CHECK-NEXT:   1:  CFGNewAllocator(A *)
151// WARNINGS-NEXT:   2:  (CXXConstructExpr, class A)
152// ANALYZER-NEXT:   2:  (CXXConstructExpr, [B1.3], class A)
153// CHECK-NEXT:   3: new A([B1.2])
154// CHECK-NEXT:   4: A *a = new A();
155// CHECK-NEXT:   5: a
156// CHECK-NEXT:   6: [B1.5] (ImplicitCastExpr, LValueToRValue, class A *)
157// CHECK-NEXT:   7: [B1.6]->~A() (Implicit destructor)
158// CHECK-NEXT:   8: delete [B1.6]
159// CHECK-NEXT:   Preds (1): B2
160// CHECK-NEXT:   Succs (1): B0
161// CHECK: [B0 (EXIT)]
162// CHECK-NEXT:   Preds (1): B1
163void test_deletedtor() {
164  A *a = new A();
165  delete a;
166}
167
168// CHECK-LABEL: void test_deleteArraydtor()
169// CHECK: [B2 (ENTRY)]
170// CHECK-NEXT:   Succs (1): B1
171// CHECK: [B1]
172// CHECK-NEXT:   1: 5
173// CHECK-NEXT:   2: CFGNewAllocator(A *)
174// WARNINGS-NEXT:   3:  (CXXConstructExpr, class A [5])
175// ANALYZER-NEXT:   3:  (CXXConstructExpr, [B1.4], class A [5])
176// CHECK-NEXT:   4: new A {{\[\[}}B1.1]]
177// CHECK-NEXT:   5: A *a = new A [5];
178// CHECK-NEXT:   6: a
179// CHECK-NEXT:   7: [B1.6] (ImplicitCastExpr, LValueToRValue, class A *)
180// CHECK-NEXT:   8: [B1.7]->~A() (Implicit destructor)
181// CHECK-NEXT:   9: delete [] [B1.7]
182// CHECK-NEXT:   Preds (1): B2
183// CHECK-NEXT:   Succs (1): B0
184// CHECK: [B0 (EXIT)]
185// CHECK-NEXT:   Preds (1): B1
186void test_deleteArraydtor() {
187  A *a = new A[5];
188  delete[] a;
189}
190
191
192namespace NoReturnSingleSuccessor {
193  struct A {
194    A();
195    ~A();
196  };
197
198  struct B : public A {
199    B();
200    ~B() __attribute__((noreturn));
201  };
202
203// CHECK-LABEL: int test1(int *x)
204// CHECK: 1: 1
205// CHECK-NEXT: 2: return
206// CHECK-NEXT: ~B() (Implicit destructor)
207// CHECK-NEXT: Preds (1)
208// CHECK-NEXT: Succs (1): B0
209  int test1(int *x) {
210    B b;
211    if (x)
212      return 1;
213  }
214
215// CHECK-LABEL: int test2(int *x)
216// CHECK: 1: 1
217// CHECK-NEXT: 2: return
218// CHECK-NEXT: destructor
219// CHECK-NEXT: Preds (1)
220// CHECK-NEXT: Succs (1): B0
221  int test2(int *x) {
222    const A& a = B();
223    if (x)
224      return 1;
225  }
226}
227
228// Test CFG support for "extending" an enum.
229// CHECK-LABEL: int test_enum_with_extension(enum MyEnum value)
230// CHECK:  [B7 (ENTRY)]
231// CHECK-NEXT:    Succs (1): B2
232// CHECK:  [B1]
233// CHECK-NEXT:    1: x
234// CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
235// CHECK-NEXT:    3: return [B1.2];
236// CHECK-NEXT:    Preds (5): B3 B4 B5 B6 B2(Unreachable)
237// CHECK-NEXT:    Succs (1): B0
238// CHECK:  [B2]
239// CHECK-NEXT:    1: 0
240// CHECK-NEXT:    2: int x = 0;
241// CHECK-NEXT:    3: value
242// CHECK-NEXT:    4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum)
243// CHECK-NEXT:    5: [B2.4] (ImplicitCastExpr, IntegralCast, int)
244// CHECK-NEXT:    T: switch [B2.5]
245// CHECK-NEXT:    Preds (1): B7
246// CHECK-NEXT:    Succs (5): B3 B4 B5 B6 B1(Unreachable)
247// CHECK:  [B3]
248// CHECK-NEXT:   case D:
249// CHECK-NEXT:    1: 4
250// CHECK-NEXT:    2: x
251// CHECK-NEXT:    3: [B3.2] = [B3.1]
252// CHECK-NEXT:    T: break;
253// CHECK-NEXT:    Preds (1): B2
254// CHECK-NEXT:    Succs (1): B1
255// CHECK:  [B4]
256// CHECK-NEXT:   case C:
257// CHECK-NEXT:    1: 3
258// CHECK-NEXT:    2: x
259// CHECK-NEXT:    3: [B4.2] = [B4.1]
260// CHECK-NEXT:    T: break;
261// CHECK-NEXT:    Preds (1): B2
262// CHECK-NEXT:    Succs (1): B1
263// CHECK:  [B5]
264// CHECK-NEXT:   case B:
265// CHECK-NEXT:    1: 2
266// CHECK-NEXT:    2: x
267// CHECK-NEXT:    3: [B5.2] = [B5.1]
268// CHECK-NEXT:    T: break;
269// CHECK-NEXT:    Preds (1): B2
270// CHECK-NEXT:    Succs (1): B1
271// CHECK:  [B6]
272// CHECK-NEXT:   case A:
273// CHECK-NEXT:    1: 1
274// CHECK-NEXT:    2: x
275// CHECK-NEXT:    3: [B6.2] = [B6.1]
276// CHECK-NEXT:    T: break;
277// CHECK-NEXT:    Preds (1): B2
278// CHECK-NEXT:    Succs (1): B1
279// CHECK:  [B0 (EXIT)]
280// CHECK-NEXT:    Preds (1): B1
281enum MyEnum { A, B, C };
282static const enum MyEnum D = (enum MyEnum) 32;
283
284int test_enum_with_extension(enum MyEnum value) {
285  int x = 0;
286  switch (value) {
287    case A: x = 1; break;
288    case B: x = 2; break;
289    case C: x = 3; break;
290    case D: x = 4; break;
291  }
292  return x;
293}
294
295// CHECK-LABEL: int test_enum_with_extension_default(enum MyEnum value)
296// CHECK:  [B7 (ENTRY)]
297// CHECK-NEXT:    Succs (1): B2
298// CHECK:  [B1]
299// CHECK-NEXT:    1: x
300// CHECK-NEXT:    2: [B1.1] (ImplicitCastExpr, LValueToRValue, int)
301// CHECK-NEXT:    3: return [B1.2];
302// CHECK-NEXT:    Preds (4): B3 B4 B5 B6
303// CHECK-NEXT:    Succs (1): B0
304// CHECK:  [B2]
305// CHECK-NEXT:    1: 0
306// CHECK-NEXT:    2: int x = 0;
307// CHECK-NEXT:    3: value
308// CHECK-NEXT:    4: [B2.3] (ImplicitCastExpr, LValueToRValue, enum MyEnum)
309// CHECK-NEXT:    5: [B2.4] (ImplicitCastExpr, IntegralCast, int)
310// CHECK-NEXT:    T: switch [B2.5]
311// CHECK-NEXT:    Preds (1): B7
312// CHECK-NEXT:    Succs (4): B4 B5 B6 B3(Unreachable)
313// CHECK:  [B3]
314// CHECK-NEXT:   default:
315// CHECK-NEXT:    1: 4
316// CHECK-NEXT:    2: x
317// CHECK-NEXT:    3: [B3.2] = [B3.1]
318// CHECK-NEXT:    T: break;
319// CHECK-NEXT:    Preds (1): B2(Unreachable)
320// CHECK-NEXT:    Succs (1): B1
321// CHECK:  [B4]
322// CHECK-NEXT:   case C:
323// CHECK-NEXT:    1: 3
324// CHECK-NEXT:    2: x
325// CHECK-NEXT:    3: [B4.2] = [B4.1]
326// CHECK-NEXT:    T: break;
327// CHECK-NEXT:    Preds (1): B2
328// CHECK-NEXT:    Succs (1): B1
329// CHECK:  [B5]
330// CHECK-NEXT:   case B:
331// CHECK-NEXT:    1: 2
332// CHECK-NEXT:    2: x
333// CHECK-NEXT:    3: [B5.2] = [B5.1]
334// CHECK-NEXT:    T: break;
335// CHECK-NEXT:    Preds (1): B2
336// CHECK-NEXT:    Succs (1): B1
337// CHECK:  [B6]
338// CHECK-NEXT:   case A:
339// CHECK-NEXT:    1: 1
340// CHECK-NEXT:    2: x
341// CHECK-NEXT:    3: [B6.2] = [B6.1]
342// CHECK-NEXT:    T: break;
343// CHECK-NEXT:    Preds (1): B2
344// CHECK-NEXT:    Succs (1): B1
345// CHECK:  [B0 (EXIT)]
346// CHECK-NEXT:    Preds (1): B1
347int test_enum_with_extension_default(enum MyEnum value) {
348  int x = 0;
349  switch (value) {
350    case A: x = 1; break;
351    case B: x = 2; break;
352    case C: x = 3; break;
353    default: x = 4; break;
354  }
355  return x;
356}
357
358
359// CHECK-LABEL: void test_placement_new()
360// CHECK:  [B2 (ENTRY)]
361// CHECK-NEXT:  Succs (1): B1
362// CHECK:  [B1]
363// CHECK-NEXT:  1: int buffer[16];
364// CHECK-NEXT:  2: buffer
365// CHECK-NEXT:  3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *)
366// CHECK-NEXT:  4: [B1.3] (ImplicitCastExpr, BitCast, void *)
367// CHECK-NEXT:  5: CFGNewAllocator(MyClass *)
368// WARNINGS-NEXT:  6:  (CXXConstructExpr, class MyClass)
369// ANALYZER-NEXT:  6:  (CXXConstructExpr, [B1.7], class MyClass)
370// CHECK-NEXT:  7: new ([B1.4]) MyClass([B1.6])
371// CHECK-NEXT:  8: MyClass *obj = new (buffer) MyClass();
372// CHECK-NEXT:  Preds (1): B2
373// CHECK-NEXT:  Succs (1): B0
374// CHECK: [B0 (EXIT)]
375// CHECK-NEXT:  Preds (1): B1
376
377extern void* operator new (unsigned long sz, void* v);
378extern void* operator new[] (unsigned long sz, void* ptr);
379
380class MyClass {
381public:
382  MyClass() {}
383  ~MyClass() {}
384};
385
386void test_placement_new() {
387  int buffer[16];
388  MyClass* obj = new (buffer) MyClass();
389}
390
391// CHECK-LABEL: void test_placement_new_array()
392// CHECK:  [B2 (ENTRY)]
393// CHECK-NEXT:  Succs (1): B1
394// CHECK: [B1]
395// CHECK-NEXT:  1: int buffer[16];
396// CHECK-NEXT:  2: buffer
397// CHECK-NEXT:  3: [B1.2] (ImplicitCastExpr, ArrayToPointerDecay, int *)
398// CHECK-NEXT:  4: [B1.3] (ImplicitCastExpr, BitCast, void *)
399// CHECK-NEXT:  5: 5
400// CHECK-NEXT:  6: CFGNewAllocator(MyClass *)
401// WARNINGS-NEXT:  7:  (CXXConstructExpr, class MyClass [5])
402// ANALYZER-NEXT:  7:  (CXXConstructExpr, [B1.8], class MyClass [5])
403// CHECK-NEXT:  8: new ([B1.4]) MyClass {{\[\[}}B1.5]]
404// CHECK-NEXT:  9: MyClass *obj = new (buffer) MyClass [5];
405// CHECK-NEXT:  Preds (1): B2
406// CHECK-NEXT:  Succs (1): B0
407// CHECK: [B0 (EXIT)]
408// CHECK-NEXT:  Preds (1): B1
409
410void test_placement_new_array() {
411  int buffer[16];
412  MyClass* obj = new (buffer) MyClass[5];
413}
414
415
416// CHECK-LABEL: void test_lifetime_extended_temporaries()
417// CHECK: [B1]
418struct LifetimeExtend { LifetimeExtend(int); ~LifetimeExtend(); };
419struct Aggregate { const LifetimeExtend a; const LifetimeExtend b; };
420struct AggregateRef { const LifetimeExtend &a; const LifetimeExtend &b; };
421void test_lifetime_extended_temporaries() {
422  // CHECK: LifetimeExtend(1);
423  // CHECK-NEXT: : 1
424  // CHECK-NEXT: ~LifetimeExtend()
425  // CHECK-NOT: ~LifetimeExtend()
426  {
427    const LifetimeExtend &l = LifetimeExtend(1);
428    1;
429  }
430  // CHECK: LifetimeExtend(2)
431  // CHECK-NEXT: ~LifetimeExtend()
432  // CHECK-NEXT: : 2
433  // CHECK-NOT: ~LifetimeExtend()
434  {
435    // No life-time extension.
436    const int &l = (LifetimeExtend(2), 2);
437    2;
438  }
439  // CHECK: LifetimeExtend(3)
440  // CHECK-NEXT: : 3
441  // CHECK-NEXT: ~LifetimeExtend()
442  // CHECK-NOT: ~LifetimeExtend()
443  {
444    // The last one is lifetime extended.
445    const LifetimeExtend &l = (3, LifetimeExtend(3));
446    3;
447  }
448  // CHECK: LifetimeExtend(4)
449  // CHECK-NEXT: ~LifetimeExtend()
450  // CHECK-NEXT: ~LifetimeExtend()
451  // CHECK-NEXT: : 4
452  // CHECK-NOT: ~LifetimeExtend()
453  {
454    Aggregate a{LifetimeExtend(4), LifetimeExtend(4)};
455    4;
456  }
457  // CHECK: LifetimeExtend(5)
458  // CHECK-NEXT: : 5
459  // FIXME: We want to emit the destructors of the lifetime
460  // extended variables here.
461  // CHECK-NOT: ~LifetimeExtend()
462  {
463    AggregateRef a{LifetimeExtend(5), LifetimeExtend(5)};
464    5;
465  }
466  // FIXME: Add tests for lifetime extension via subobject
467  // references (LifetimeExtend().some_member).
468}
469
470
471// FIXME: The destructor for 'a' shouldn't be there because it's deleted
472// in the union.
473// CHECK-LABEL: void foo()
474// CHECK:  [B2 (ENTRY)]
475// CHECK-NEXT:    Succs (1): B1
476// CHECK:  [B1]
477// WARNINGS-NEXT:    1:  (CXXConstructExpr, struct pr37688_deleted_union_destructor::A)
478// ANALYZER-NEXT:    1:  (CXXConstructExpr, [B1.2], struct pr37688_deleted_union_destructor::A)
479// CHECK-NEXT:    2: pr37688_deleted_union_destructor::A a;
480// CHECK-NEXT:    3: [B1.2].~A() (Implicit destructor)
481// CHECK-NEXT:    Preds (1): B2
482// CHECK-NEXT:    Succs (1): B0
483// CHECK:  [B0 (EXIT)]
484// CHECK-NEXT:    Preds (1): B1
485
486namespace pr37688_deleted_union_destructor {
487struct S { ~S(); };
488struct A {
489  ~A() noexcept {}
490  union {
491    struct {
492      S s;
493    } ss;
494  };
495};
496void foo() {
497  A a;
498}
499} // end namespace pr37688_deleted_union_destructor
500
501
502// CHECK-LABEL: template<> int *PR18472<int>()
503// CHECK: [B2 (ENTRY)]
504// CHECK-NEXT:   Succs (1): B1
505// CHECK: [B1]
506// CHECK-NEXT:   1: 0
507// CHECK-NEXT:   2: [B1.1] (ImplicitCastExpr, NullToPointer, PR18472_t)
508// CHECK-NEXT:   3: (PR18472_t)[B1.2] (CStyleCastExpr, NoOp, PR18472_t)
509// CHECK-NEXT:   4: CFGNewAllocator(int *)
510// CHECK-NEXT:   5: new (([B1.3])) int
511// CHECK-NEXT:   6: return [B1.5];
512// CHECK-NEXT:   Preds (1): B2
513// CHECK-NEXT:   Succs (1): B0
514// CHECK: [B0 (EXIT)]
515// CHECK-NEXT:   Preds (1): B1
516
517extern "C" typedef int *PR18472_t;
518void *operator new (unsigned long, PR18472_t);
519template <class T> T *PR18472() {
520  return new (((PR18472_t) 0)) T;
521}
522void PR18472_helper() {
523  PR18472<int>();
524}
525
526