blob: 6b49fcbddd419a75cbaeed33dca880a52e186cbf [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
122 // FIXME: Don't crash here when tmp dtros 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
174/*
175 // PR16664 and PR18159
176 FIXME: Don't crash here.
Pavel Labathd527cf82013-09-02 09:09:15 +0000177 void testConsistencyNested(int i) {
178 extern bool compute(bool);
Anna Zakscf8d2162013-12-06 18:56:29 +0000179
Pavel Labathd527cf82013-09-02 09:09:15 +0000180 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
Anna Zakscf8d2162013-12-06 18:56:29 +0000181 clang_analyzer_eval(true); // expected TRUE
182
183 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
184 clang_analyzer_eval(true); // expected TRUE
Pavel Labathd527cf82013-09-02 09:09:15 +0000185
186 if (i != 5)
187 return;
188
189 if (compute(i == 5 &&
190 (i == 4 || compute(true) ||
191 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
192 i != 4) {
Anna Zakscf8d2162013-12-06 18:56:29 +0000193 clang_analyzer_eval(true); // expected TRUE
Pavel Labathd527cf82013-09-02 09:09:15 +0000194 }
195
196 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 }*/
203
Pavel Labathd527cf82013-09-02 09:09:15 +0000204#endif // TEMPORARY_DTORS
Jordan Rosee15a8a42013-07-25 17:22:05 +0000205}
Pavel Labathcf878bb2013-07-26 11:50:42 +0000206
207void testStaticMaterializeTemporaryExpr() {
208 static const Trivial &ref = getTrivial();
209 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
210
211 static const Trivial &directRef = Trivial(42);
212 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
213
Pavel Labathe4e30862013-07-26 12:50:30 +0000214#if __has_feature(cxx_thread_local)
Pavel Labathcf878bb2013-07-26 11:50:42 +0000215 thread_local static const Trivial &threadRef = getTrivial();
216 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
217
218 thread_local static const Trivial &threadDirectRef = Trivial(42);
219 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
220#endif
221}
Pavel Labath375e18e2013-08-09 07:46:29 +0000222
223namespace PR16629 {
224 struct A {
225 explicit A(int* p_) : p(p_) {}
226 int* p;
227 };
228
229 extern void escape(const A*[]);
230 extern void check(int);
231
232 void callEscape(const A& a) {
233 const A* args[] = { &a };
234 escape(args);
235 }
236
237 void testNoWarning() {
238 int x;
239 callEscape(A(&x));
240 check(x); // Analyzer used to give a "x is uninitialized warning" here
241 }
242
243 void set(const A*a[]) {
244 *a[0]->p = 47;
245 }
246
247 void callSet(const A& a) {
248 const A* args[] = { &a };
249 set(args);
250 }
251
252 void testConsistency() {
253 int x;
254 callSet(A(&x));
255 clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
256 }
257}