blob: 1603ff3893449f2fee04f088d31428d4a747f0e6 [file] [log] [blame]
Jordan Rosebc403862013-02-15 00:32:15 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
Jordan Rosebf83e7c2012-08-03 23:08:36 +00002
3void clang_analyzer_eval(bool);
Jordan Rosede5277f2012-08-31 17:06:49 +00004void clang_analyzer_checkInlined(bool);
Jordan Rose1d3ca252012-07-26 20:04:30 +00005
Jordan Rosebc403862013-02-15 00:32:15 +00006// A simplified version of std::move.
7template <typename T>
8T &&move(T &obj) {
9 return static_cast<T &&>(obj);
10}
11
12
Jordan Rose1d3ca252012-07-26 20:04:30 +000013struct Wrapper {
14 __strong id obj;
15};
16
17void test() {
18 Wrapper w;
19 // force a diagnostic
20 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
21}
Jordan Rosebf83e7c2012-08-03 23:08:36 +000022
23
24struct IntWrapper {
25 int x;
26};
27
28void testCopyConstructor() {
29 IntWrapper a;
30 a.x = 42;
31
32 IntWrapper b(a);
33 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
34}
35
36struct NonPODIntWrapper {
37 int x;
38
39 virtual int get();
40};
41
42void testNonPODCopyConstructor() {
43 NonPODIntWrapper a;
44 a.x = 42;
45
46 NonPODIntWrapper b(a);
47 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
48}
49
Jordan Rose4e79fdf2012-08-15 20:07:17 +000050
51namespace ConstructorVirtualCalls {
52 class A {
53 public:
54 int *out1, *out2, *out3;
55
56 virtual int get() { return 1; }
57
58 A(int *out1) {
59 *out1 = get();
60 }
61 };
62
63 class B : public A {
64 public:
65 virtual int get() { return 2; }
66
67 B(int *out1, int *out2) : A(out1) {
68 *out2 = get();
69 }
70 };
71
72 class C : public B {
73 public:
74 virtual int get() { return 3; }
75
76 C(int *out1, int *out2, int *out3) : B(out1, out2) {
77 *out3 = get();
78 }
79 };
80
81 void test() {
82 int a, b, c;
83
84 C obj(&a, &b, &c);
85 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
86 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
87 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
88
89 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
90
91 // Sanity check for devirtualization.
92 A *base = &obj;
93 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
94 }
95}
96
Jordan Rosede5277f2012-08-31 17:06:49 +000097namespace TemporaryConstructor {
98 class BoolWrapper {
99 public:
100 BoolWrapper() {
101 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
102 value = true;
103 }
104 bool value;
105 };
Jordan Rose4e79fdf2012-08-15 20:07:17 +0000106
Jordan Rosede5277f2012-08-31 17:06:49 +0000107 void test() {
108 // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
109 if (BoolWrapper().value)
110 return;
111 }
112}
Jordan Rose0504a592012-10-01 17:51:35 +0000113
114
115namespace ConstructorUsedAsRValue {
116 using TemporaryConstructor::BoolWrapper;
117
118 bool extractValue(BoolWrapper b) {
119 return b.value;
120 }
121
122 void test() {
123 bool result = extractValue(BoolWrapper());
124 clang_analyzer_eval(result); // expected-warning{{TRUE}}
125 }
126}
Jordan Rosebc403862013-02-15 00:32:15 +0000127
128namespace PODUninitialized {
129 class POD {
130 public:
131 int x, y;
132 };
133
134 class PODWrapper {
135 public:
136 POD p;
137 };
138
139 class NonPOD {
140 public:
141 int x, y;
142
143 NonPOD() {}
144 NonPOD(const NonPOD &Other)
145 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
146 {
147 }
148 NonPOD(NonPOD &&Other)
149 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
150 {
151 }
152 };
153
154 class NonPODWrapper {
155 public:
156 class Inner {
157 public:
158 int x, y;
159
160 Inner() {}
161 Inner(const Inner &Other)
162 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
163 {
164 }
165 Inner(Inner &&Other)
166 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
167 {
168 }
169 };
170
171 Inner p;
172 };
173
174 void testPOD() {
175 POD p;
176 p.x = 1;
177 POD p2 = p; // no-warning
178 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
179 POD p3 = move(p); // no-warning
180 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
181
182 // Use rvalues as well.
183 clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
184
185 PODWrapper w;
186 w.p.y = 1;
187 PODWrapper w2 = w; // no-warning
188 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
189 PODWrapper w3 = move(w); // no-warning
190 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
191
192 // Use rvalues as well.
193 clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
194 }
195
196 void testNonPOD() {
197 NonPOD p;
198 p.x = 1;
199 NonPOD p2 = p;
200 }
201
202 void testNonPODMove() {
203 NonPOD p;
204 p.x = 1;
205 NonPOD p2 = move(p);
206 }
207
208 void testNonPODWrapper() {
209 NonPODWrapper w;
210 w.p.y = 1;
211 NonPODWrapper w2 = w;
212 }
213
214 void testNonPODWrapperMove() {
215 NonPODWrapper w;
216 w.p.y = 1;
217 NonPODWrapper w2 = move(w);
218 }
219}