blob: 3bb88c4d4eebaa103b98c58ba69f32cab06e6ce4 [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
Anna Zakscf8d2162013-12-06 18:56:29 +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 {
Anna Zakscf8d2162013-12-06 18:56:29 +0000114 void testPR16664andPR18159Crash() {
Jordan Rosee15a8a42013-07-25 17:22:05 +0000115 struct Dtor {
116 ~Dtor();
117 };
118 extern bool coin();
119 extern bool check(const Dtor &);
120
Anna Zakscf8d2162013-12-06 18:56:29 +0000121#ifndef TEMPORARY_DTORS
Jordan Rose398fb002014-04-01 16:39:33 +0000122 // FIXME: Don't assert here when tmp dtors are enabled.
123 // PR16664 and PR18159
Jordan Rosee15a8a42013-07-25 17:22:05 +0000124 if (coin() && (coin() || coin() || check(Dtor()))) {
125 Dtor();
126 }
Anna Zakscf8d2162013-12-06 18:56:29 +0000127#endif
Jordan Rosee15a8a42013-07-25 17:22:05 +0000128 }
129
Pavel Labathd527cf82013-09-02 09:09:15 +0000130#ifdef TEMPORARY_DTORS
131 struct NoReturnDtor {
132 ~NoReturnDtor() __attribute__((noreturn));
133 };
134
135 void noReturnTemp(int *x) {
136 if (! x) NoReturnDtor();
137 *x = 47; // no warning
138 }
139
140 void noReturnInline(int **x) {
141 NoReturnDtor();
142 }
143
144 void callNoReturn() {
145 int *x;
146 noReturnInline(&x);
147 *x = 47; // no warning
148 }
149
150 extern bool check(const NoReturnDtor &);
151
152 void testConsistencyIf(int i) {
Jordan Rosee15a8a42013-07-25 17:22:05 +0000153 if (i != 5)
154 return;
155 if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
Pavel Labathd527cf82013-09-02 09:09:15 +0000156 clang_analyzer_eval(true); // no warning, unreachable code
Jordan Rosee15a8a42013-07-25 17:22:05 +0000157 }
158 }
Pavel Labathd527cf82013-09-02 09:09:15 +0000159
160 void testConsistencyTernary(int i) {
161 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
162
163 clang_analyzer_eval(true); // expected-warning{{TRUE}}
164
165 if (i != 5)
166 return;
167
168 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
169
170 clang_analyzer_eval(true); // no warning, unreachable code
171 }
172
Anna Zakscf8d2162013-12-06 18:56:29 +0000173/*
Jordan Rose398fb002014-04-01 16:39:33 +0000174 // PR16664 and PR18159
175 FIXME: Don't assert here.
Pavel Labathd527cf82013-09-02 09:09:15 +0000176 void testConsistencyNested(int i) {
177 extern bool compute(bool);
Anna Zakscf8d2162013-12-06 18:56:29 +0000178
Pavel Labathd527cf82013-09-02 09:09:15 +0000179 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
Anna Zakscf8d2162013-12-06 18:56:29 +0000180 clang_analyzer_eval(true); // expected TRUE
181
182 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
183 clang_analyzer_eval(true); // expected TRUE
Pavel Labathd527cf82013-09-02 09:09:15 +0000184
185 if (i != 5)
186 return;
187
188 if (compute(i == 5 &&
189 (i == 4 || compute(true) ||
190 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
191 i != 4) {
Anna Zakscf8d2162013-12-06 18:56:29 +0000192 clang_analyzer_eval(true); // expected TRUE
Pavel Labathd527cf82013-09-02 09:09:15 +0000193 }
194
Jordan Rose398fb002014-04-01 16:39:33 +0000195 FIXME: This shouldn't cause a warning.
Pavel Labathd527cf82013-09-02 09:09:15 +0000196 if (compute(i == 5 &&
197 (i == 4 || i == 4 ||
198 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
199 i != 4) {
200 clang_analyzer_eval(true); // no warning, unreachable code
201 }
Anna Zakscf8d2162013-12-06 18:56:29 +0000202 }*/
Jordan Rose398fb002014-04-01 16:39:33 +0000203
204 // PR16664 and PR18159
205 void testConsistencyNestedSimple(bool value) {
206 if (value) {
207 if (!value || check(NoReturnDtor())) {
208 clang_analyzer_eval(true); // no warning, unreachable code
209 }
210 }
211 }
212
213 // PR16664 and PR18159
214 void testConsistencyNestedComplex(bool value) {
215 if (value) {
216 if (!value || !value || check(NoReturnDtor())) {
217 // FIXME: This shouldn't cause a warning.
218 clang_analyzer_eval(true); // expected-warning{{TRUE}}
219 }
220 }
221 }
222
223 // PR16664 and PR18159
224 void testConsistencyNestedWarning(bool value) {
225 if (value) {
226 if (!value || value || check(NoReturnDtor())) {
227 clang_analyzer_eval(true); // expected-warning{{TRUE}}
228 }
229 }
230 }
231
Pavel Labathd527cf82013-09-02 09:09:15 +0000232#endif // TEMPORARY_DTORS
Jordan Rosee15a8a42013-07-25 17:22:05 +0000233}
Pavel Labathcf878bb2013-07-26 11:50:42 +0000234
235void testStaticMaterializeTemporaryExpr() {
236 static const Trivial &ref = getTrivial();
237 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
238
239 static const Trivial &directRef = Trivial(42);
240 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
241
Pavel Labathe4e30862013-07-26 12:50:30 +0000242#if __has_feature(cxx_thread_local)
Pavel Labathcf878bb2013-07-26 11:50:42 +0000243 thread_local static const Trivial &threadRef = getTrivial();
244 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
245
246 thread_local static const Trivial &threadDirectRef = Trivial(42);
247 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
248#endif
249}
Pavel Labath375e18e2013-08-09 07:46:29 +0000250
251namespace PR16629 {
252 struct A {
253 explicit A(int* p_) : p(p_) {}
254 int* p;
255 };
256
257 extern void escape(const A*[]);
258 extern void check(int);
259
260 void callEscape(const A& a) {
261 const A* args[] = { &a };
262 escape(args);
263 }
264
265 void testNoWarning() {
266 int x;
267 callEscape(A(&x));
268 check(x); // Analyzer used to give a "x is uninitialized warning" here
269 }
270
271 void set(const A*a[]) {
272 *a[0]->p = 47;
273 }
274
275 void callSet(const A& a) {
276 const A* args[] = { &a };
277 set(args);
278 }
279
280 void testConsistency() {
281 int x;
282 callSet(A(&x));
283 clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
284 }
285}