]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/ctor.mm
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
[FreeBSD/FreeBSD.git] / test / Analysis / ctor.mm
1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
2
3 #include "Inputs/system-header-simulator-cxx.h"
4
5 void clang_analyzer_eval(bool);
6 void clang_analyzer_checkInlined(bool);
7
8 // A simplified version of std::move.
9 template <typename T>
10 T &&move(T &obj) {
11   return static_cast<T &&>(obj);
12 }
13
14
15 struct Wrapper {
16   __strong id obj;
17 };
18
19 void test() {
20   Wrapper w;
21   // force a diagnostic
22   *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
23 }
24
25
26 struct IntWrapper {
27   int x;
28 };
29
30 void testCopyConstructor() {
31   IntWrapper a;
32   a.x = 42;
33
34   IntWrapper b(a);
35   clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
36 }
37
38 struct NonPODIntWrapper {
39   int x;
40
41   virtual int get();
42 };
43
44 void testNonPODCopyConstructor() {
45   NonPODIntWrapper a;
46   a.x = 42;
47
48   NonPODIntWrapper b(a);
49   clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
50 }
51
52
53 namespace ConstructorVirtualCalls {
54   class A {
55   public:
56     int *out1, *out2, *out3;
57
58     virtual int get() { return 1; }
59
60     A(int *out1) {
61       *out1 = get();
62     }
63   };
64
65   class B : public A {
66   public:
67     virtual int get() { return 2; }
68
69     B(int *out1, int *out2) : A(out1) {
70       *out2 = get();
71     }
72   };
73
74   class C : public B {
75   public:
76     virtual int get() { return 3; }
77
78     C(int *out1, int *out2, int *out3) : B(out1, out2) {
79       *out3 = get();
80     }
81   };
82
83   void test() {
84     int a, b, c;
85
86     C obj(&a, &b, &c);
87     clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
88     clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
89     clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
90
91     clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
92
93     // Sanity check for devirtualization.
94     A *base = &obj;
95     clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
96   }
97 }
98
99 namespace TemporaryConstructor {
100   class BoolWrapper {
101   public:
102     BoolWrapper() {
103       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104       value = true;
105     }
106     bool value;
107   };
108
109   void test() {
110     // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
111     if (BoolWrapper().value)
112       return;
113   }
114 }
115
116
117 namespace ConstructorUsedAsRValue {
118   using TemporaryConstructor::BoolWrapper;
119
120   bool extractValue(BoolWrapper b) {
121     return b.value;
122   }
123
124   void test() {
125     bool result = extractValue(BoolWrapper());
126     clang_analyzer_eval(result); // expected-warning{{TRUE}}
127   }
128 }
129
130 namespace PODUninitialized {
131   class POD {
132   public:
133     int x, y;
134   };
135
136   class PODWrapper {
137   public:
138     POD p;
139   };
140
141   class NonPOD {
142   public:
143     int x, y;
144
145     NonPOD() {}
146     NonPOD(const NonPOD &Other)
147       : x(Other.x), y(Other.y) // expected-warning {{undefined}}
148     {
149     }
150     NonPOD(NonPOD &&Other)
151     : x(Other.x), y(Other.y) // expected-warning {{undefined}}
152     {
153     }
154
155     NonPOD &operator=(const NonPOD &Other)
156     {
157       x = Other.x;
158       y = Other.y; // expected-warning {{undefined}}
159       return *this;
160     }
161     NonPOD &operator=(NonPOD &&Other)
162     {
163       x = Other.x;
164       y = Other.y; // expected-warning {{undefined}}
165       return *this;
166     }
167   };
168
169   class NonPODWrapper {
170   public:
171     class Inner {
172     public:
173       int x, y;
174
175       Inner() {}
176       Inner(const Inner &Other)
177         : x(Other.x), y(Other.y) // expected-warning {{undefined}}
178       {
179       }
180       Inner(Inner &&Other)
181       : x(Other.x), y(Other.y) // expected-warning {{undefined}}
182       {
183       }
184
185       Inner &operator=(const Inner &Other)
186       {
187         x = Other.x; // expected-warning {{undefined}}
188         y = Other.y;
189         return *this;
190       }
191       Inner &operator=(Inner &&Other)
192       {
193         x = Other.x; // expected-warning {{undefined}}
194         y = Other.y;
195         return *this;
196       }
197     };
198
199     Inner p;
200   };
201
202   void testPOD() {
203     POD p;
204     p.x = 1;
205     POD p2 = p; // no-warning
206     clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
207     POD p3 = move(p); // no-warning
208     clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
209
210     // Use rvalues as well.
211     clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
212
213     PODWrapper w;
214     w.p.y = 1;
215     PODWrapper w2 = w; // no-warning
216     clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
217     PODWrapper w3 = move(w); // no-warning
218     clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
219
220     // Use rvalues as well.
221     clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
222   }
223
224   void testNonPOD() {
225     NonPOD p;
226     p.x = 1;
227     NonPOD p2 = p;
228   }
229
230   void testNonPODMove() {
231     NonPOD p;
232     p.x = 1;
233     NonPOD p2 = move(p);
234   }
235
236   void testNonPODWrapper() {
237     NonPODWrapper w;
238     w.p.y = 1;
239     NonPODWrapper w2 = w;
240   }
241
242   void testNonPODWrapperMove() {
243     NonPODWrapper w;
244     w.p.y = 1;
245     NonPODWrapper w2 = move(w);
246   }
247
248   // Not strictly about constructors, but trivial assignment operators should
249   // essentially work the same way.
250   namespace AssignmentOperator {
251     void testPOD() {
252       POD p;
253       p.x = 1;
254       POD p2;
255       p2 = p; // no-warning
256       clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
257       POD p3;
258       p3 = move(p); // no-warning
259       clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
260
261       PODWrapper w;
262       w.p.y = 1;
263       PODWrapper w2;
264       w2 = w; // no-warning
265       clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
266       PODWrapper w3;
267       w3 = move(w); // no-warning
268       clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
269     }
270
271     void testReturnValue() {
272       POD p;
273       p.x = 1;
274       POD p2;
275       clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
276
277       PODWrapper w;
278       w.p.y = 1;
279       PODWrapper w2;
280       clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
281     }
282
283     void testNonPOD() {
284       NonPOD p;
285       p.x = 1;
286       NonPOD p2;
287       p2 = p;
288     }
289
290     void testNonPODMove() {
291       NonPOD p;
292       p.x = 1;
293       NonPOD p2;
294       p2 = move(p);
295     }
296
297     void testNonPODWrapper() {
298       NonPODWrapper w;
299       w.p.y = 1;
300       NonPODWrapper w2;
301       w2 = w;
302     }
303
304     void testNonPODWrapperMove() {
305       NonPODWrapper w;
306       w.p.y = 1;
307       NonPODWrapper w2;
308       w2 = move(w);
309     }
310   }
311 }
312
313 namespace ArrayMembers {
314   struct Primitive {
315     int values[3];
316   };
317
318   void testPrimitive() {
319     Primitive a = { { 1, 2, 3 } };
320
321     clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
322     clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
323     clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
324
325     Primitive b = a;
326
327     clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
328     clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
329     clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
330
331     Primitive c;
332     c = b;
333
334     clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
335     clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
336     clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
337   }
338
339   struct NestedPrimitive {
340     int values[2][3];
341   };
342
343   void testNestedPrimitive() {
344     NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
345
346     clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
347     clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
348     clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
349
350     NestedPrimitive b = a;
351
352     clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
353     clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
354     clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
355
356     NestedPrimitive c;
357     c = b;
358
359     clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
360     clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
361     clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
362   }
363
364   struct POD {
365     IntWrapper values[3];
366   };
367
368   void testPOD() {
369     POD a = { { { 1 }, { 2 }, { 3 } } };
370
371     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
372     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
373     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
374
375     POD b = a;
376
377     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
378     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
379     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
380
381     POD c;
382     c = b;
383
384     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
385     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
386     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
387   }
388
389   struct NestedPOD {
390     IntWrapper values[2][3];
391   };
392
393   void testNestedPOD() {
394     NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
395
396     clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
397     clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
398     clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
399
400     NestedPOD b = a;
401
402     clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
403     clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
404     clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
405
406     NestedPOD c;
407     c = b;
408
409     clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
410     clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
411     clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
412   }
413
414   struct NonPOD {
415     NonPODIntWrapper values[3];
416   };
417
418   void testNonPOD() {
419     NonPOD a;
420     a.values[0].x = 1;
421     a.values[1].x = 2;
422     a.values[2].x = 3;
423
424     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
425     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
426     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
427
428     NonPOD b = a;
429
430     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
431     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
432     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
433
434     NonPOD c;
435     c = b;
436
437     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
438     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
439     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
440   }
441
442   struct NestedNonPOD {
443     NonPODIntWrapper values[2][3];
444   };
445
446   void testNestedNonPOD() {
447     NestedNonPOD a;
448     a.values[0][0].x = 0;
449     a.values[0][1].x = 0;
450     a.values[0][2].x = 0;
451     a.values[1][0].x = 1;
452     a.values[1][1].x = 2;
453     a.values[1][2].x = 3;
454
455     clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
456     clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
457     clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
458
459     NestedNonPOD b = a;
460
461     clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
462     clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
463     clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
464
465     NestedNonPOD c;
466     c = b;
467
468     clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
469     clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
470     clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
471   }
472   
473   struct NonPODDefaulted {
474     NonPODIntWrapper values[3];
475
476     NonPODDefaulted() = default;
477     NonPODDefaulted(const NonPODDefaulted &) = default;
478     NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
479   };
480
481   void testNonPODDefaulted() {
482     NonPODDefaulted a;
483     a.values[0].x = 1;
484     a.values[1].x = 2;
485     a.values[2].x = 3;
486
487     clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
488     clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
489     clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
490
491     NonPODDefaulted b = a;
492
493     clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
494     clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
495     clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
496
497     NonPODDefaulted c;
498     c = b;
499
500     clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
501     clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
502     clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
503   }
504 };
505
506 namespace VirtualInheritance {
507   int counter;
508
509   struct base {
510     base() {
511       ++counter;
512     }
513   };
514
515   struct virtual_subclass : public virtual base {
516     virtual_subclass() {}
517   };
518
519   struct double_subclass : public virtual_subclass {
520     double_subclass() {}
521   };
522
523   void test() {
524     counter = 0;
525     double_subclass obj;
526     clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
527   }
528
529   struct double_virtual_subclass : public virtual virtual_subclass {
530     double_virtual_subclass() {}
531   };
532
533   void testVirtual() {
534     counter = 0;
535     double_virtual_subclass obj;
536     clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
537   }
538 }
539
540 namespace ZeroInitialization {
541   struct raw_pair {
542     int p1;
543     int p2;
544   };
545
546   void testVarDecl() {
547     raw_pair p{};
548     clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
549     clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
550   }
551
552   void testTemporary() {
553     clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
554     clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
555   }
556
557   void testArray() {
558     raw_pair p[2] = {};
559     clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
560     clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
561     clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
562     clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
563   }
564
565   void testNew() {
566     // FIXME: Pending proper implementation of constructors for 'new'.
567     raw_pair *pp = new raw_pair();
568     clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}}
569     clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}}
570   }
571
572   void testArrayNew() {
573     // FIXME: Pending proper implementation of constructors for 'new[]'.
574     raw_pair *p = new raw_pair[2]();
575     clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}}
576     clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}}
577     clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}}
578     clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}}
579   }
580
581   struct initializing_pair {
582   public:
583     int x;
584     raw_pair y;
585     initializing_pair() : x(), y() {}
586   };
587   
588   void testFieldInitializers() {
589     initializing_pair p;
590     clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
591     clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
592     clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
593   }
594
595   struct subclass : public raw_pair {
596     subclass() = default;
597   };
598
599   void testSubclass() {
600     subclass p;
601     clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
602   }
603
604   struct initializing_subclass : public raw_pair {
605     initializing_subclass() : raw_pair() {}
606   };
607
608   void testInitializingSubclass() {
609     initializing_subclass p;
610     clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
611     clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
612   }
613
614   struct pair_wrapper {
615     pair_wrapper() : p() {}
616     raw_pair p;
617   };
618
619   struct virtual_subclass : public virtual pair_wrapper {
620     virtual_subclass() {}
621   };
622
623   struct double_virtual_subclass : public virtual_subclass {
624     double_virtual_subclass() {
625       // This previously caused a crash because the pair_wrapper subobject was
626       // initialized twice.
627     }
628   };
629
630   class Empty {
631   public:
632     Empty();
633   };
634
635   class PairContainer : public Empty {
636     raw_pair p;
637   public:
638     PairContainer() : Empty(), p() {
639       // This previously caused a crash because the empty base class looked
640       // like an initialization of 'p'.
641     }
642     PairContainer(int) : Empty(), p() {
643       // Test inlining something else here.
644     }
645   };
646
647   class PairContainerContainer {
648     int padding;
649     PairContainer pc;
650   public:
651     PairContainerContainer() : pc(1) {}
652   };
653 }
654
655 namespace InitializerList {
656   struct List {
657     bool usedInitializerList;
658
659     List() : usedInitializerList(false) {}
660     List(std::initializer_list<int>) : usedInitializerList(true) {}
661   };
662
663   void testStatic() {
664     List defaultCtor;
665     clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
666
667     List list{1, 2};
668     clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
669   }
670
671   void testDynamic() {
672     List *list = new List{1, 2};
673     // FIXME: When we handle constructors with 'new', this will be TRUE.
674     clang_analyzer_eval(list->usedInitializerList); // expected-warning{{UNKNOWN}}
675   }
676 }