blob: c57d984a1dc8458bd595e34eb9e14fddb2d5bacb [file] [log] [blame]
Jordan Rose5d2abef2013-05-06 16:48:20 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
Pavel Labathe4e30862013-07-26 12:50:30 +00002// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
Rui Ueyamaa89f9c82014-08-06 22:01:54 +00003// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s
Jordan Rose2c625dd2012-08-29 01:11:59 +00004
Jordan Rosefe03e402013-02-21 23:57:17 +00005extern bool clang_analyzer_eval(bool);
6
Jordan Rose2c625dd2012-08-29 01:11:59 +00007struct Trivial {
8 Trivial(int x) : value(x) {}
9 int value;
10};
11
12struct NonTrivial : public Trivial {
13 NonTrivial(int x) : Trivial(x) {}
14 ~NonTrivial();
15};
16
17
18Trivial getTrivial() {
19 return Trivial(42); // no-warning
20}
21
22const Trivial &getTrivialRef() {
Jordan Rosec9487092013-02-26 01:21:21 +000023 return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
Jordan Rose2c625dd2012-08-29 01:11:59 +000024}
25
26
27NonTrivial getNonTrivial() {
28 return NonTrivial(42); // no-warning
29}
30
31const NonTrivial &getNonTrivialRef() {
Jordan Rosec9487092013-02-26 01:21:21 +000032 return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
Jordan Rose2c625dd2012-08-29 01:11:59 +000033}
34
Jordan Rosefe03e402013-02-21 23:57:17 +000035namespace rdar13265460 {
36 struct TrivialSubclass : public Trivial {
37 TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
38 int anotherValue;
39 };
40
41 TrivialSubclass getTrivialSub() {
42 TrivialSubclass obj(1);
43 obj.value = 42;
44 obj.anotherValue = -42;
45 return obj;
46 }
47
Jordan Rose5772f822013-02-22 01:51:15 +000048 void testImmediate() {
Jordan Rosefe03e402013-02-21 23:57:17 +000049 TrivialSubclass obj = getTrivialSub();
50
51 clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
52 clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
53
54 clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
55 clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
56 }
Jordan Rose5772f822013-02-22 01:51:15 +000057
58 void testMaterializeTemporaryExpr() {
59 const TrivialSubclass &ref = getTrivialSub();
60 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
61
62 const Trivial &baseRef = getTrivialSub();
63 clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
64 }
Jordan Rosefe03e402013-02-21 23:57:17 +000065}
66
Jordan Rose861a1742013-02-26 01:21:27 +000067namespace rdar13281951 {
68 struct Derived : public Trivial {
69 Derived(int value) : Trivial(value), value2(-value) {}
70 int value2;
71 };
72
73 void test() {
74 Derived obj(1);
75 obj.value = 42;
76 const Trivial * const &pointerRef = &obj;
77 clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
78 }
79}
80
Jordan Rose5d2abef2013-05-06 16:48:20 +000081namespace compound_literals {
82 struct POD {
83 int x, y;
84 };
85 struct HasCtor {
86 HasCtor(int x, int y) : x(x), y(y) {}
87 int x, y;
88 };
89 struct HasDtor {
90 int x, y;
91 ~HasDtor();
92 };
93 struct HasCtorDtor {
94 HasCtorDtor(int x, int y) : x(x), y(y) {}
95 ~HasCtorDtor();
96 int x, y;
97 };
98
99 void test() {
100 clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
101 clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
102
103#if __cplusplus >= 201103L
104 clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
105
106 // FIXME: should be TRUE, but we don't inline the constructors of
107 // temporaries because we can't model their destructors yet.
108 clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
109#endif
110 }
111}
112
Jordan Rosee15a8a42013-07-25 17:22:05 +0000113namespace destructors {
Manuel Klimekd9b4ad62014-08-06 12:45:51 +0000114 void testPR16664andPR18159Crash() {
Rui Ueyamaa89f9c82014-08-06 22:01:54 +0000115 struct Dtor {
116 ~Dtor();
117 };
118 extern bool coin();
119 extern bool check(const Dtor &);
120
Manuel Klimek264f9632014-05-05 09:58:03 +0000121 // Regression test: we used to assert here when tmp dtors are enabled.
Jordan Rose398fb002014-04-01 16:39:33 +0000122 // PR16664 and PR18159
Jordan Rosee15a8a42013-07-25 17:22:05 +0000123 if (coin() && (coin() || coin() || check(Dtor()))) {
124 Dtor();
125 }
126 }
127
Pavel Labathd527cf82013-09-02 09:09:15 +0000128#ifdef TEMPORARY_DTORS
129 struct NoReturnDtor {
130 ~NoReturnDtor() __attribute__((noreturn));
131 };
132
133 void noReturnTemp(int *x) {
134 if (! x) NoReturnDtor();
135 *x = 47; // no warning
136 }
137
138 void noReturnInline(int **x) {
139 NoReturnDtor();
140 }
141
142 void callNoReturn() {
143 int *x;
144 noReturnInline(&x);
145 *x = 47; // no warning
146 }
147
148 extern bool check(const NoReturnDtor &);
149
150 void testConsistencyIf(int i) {
Jordan Rosee15a8a42013-07-25 17:22:05 +0000151 if (i != 5)
152 return;
153 if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
Pavel Labathd527cf82013-09-02 09:09:15 +0000154 clang_analyzer_eval(true); // no warning, unreachable code
Jordan Rosee15a8a42013-07-25 17:22:05 +0000155 }
156 }
Pavel Labathd527cf82013-09-02 09:09:15 +0000157
158 void testConsistencyTernary(int i) {
159 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
160
161 clang_analyzer_eval(true); // expected-warning{{TRUE}}
162
163 if (i != 5)
164 return;
165
166 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
167
168 clang_analyzer_eval(true); // no warning, unreachable code
169 }
170
Manuel Klimek264f9632014-05-05 09:58:03 +0000171 // Regression test: we used to assert here.
Jordan Rose398fb002014-04-01 16:39:33 +0000172 // PR16664 and PR18159
Pavel Labathd527cf82013-09-02 09:09:15 +0000173 void testConsistencyNested(int i) {
174 extern bool compute(bool);
Manuel Klimek264f9632014-05-05 09:58:03 +0000175
Pavel Labathd527cf82013-09-02 09:09:15 +0000176 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
Manuel Klimek264f9632014-05-05 09:58:03 +0000177 clang_analyzer_eval(true); // expected-warning{{TRUE}}
178
Anna Zakscf8d2162013-12-06 18:56:29 +0000179 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
Manuel Klimek264f9632014-05-05 09:58:03 +0000180 clang_analyzer_eval(true); // expected-warning{{TRUE}}
Pavel Labathd527cf82013-09-02 09:09:15 +0000181
182 if (i != 5)
183 return;
184
185 if (compute(i == 5 &&
186 (i == 4 || compute(true) ||
187 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
188 i != 4) {
Manuel Klimek264f9632014-05-05 09:58:03 +0000189 clang_analyzer_eval(true); // expected-warning{{TRUE}}
Pavel Labathd527cf82013-09-02 09:09:15 +0000190 }
191
192 if (compute(i == 5 &&
193 (i == 4 || i == 4 ||
194 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
195 i != 4) {
Rui Ueyamaa89f9c82014-08-06 22:01:54 +0000196 // FIXME: This shouldn't cause a warning.
197 clang_analyzer_eval(true); // expected-warning{{TRUE}}
Pavel Labathd527cf82013-09-02 09:09:15 +0000198 }
Manuel Klimek264f9632014-05-05 09:58:03 +0000199 }
Jordan Rose398fb002014-04-01 16:39:33 +0000200
201 // PR16664 and PR18159
202 void testConsistencyNestedSimple(bool value) {
203 if (value) {
204 if (!value || check(NoReturnDtor())) {
205 clang_analyzer_eval(true); // no warning, unreachable code
206 }
207 }
208 }
209
210 // PR16664 and PR18159
211 void testConsistencyNestedComplex(bool value) {
212 if (value) {
213 if (!value || !value || check(NoReturnDtor())) {
Rui Ueyamaa89f9c82014-08-06 22:01:54 +0000214 // FIXME: This shouldn't cause a warning.
215 clang_analyzer_eval(true); // expected-warning{{TRUE}}
Jordan Rose398fb002014-04-01 16:39:33 +0000216 }
217 }
218 }
219
220 // PR16664 and PR18159
221 void testConsistencyNestedWarning(bool value) {
222 if (value) {
223 if (!value || value || check(NoReturnDtor())) {
224 clang_analyzer_eval(true); // expected-warning{{TRUE}}
225 }
226 }
227 }
228
Manuel Klimek264f9632014-05-05 09:58:03 +0000229 void testBinaryOperatorShortcut(bool value) {
230 if (value) {
231 if (false && false && check(NoReturnDtor()) && true) {
232 clang_analyzer_eval(true);
233 }
234 }
235 }
236
Pavel Labathd527cf82013-09-02 09:09:15 +0000237#endif // TEMPORARY_DTORS
Jordan Rosee15a8a42013-07-25 17:22:05 +0000238}
Pavel Labathcf878bb2013-07-26 11:50:42 +0000239
240void testStaticMaterializeTemporaryExpr() {
241 static const Trivial &ref = getTrivial();
242 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
243
244 static const Trivial &directRef = Trivial(42);
245 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
246
Pavel Labathe4e30862013-07-26 12:50:30 +0000247#if __has_feature(cxx_thread_local)
Pavel Labathcf878bb2013-07-26 11:50:42 +0000248 thread_local static const Trivial &threadRef = getTrivial();
249 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
250
251 thread_local static const Trivial &threadDirectRef = Trivial(42);
252 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
253#endif
254}
Pavel Labath375e18e2013-08-09 07:46:29 +0000255
256namespace PR16629 {
257 struct A {
258 explicit A(int* p_) : p(p_) {}
259 int* p;
260 };
261
262 extern void escape(const A*[]);
263 extern void check(int);
264
265 void callEscape(const A& a) {
266 const A* args[] = { &a };
267 escape(args);
268 }
269
270 void testNoWarning() {
271 int x;
272 callEscape(A(&x));
273 check(x); // Analyzer used to give a "x is uninitialized warning" here
274 }
275
276 void set(const A*a[]) {
277 *a[0]->p = 47;
278 }
279
280 void callSet(const A& a) {
281 const A* args[] = { &a };
282 set(args);
283 }
284
285 void testConsistency() {
286 int x;
287 callSet(A(&x));
288 clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
289 }
290}