1 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
2 // RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
3 // RUN: -analyzer-config eagerly-assume=false -verify %s\
4 // RUN: -std=c++03 -analyzer-config cfg-temporary-dtors=false
5
6 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
7 // RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
8 // RUN: -analyzer-config eagerly-assume=false -verify %s\
9 // RUN: -std=c++11 -analyzer-config cfg-temporary-dtors=false
10
11 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
12 // RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
13 // RUN: -analyzer-config eagerly-assume=false -verify %s\
14 // RUN: -std=c++11 -analyzer-config cfg-temporary-dtors=true\
15 // RUN: -DTEMPORARY_DTORS
16
17 // RUN: %clang_analyze_cc1 -w -analyzer-checker=core,cplusplus\
18 // RUN: -analyzer-checker debug.ExprInspection -Wno-non-pod-varargs\
19 // RUN: -analyzer-config eagerly-assume=false -verify %s\
20 // RUN: -std=c++17 -analyzer-config cfg-temporary-dtors=true\
21 // RUN: -DTEMPORARY_DTORS
22
23
24 extern bool clang_analyzer_eval(bool);
25 extern bool clang_analyzer_warnIfReached();
26 void clang_analyzer_checkInlined(bool);
27
28 #include "Inputs/system-header-simulator-cxx.h"
29
30 struct Trivial {
TrivialTrivial31 Trivial(int x) : value(x) {}
32 int value;
33 };
34
35 struct NonTrivial : public Trivial {
NonTrivialNonTrivial36 NonTrivial(int x) : Trivial(x) {}
37 ~NonTrivial();
38 };
39
40
getTrivial()41 Trivial getTrivial() {
42 return Trivial(42); // no-warning
43 }
44
getTrivialRef()45 const Trivial &getTrivialRef() {
46 return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
47 }
48
49
getNonTrivial()50 NonTrivial getNonTrivial() {
51 return NonTrivial(42); // no-warning
52 }
53
getNonTrivialRef()54 const NonTrivial &getNonTrivialRef() {
55 return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
56 }
57
58 namespace rdar13265460 {
59 struct TrivialSubclass : public Trivial {
TrivialSubclassrdar13265460::TrivialSubclass60 TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
61 int anotherValue;
62 };
63
getTrivialSub()64 TrivialSubclass getTrivialSub() {
65 TrivialSubclass obj(1);
66 obj.value = 42;
67 obj.anotherValue = -42;
68 return obj;
69 }
70
testImmediate()71 void testImmediate() {
72 TrivialSubclass obj = getTrivialSub();
73
74 clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
75 clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
76
77 clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
78 clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
79 }
80
testMaterializeTemporaryExpr()81 void testMaterializeTemporaryExpr() {
82 const TrivialSubclass &ref = getTrivialSub();
83 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
84
85 const Trivial &baseRef = getTrivialSub();
86 clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
87 }
88 }
89
90 namespace rdar13281951 {
91 struct Derived : public Trivial {
Derivedrdar13281951::Derived92 Derived(int value) : Trivial(value), value2(-value) {}
93 int value2;
94 };
95
test()96 void test() {
97 Derived obj(1);
98 obj.value = 42;
99 const Trivial * const &pointerRef = &obj;
100 clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
101 }
102 }
103
104 namespace compound_literals {
105 struct POD {
106 int x, y;
107 };
108 struct HasCtor {
HasCtorcompound_literals::HasCtor109 HasCtor(int x, int y) : x(x), y(y) {}
110 int x, y;
111 };
112 struct HasDtor {
113 int x, y;
114 ~HasDtor();
115 };
116 struct HasCtorDtor {
HasCtorDtorcompound_literals::HasCtorDtor117 HasCtorDtor(int x, int y) : x(x), y(y) {}
118 ~HasCtorDtor();
119 int x, y;
120 };
121
test()122 void test() {
123 clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
124 clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
125
126 #if __cplusplus >= 201103L
127 clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
128
129 // FIXME: should be TRUE, but we don't inline the constructors of
130 // temporaries because we can't model their destructors yet.
131 clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
132 #endif
133 }
134 }
135
136 namespace destructors {
137 struct Dtor {
138 ~Dtor();
139 };
140 extern bool coin();
141 extern bool check(const Dtor &);
142
testPR16664andPR18159Crash()143 void testPR16664andPR18159Crash() {
144 // Regression test: we used to assert here when tmp dtors are enabled.
145 // PR16664 and PR18159
146 if (coin() && (coin() || coin() || check(Dtor()))) {
147 Dtor();
148 }
149 }
150
151 #ifdef TEMPORARY_DTORS
152 struct NoReturnDtor {
153 ~NoReturnDtor() __attribute__((noreturn));
154 };
155
noReturnTemp(int * x)156 void noReturnTemp(int *x) {
157 if (! x) NoReturnDtor();
158 *x = 47; // no warning
159 }
160
noReturnInline(int ** x)161 void noReturnInline(int **x) {
162 NoReturnDtor();
163 }
164
callNoReturn()165 void callNoReturn() {
166 int *x;
167 noReturnInline(&x);
168 *x = 47; // no warning
169 }
170
171 extern bool check(const NoReturnDtor &);
172
testConsistencyIf(int i)173 void testConsistencyIf(int i) {
174 if (i != 5)
175 return;
176 if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
177 clang_analyzer_eval(true); // no warning, unreachable code
178 }
179 }
180
testConsistencyTernary(int i)181 void testConsistencyTernary(int i) {
182 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
183
184 clang_analyzer_eval(true); // expected-warning{{TRUE}}
185
186 if (i != 5)
187 return;
188
189 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
190
191 clang_analyzer_eval(true); // no warning, unreachable code
192 }
193
194 // Regression test: we used to assert here.
195 // PR16664 and PR18159
testConsistencyNested(int i)196 void testConsistencyNested(int i) {
197 extern bool compute(bool);
198
199 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
200 clang_analyzer_eval(true); // expected-warning{{TRUE}}
201
202 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
203 clang_analyzer_eval(true); // expected-warning{{TRUE}}
204
205 if (i != 5)
206 return;
207
208 if (compute(i == 5 &&
209 (i == 4 || compute(true) ||
210 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
211 i != 4) {
212 clang_analyzer_eval(true); // expected-warning{{TRUE}}
213 }
214
215 if (compute(i == 5 &&
216 (i == 4 || i == 4 ||
217 compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
218 i != 4) {
219 clang_analyzer_eval(true); // no warning, unreachable code
220 }
221 }
222
223 // PR16664 and PR18159
testConsistencyNestedSimple(bool value)224 void testConsistencyNestedSimple(bool value) {
225 if (value) {
226 if (!value || check(NoReturnDtor())) {
227 clang_analyzer_eval(true); // no warning, unreachable code
228 }
229 }
230 }
231
232 // PR16664 and PR18159
testConsistencyNestedComplex(bool value)233 void testConsistencyNestedComplex(bool value) {
234 if (value) {
235 if (!value || !value || check(NoReturnDtor())) {
236 clang_analyzer_eval(true); // no warning, unreachable code
237 }
238 }
239 }
240
241 // PR16664 and PR18159
testConsistencyNestedWarning(bool value)242 void testConsistencyNestedWarning(bool value) {
243 if (value) {
244 if (!value || value || check(NoReturnDtor())) {
245 clang_analyzer_eval(true); // expected-warning{{TRUE}}
246 }
247 }
248 }
249 // PR16664 and PR18159
testConsistencyNestedComplexMidBranch(bool value)250 void testConsistencyNestedComplexMidBranch(bool value) {
251 if (value) {
252 if (!value || !value || check(NoReturnDtor()) || value) {
253 clang_analyzer_eval(true); // no warning, unreachable code
254 }
255 }
256 }
257
258 // PR16664 and PR18159
testConsistencyNestedComplexNestedBranch(bool value)259 void testConsistencyNestedComplexNestedBranch(bool value) {
260 if (value) {
261 if (!value || (!value || check(NoReturnDtor()) || value)) {
262 clang_analyzer_eval(true); // no warning, unreachable code
263 }
264 }
265 }
266
267 // PR16664 and PR18159
testConsistencyNestedVariableModification(bool value)268 void testConsistencyNestedVariableModification(bool value) {
269 bool other = true;
270 if (value) {
271 if (!other || !value || (other = false) || check(NoReturnDtor()) ||
272 !other) {
273 clang_analyzer_eval(true); // no warning, unreachable code
274 }
275 }
276 }
277
testTernaryNoReturnTrueBranch(bool value)278 void testTernaryNoReturnTrueBranch(bool value) {
279 if (value) {
280 bool b = value && (value ? check(NoReturnDtor()) : true);
281 clang_analyzer_eval(true); // no warning, unreachable code
282 }
283 }
testTernaryNoReturnFalseBranch(bool value)284 void testTernaryNoReturnFalseBranch(bool value) {
285 if (value) {
286 bool b = !value && !value ? true : check(NoReturnDtor());
287 clang_analyzer_eval(true); // no warning, unreachable code
288 }
289 }
testTernaryIgnoreNoreturnBranch(bool value)290 void testTernaryIgnoreNoreturnBranch(bool value) {
291 if (value) {
292 bool b = !value && !value ? check(NoReturnDtor()) : true;
293 clang_analyzer_eval(true); // expected-warning{{TRUE}}
294 }
295 }
testTernaryTrueBranchReached(bool value)296 void testTernaryTrueBranchReached(bool value) {
297 value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}
298 check(NoReturnDtor());
299 }
testTernaryFalseBranchReached(bool value)300 void testTernaryFalseBranchReached(bool value) {
301 value ? check(NoReturnDtor()) :
302 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
303 }
304
testLoop()305 void testLoop() {
306 for (int i = 0; i < 10; ++i) {
307 if (i < 3 && (i >= 2 || check(NoReturnDtor()))) {
308 clang_analyzer_eval(true); // no warning, unreachable code
309 }
310 }
311 }
312
testRecursiveFrames(bool isInner)313 bool testRecursiveFrames(bool isInner) {
314 if (isInner ||
315 (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}}
316 check(NoReturnDtor()) ||
317 testRecursiveFrames(true)) {
318 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
319 }
320 }
testRecursiveFramesStart()321 void testRecursiveFramesStart() { testRecursiveFrames(false); }
322
testLambdas()323 void testLambdas() {
324 []() { check(NoReturnDtor()); } != nullptr || check(Dtor());
325 }
326
testGnuExpressionStatements(int v)327 void testGnuExpressionStatements(int v) {
328 ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;
329 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
330
331 ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;
332 clang_analyzer_warnIfReached(); // no warning, unreachable code
333 }
334
testGnuExpressionStatementsDestructionPoint(int v)335 void testGnuExpressionStatementsDestructionPoint(int v) {
336 // In normal context, the temporary destructor runs at the end of the full
337 // statement, thus the last statement is reached.
338 (++v, check(NoReturnDtor()), v == 42),
339 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
340
341 // GNU expression statements execute temporary destructors within the
342 // blocks, thus the last statement is not reached.
343 ({ ++v; check(NoReturnDtor()); v == 42; }),
344 clang_analyzer_warnIfReached(); // no warning, unreachable code
345 }
346
testMultipleTemporaries(bool value)347 void testMultipleTemporaries(bool value) {
348 if (value) {
349 // FIXME: Find a way to verify construction order.
350 // ~Dtor should run before ~NoReturnDtor() because construction order is
351 // guaranteed by comma operator.
352 if (!value || check((NoReturnDtor(), Dtor())) || value) {
353 clang_analyzer_eval(true); // no warning, unreachable code
354 }
355 }
356 }
357
testBinaryOperatorShortcut(bool value)358 void testBinaryOperatorShortcut(bool value) {
359 if (value) {
360 if (false && false && check(NoReturnDtor()) && true) {
361 clang_analyzer_eval(true);
362 }
363 }
364 }
365
testIfAtEndOfLoop()366 void testIfAtEndOfLoop() {
367 int y = 0;
368 while (true) {
369 if (y > 0) {
370 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
371 }
372 ++y;
373 // Test that the CFG gets hooked up correctly when temporary destructors
374 // are handled after a statically known branch condition.
375 if (true) (void)0; else (void)check(NoReturnDtor());
376 }
377 }
378
testTernaryAtEndOfLoop()379 void testTernaryAtEndOfLoop() {
380 int y = 0;
381 while (true) {
382 if (y > 0) {
383 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
384 }
385 ++y;
386 // Test that the CFG gets hooked up correctly when temporary destructors
387 // are handled after a statically known branch condition.
388 true ? (void)0 : (void)check(NoReturnDtor());
389 }
390 }
391
testNoReturnInComplexCondition()392 void testNoReturnInComplexCondition() {
393 check(Dtor()) &&
394 (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
395 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
396 }
397
testSequencingOfConditionalTempDtors(bool b)398 void testSequencingOfConditionalTempDtors(bool b) {
399 b || (check(Dtor()), check(NoReturnDtor()));
400 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
401 }
402
testSequencingOfConditionalTempDtors2(bool b)403 void testSequencingOfConditionalTempDtors2(bool b) {
404 (b || check(Dtor())), check(NoReturnDtor());
405 clang_analyzer_warnIfReached(); // no warning, unreachable code
406 }
407
testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b)408 void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {
409 b || (check(Dtor()) + check(NoReturnDtor()));
410 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
411 }
412
413 void f(Dtor d = Dtor());
testDefaultParameters()414 void testDefaultParameters() {
415 f();
416 }
417
418 struct DefaultParam {
419 DefaultParam(int, const Dtor& d = Dtor());
420 ~DefaultParam();
421 };
testDefaultParamConstructorsInLoops()422 void testDefaultParamConstructorsInLoops() {
423 while (true) {
424 // FIXME: This exact pattern triggers the temporary cleanup logic
425 // to fail when adding a 'clean' state.
426 DefaultParam(42);
427 DefaultParam(42);
428 }
429 }
testDefaultParamConstructorsInTernariesInLoops(bool value)430 void testDefaultParamConstructorsInTernariesInLoops(bool value) {
431 while (true) {
432 // FIXME: This exact pattern triggers the temporary cleanup logic
433 // to visit the bind-temporary logic with a state that already has that
434 // temporary marked as executed.
435 value ? DefaultParam(42) : DefaultParam(42);
436 }
437 }
438 #else // !TEMPORARY_DTORS
439
440 // Test for fallback logic that conservatively stops exploration after
441 // executing a temporary constructor for a class with a no-return destructor
442 // when temporary destructors are not enabled in the CFG.
443
444 struct CtorWithNoReturnDtor {
445 CtorWithNoReturnDtor() = default;
446
CtorWithNoReturnDtordestructors::CtorWithNoReturnDtor447 CtorWithNoReturnDtor(int x) {
448 clang_analyzer_checkInlined(false); // no-warning
449 }
450
451 ~CtorWithNoReturnDtor() __attribute__((noreturn));
452 };
453
testDefaultContructorWithNoReturnDtor()454 void testDefaultContructorWithNoReturnDtor() {
455 CtorWithNoReturnDtor();
456 clang_analyzer_warnIfReached(); // no-warning
457 }
458
testLifeExtensionWithNoReturnDtor()459 void testLifeExtensionWithNoReturnDtor() {
460 const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();
461
462 // This represents an (expected) loss of coverage, since the destructor
463 // of the lifetime-exended temporary is executed at the end of
464 // scope.
465 clang_analyzer_warnIfReached(); // no-warning
466 }
467
468 #if __cplusplus >= 201103L
469 struct CtorWithNoReturnDtor2 {
470 CtorWithNoReturnDtor2() = default;
471
CtorWithNoReturnDtor2destructors::CtorWithNoReturnDtor2472 CtorWithNoReturnDtor2(int x) {
473 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
474 }
475
476 ~CtorWithNoReturnDtor2() __attribute__((noreturn));
477 };
returnNoReturnDtor()478 CtorWithNoReturnDtor2 returnNoReturnDtor() {
479 return {1}; // no-crash
480 }
481 #endif
482
483 #endif // TEMPORARY_DTORS
484 }
485
486 namespace default_param_elided_destructors {
487 struct a {
488 ~a();
489 };
490 struct F {
491 a d;
492 F(char *, a = a());
493 };
g()494 void g() {
495 char h[1];
496 for (int i = 0;;)
497 F j(i ? j : h);
498 }
499 } // namespace default_param_elided_destructors
500
testStaticMaterializeTemporaryExpr()501 void testStaticMaterializeTemporaryExpr() {
502 static const Trivial &ref = getTrivial();
503 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
504
505 static const Trivial &directRef = Trivial(42);
506 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
507
508 #if __has_feature(cxx_thread_local)
509 thread_local static const Trivial &threadRef = getTrivial();
510 clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
511
512 thread_local static const Trivial &threadDirectRef = Trivial(42);
513 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
514 #endif
515 }
516
517 namespace PR16629 {
518 struct A {
APR16629::A519 explicit A(int* p_) : p(p_) {}
520 int* p;
521 };
522
523 extern void escape(const A*[]);
524 extern void check(int);
525
callEscape(const A & a)526 void callEscape(const A& a) {
527 const A* args[] = { &a };
528 escape(args);
529 }
530
testNoWarning()531 void testNoWarning() {
532 int x;
533 callEscape(A(&x));
534 check(x); // Analyzer used to give a "x is uninitialized warning" here
535 }
536
set(const A * a[])537 void set(const A*a[]) {
538 *a[0]->p = 47;
539 }
540
callSet(const A & a)541 void callSet(const A& a) {
542 const A* args[] = { &a };
543 set(args);
544 }
545
testConsistency()546 void testConsistency() {
547 int x;
548 callSet(A(&x));
549 clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
550 }
551 }
552
553 namespace PR32088 {
testReturnFromStmtExprInitializer()554 void testReturnFromStmtExprInitializer() {
555 // We shouldn't try to destroy the object pointed to by `obj' upon return.
556 const NonTrivial &obj = ({
557 return; // no-crash
558 NonTrivial(42);
559 });
560 }
561 }
562
563 namespace CopyToTemporaryCorrectly {
564 class Super {
565 public:
m()566 void m() {
567 mImpl();
568 }
569 virtual void mImpl() = 0;
570 };
571 class Sub : public Super {
572 public:
Sub(const int & p)573 Sub(const int &p) : j(p) {}
mImpl()574 virtual void mImpl() override {
575 // Used to be undefined pointer dereference because we didn't copy
576 // the subclass data (j) to the temporary object properly.
577 (void)(j + 1); // no-warning
578 if (j != 22) {
579 clang_analyzer_warnIfReached(); // no-warning
580 }
581 }
582 const int &j;
583 };
run()584 void run() {
585 int i = 22;
586 Sub(i).m();
587 }
588 }
589
590 namespace test_return_temporary {
591 class C {
592 int x, y;
593
594 public:
C(int x,int y)595 C(int x, int y) : x(x), y(y) {}
getX() const596 int getX() const { return x; }
getY() const597 int getY() const { return y; }
~C()598 ~C() {}
599 };
600
601 class D: public C {
602 public:
D()603 D() : C(1, 2) {}
D(const D & d)604 D(const D &d): C(d.getX(), d.getY()) {}
605 };
606
returnTemporaryWithVariable()607 C returnTemporaryWithVariable() { C c(1, 2); return c; }
returnTemporaryWithAnotherFunctionWithVariable()608 C returnTemporaryWithAnotherFunctionWithVariable() {
609 return returnTemporaryWithVariable();
610 }
returnTemporaryWithCopyConstructionWithVariable()611 C returnTemporaryWithCopyConstructionWithVariable() {
612 return C(returnTemporaryWithVariable());
613 }
614
returnTemporaryWithConstruction()615 C returnTemporaryWithConstruction() { return C(1, 2); }
returnTemporaryWithAnotherFunctionWithConstruction()616 C returnTemporaryWithAnotherFunctionWithConstruction() {
617 return returnTemporaryWithConstruction();
618 }
returnTemporaryWithCopyConstructionWithConstruction()619 C returnTemporaryWithCopyConstructionWithConstruction() {
620 return C(returnTemporaryWithConstruction());
621 }
622
returnTemporaryWithVariableAndNonTrivialCopy()623 D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy()624 D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
625 return returnTemporaryWithVariableAndNonTrivialCopy();
626 }
returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy()627 D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
628 return D(returnTemporaryWithVariableAndNonTrivialCopy());
629 }
630
631 #if __cplusplus >= 201103L
returnTemporaryWithBraces()632 C returnTemporaryWithBraces() { return {1, 2}; }
returnTemporaryWithAnotherFunctionWithBraces()633 C returnTemporaryWithAnotherFunctionWithBraces() {
634 return returnTemporaryWithBraces();
635 }
returnTemporaryWithCopyConstructionWithBraces()636 C returnTemporaryWithCopyConstructionWithBraces() {
637 return C(returnTemporaryWithBraces());
638 }
639 #endif // C++11
640
test()641 void test() {
642 C c1 = returnTemporaryWithVariable();
643 clang_analyzer_eval(c1.getX() == 1); // expected-warning{{TRUE}}
644 clang_analyzer_eval(c1.getY() == 2); // expected-warning{{TRUE}}
645
646 C c2 = returnTemporaryWithAnotherFunctionWithVariable();
647 clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}
648 clang_analyzer_eval(c2.getY() == 2); // expected-warning{{TRUE}}
649
650 C c3 = returnTemporaryWithCopyConstructionWithVariable();
651 clang_analyzer_eval(c3.getX() == 1); // expected-warning{{TRUE}}
652 clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
653
654 C c4 = returnTemporaryWithConstruction();
655 clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}}
656 clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}}
657
658 C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
659 clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
660 clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
661
662 C c6 = returnTemporaryWithCopyConstructionWithConstruction();
663 clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
664 clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
665
666 #if __cplusplus >= 201103L
667
668 C c7 = returnTemporaryWithBraces();
669 clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}}
670 clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}}
671
672 C c8 = returnTemporaryWithAnotherFunctionWithBraces();
673 clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}}
674 clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}}
675
676 C c9 = returnTemporaryWithCopyConstructionWithBraces();
677 clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}}
678 clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}}
679
680 #endif // C++11
681
682 D d1 = returnTemporaryWithVariableAndNonTrivialCopy();
683 clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}}
684 clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}}
685
686 D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy();
687 clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}}
688 clang_analyzer_eval(d2.getY() == 2); // expected-warning{{TRUE}}
689
690 D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
691 clang_analyzer_eval(d3.getX() == 1); // expected-warning{{TRUE}}
692 clang_analyzer_eval(d3.getY() == 2); // expected-warning{{TRUE}}
693 }
694 } // namespace test_return_temporary
695
696
697 namespace test_temporary_object_expr_without_dtor {
698 class C {
699 int x;
700 public:
C(int x)701 C(int x) : x(x) {}
getX() const702 int getX() const { return x; }
703 };
704
test()705 void test() {
706 clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
707 };
708 }
709
710 namespace test_temporary_object_expr_with_dtor {
711 class C {
712 int x;
713
714 public:
C(int x)715 C(int x) : x(x) {}
~C()716 ~C() {}
getX() const717 int getX() const { return x; }
718 };
719
test(int coin)720 void test(int coin) {
721 clang_analyzer_eval(C(3).getX() == 3);
722 #ifdef TEMPORARY_DTORS
723 // expected-warning@-2{{TRUE}}
724 #else
725 // expected-warning@-4{{UNKNOWN}}
726 #endif
727
728 const C &c1 = coin ? C(1) : C(2);
729 if (coin) {
730 clang_analyzer_eval(c1.getX() == 1);
731 #ifdef TEMPORARY_DTORS
732 // expected-warning@-2{{TRUE}}
733 #else
734 // expected-warning@-4{{UNKNOWN}}
735 #endif
736 } else {
737 clang_analyzer_eval(c1.getX() == 2);
738 #ifdef TEMPORARY_DTORS
739 // expected-warning@-2{{TRUE}}
740 #else
741 // expected-warning@-4{{UNKNOWN}}
742 #endif
743 }
744
745 C c2 = coin ? C(1) : C(2);
746 if (coin) {
747 clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}
748 } else {
749 clang_analyzer_eval(c2.getX() == 2); // expected-warning{{TRUE}}
750 }
751 }
752
753 } // namespace test_temporary_object_expr
754
755 namespace test_match_constructors_and_destructors {
756 class C {
757 public:
758 int &x, &y;
C(int & _x,int & _y)759 C(int &_x, int &_y) : x(_x), y(_y) { ++x; }
C(const C & c)760 C(const C &c): x(c.x), y(c.y) { ++x; }
~C()761 ~C() { ++y; }
762 };
763
test_simple_temporary()764 void test_simple_temporary() {
765 int x = 0, y = 0;
766 {
767 const C &c = C(x, y);
768 }
769 // One constructor and one destructor.
770 clang_analyzer_eval(x == 1);
771 clang_analyzer_eval(y == 1);
772 #ifdef TEMPORARY_DTORS
773 // expected-warning@-3{{TRUE}}
774 // expected-warning@-3{{TRUE}}
775 #else
776 // expected-warning@-6{{UNKNOWN}}
777 // expected-warning@-6{{UNKNOWN}}
778 #endif
779 }
780
test_simple_temporary_with_copy()781 void test_simple_temporary_with_copy() {
782 int x = 0, y = 0;
783 {
784 C c = C(x, y);
785 }
786 // Only one constructor directly into the variable, and one destructor.
787 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
788 clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
789 }
790
test_ternary_temporary(int coin)791 void test_ternary_temporary(int coin) {
792 int x = 0, y = 0, z = 0, w = 0;
793 {
794 const C &c = coin ? C(x, y) : C(z, w);
795 }
796 // Only one constructor on every branch, and one automatic destructor.
797 if (coin) {
798 clang_analyzer_eval(x == 1);
799 clang_analyzer_eval(y == 1);
800 #ifdef TEMPORARY_DTORS
801 // expected-warning@-3{{TRUE}}
802 // expected-warning@-3{{TRUE}}
803 #else
804 // expected-warning@-6{{UNKNOWN}}
805 // expected-warning@-6{{UNKNOWN}}
806 #endif
807 clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
808 clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
809
810 } else {
811 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
812 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
813 clang_analyzer_eval(z == 1);
814 clang_analyzer_eval(w == 1);
815 #ifdef TEMPORARY_DTORS
816 // expected-warning@-3{{TRUE}}
817 // expected-warning@-3{{TRUE}}
818 #else
819 // expected-warning@-6{{UNKNOWN}}
820 // expected-warning@-6{{UNKNOWN}}
821 #endif
822 }
823 }
824
test_ternary_temporary_with_copy(int coin)825 void test_ternary_temporary_with_copy(int coin) {
826 int x = 0, y = 0, z = 0, w = 0;
827 {
828 C c = coin ? C(x, y) : C(z, w);
829 }
830 // On each branch the variable is constructed directly.
831 if (coin) {
832 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
833 clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
834 clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
835 clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
836
837 } else {
838 clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
839 clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
840 clang_analyzer_eval(z == 1); // expected-warning{{TRUE}}
841 clang_analyzer_eval(w == 1); // expected-warning{{TRUE}}
842 }
843 }
844 } // namespace test_match_constructors_and_destructors
845
846 namespace destructors_for_return_values {
847
848 class C {
849 public:
~C()850 ~C() {
851 1 / 0; // expected-warning{{Division by zero}}
852 }
853 };
854
855 C make();
856
testFloatingCall()857 void testFloatingCall() {
858 make();
859 // Should have divided by zero in the destructor.
860 clang_analyzer_warnIfReached();
861 #ifndef TEMPORARY_DTORS
862 // expected-warning@-2{{REACHABLE}}
863 #endif
864 }
865
testLifetimeExtendedCall()866 void testLifetimeExtendedCall() {
867 {
868 const C &c = make();
869 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
870 }
871 // Should have divided by zero in the destructor.
872 clang_analyzer_warnIfReached(); // no-warning
873 }
874
testCopiedCall()875 void testCopiedCall() {
876 {
877 C c = make();
878 // Should have elided the constructor/destructor for the temporary
879 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
880 }
881 // Should have divided by zero in the destructor.
882 clang_analyzer_warnIfReached(); // no-warning
883 }
884 } // namespace destructors_for_return_values
885
886 namespace dont_forget_destructor_around_logical_op {
887 int glob;
888
889 class C {
890 public:
~C()891 ~C() {
892 glob = 1;
893 // FIXME: Why is destructor not inlined in C++17
894 clang_analyzer_checkInlined(true);
895 #ifdef TEMPORARY_DTORS
896 #if __cplusplus < 201703L
897 // expected-warning@-3{{TRUE}}
898 #endif
899 #endif
900 }
901 };
902
903 C get();
904
905 bool is(C);
906
907
test(int coin)908 void test(int coin) {
909 // Here temporaries are being cleaned up after && is evaluated. There are two
910 // temporaries: the return value of get() and the elidable copy constructor
911 // of that return value into is(). According to the CFG, we need to cleanup
912 // both of them depending on whether the temporary corresponding to the
913 // return value of get() was initialized. However, we didn't track
914 // temporaries returned from functions, so we took the wrong branch.
915 coin && is(get()); // no-crash
916 if (coin) {
917 // FIXME: Why is destructor not inlined in C++17
918 clang_analyzer_eval(glob);
919 #ifdef TEMPORARY_DTORS
920 #if __cplusplus < 201703L
921 // expected-warning@-3{{TRUE}}
922 #else
923 // expected-warning@-5{{UNKNOWN}}
924 #endif
925 #else
926 // expected-warning@-8{{UNKNOWN}}
927 #endif
928 } else {
929 // The destructor is not called on this branch.
930 clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
931 }
932 }
933 } // namespace dont_forget_destructor_around_logical_op
934
935 #if __cplusplus >= 201103L
936 namespace temporary_list_crash {
937 class C {
938 public:
C()939 C() {}
~C()940 ~C() {}
941 };
942
test()943 void test() {
944 std::initializer_list<C>{C(), C()}; // no-crash
945 }
946 } // namespace temporary_list_crash
947 #endif // C++11
948
949 namespace implicit_constructor_conversion {
950 struct S {
951 int x;
Simplicit_constructor_conversion::S952 S(int x) : x(x) {}
~Simplicit_constructor_conversion::S953 ~S() {}
954 };
955
956 class C {
957 int x;
958
959 public:
C(const S & s)960 C(const S &s) : x(s.x) {}
~C()961 ~C() {}
getX() const962 int getX() const { return x; }
963 };
964
test()965 void test() {
966 const C &c1 = S(10);
967 clang_analyzer_eval(c1.getX() == 10);
968 #ifdef TEMPORARY_DTORS
969 // expected-warning@-2{{TRUE}}
970 #else
971 // expected-warning@-4{{UNKNOWN}}
972 #endif
973
974 S s = 20;
975 clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}
976
977 C c2 = s;
978 clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}
979 }
980 } // end namespace implicit_constructor_conversion
981
982 namespace pass_references_through {
983 class C {
984 public:
~C()985 ~C() {}
986 };
987
988 const C &foo1();
989 C &&foo2();
990
991 // In these examples the foo() expression has record type, not reference type.
992 // Don't try to figure out how to perform construction of the record here.
bar1()993 const C &bar1() { return foo1(); } // no-crash
bar2()994 C &&bar2() { return foo2(); } // no-crash
995 } // end namespace pass_references_through
996
997
998 namespace arguments {
999 int glob;
1000
1001 struct S {
1002 int x;
Sarguments::S1003 S(int x): x(x) {}
Sarguments::S1004 S(const S &s) : x(s.x) {}
~Sarguments::S1005 ~S() {}
1006
operator +arguments::S1007 S &operator+(S s) {
1008 glob = s.x;
1009 x += s.x;
1010 return *this;
1011 }
1012 };
1013
1014 class C {
1015 public:
bar3(S s)1016 virtual void bar3(S s) {}
1017 };
1018
1019 class D: public C {
1020 public:
D()1021 D() {}
bar3(S s)1022 virtual void bar3(S s) override { glob = s.x; }
1023 };
1024
bar1(S s)1025 void bar1(S s) {
1026 glob = s.x;
1027 }
1028
1029 // Record-typed calls are a different CFGStmt, let's see if we handle that
1030 // as well.
bar2(S s)1031 S bar2(S s) {
1032 glob = s.x;
1033 return S(3);
1034 }
1035
1036 void bar5(int, ...);
1037
foo(void (* bar4)(S))1038 void foo(void (*bar4)(S)) {
1039 bar1(S(1));
1040 clang_analyzer_eval(glob == 1);
1041 #ifdef TEMPORARY_DTORS
1042 // expected-warning@-2{{TRUE}}
1043 #else
1044 // expected-warning@-4{{UNKNOWN}}
1045 #endif
1046
1047 bar2(S(2));
1048 clang_analyzer_eval(glob == 2);
1049 #ifdef TEMPORARY_DTORS
1050 // expected-warning@-2{{TRUE}}
1051 #else
1052 // expected-warning@-4{{UNKNOWN}}
1053 #endif
1054
1055 C *c = new D();
1056 c->bar3(S(3));
1057 // FIXME: Should be TRUE.
1058 clang_analyzer_eval(glob == 3); // expected-warning{{UNKNOWN}}
1059 delete c;
1060
1061 // What if we've no idea what we're calling?
1062 bar4(S(4)); // no-crash
1063
1064 S(5) + S(6);
1065 clang_analyzer_eval(glob == 6);
1066 #ifdef TEMPORARY_DTORS
1067 // expected-warning@-2{{TRUE}}
1068 #else
1069 // expected-warning@-4{{UNKNOWN}}
1070 #endif
1071
1072 // Variadic functions. This will __builtin_trap() because you cannot pass
1073 // an object as a variadic argument.
1074 bar5(7, S(7)); // no-crash
1075 clang_analyzer_warnIfReached(); // no-warning
1076 }
1077 } // namespace arguments
1078
1079 namespace ctor_argument {
1080 // Stripped down unique_ptr<int>
1081 struct IntPtr {
IntPtrctor_argument::IntPtr1082 IntPtr(): i(new int) {}
IntPtrctor_argument::IntPtr1083 IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
~IntPtrctor_argument::IntPtr1084 ~IntPtr() { delete i; }
1085
1086 int *i;
1087 };
1088
1089 struct Foo {
1090 Foo(IntPtr);
1091 void bar();
1092
1093 IntPtr i;
1094 };
1095
bar()1096 void bar() {
1097 IntPtr ptr;
1098 int *i = ptr.i;
1099 Foo f(static_cast<IntPtr &&>(ptr));
1100 *i = 99; // no-warning
1101 }
1102 } // namespace ctor_argument
1103
1104 namespace operator_implicit_argument {
1105 struct S {
1106 bool x;
Soperator_implicit_argument::S1107 S(bool x): x(x) {}
operator booloperator_implicit_argument::S1108 operator bool() const { return x; }
1109 };
1110
foo()1111 void foo() {
1112 if (S(false)) {
1113 clang_analyzer_warnIfReached(); // no-warning
1114 }
1115 if (S(true)) {
1116 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
1117 }
1118 }
1119 } // namespace operator_implicit_argument
1120
1121
1122 #if __cplusplus >= 201103L
1123 namespace argument_lazy_bindings {
1124 int glob;
1125
1126 struct S {
1127 int x, y, z;
1128 };
1129
1130 struct T {
1131 S s;
1132 int w;
Targument_lazy_bindings::T1133 T(int w): s{5, 6, 7}, w(w) {}
1134 };
1135
foo(T t)1136 void foo(T t) {
1137 t.s = {1, 2, 3};
1138 glob = t.w;
1139 }
1140
bar()1141 void bar() {
1142 foo(T(4));
1143 clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
1144 }
1145 } // namespace argument_lazy_bindings
1146 #endif
1147
1148 namespace operator_argument_cleanup {
1149 struct S {
1150 S();
1151 };
1152
1153 class C {
1154 public:
1155 void operator=(S);
1156 };
1157
foo()1158 void foo() {
1159 C c;
1160 c = S(); // no-crash
1161 }
1162 } // namespace operator_argument_cleanup
1163
1164 namespace argument_decl_lookup {
1165 class C {};
1166 int foo(C);
bar(C c)1167 int bar(C c) { foo(c); }
foo(C c)1168 int foo(C c) {}
1169 } // namespace argument_decl_lookup
1170
1171 namespace argument_virtual_decl_lookup {
1172 class C {};
1173
1174 struct T {
1175 virtual void foo(C);
1176 };
1177
run()1178 void run() {
1179 T *t;
1180 t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}
1181 }
1182
1183 // This is after run() because the test is about picking the correct decl
1184 // for the parameter region, which should belong to the correct function decl,
1185 // and the non-definition decl should be found by direct lookup.
foo(C)1186 void T::foo(C) {}
1187 } // namespace argument_virtual_decl_lookup
1188
1189 namespace union_indirect_field_crash {
1190 union U {
1191 struct {
1192 int x;
1193 };
1194 };
1195
1196 template <typename T> class C {
1197 public:
foo() const1198 void foo() const {
1199 (void)(true ? U().x : 0);
1200 }
1201 };
1202
test()1203 void test() {
1204 C<int> c;
1205 c.foo();
1206 }
1207 } // namespace union_indirect_field_crash
1208
1209 namespace return_from_top_frame {
1210 struct S {
1211 int *p;
Sreturn_from_top_frame::S1212 S() { p = new int; }
Sreturn_from_top_frame::S1213 S(S &&s) : p(s.p) { s.p = 0; }
1214 ~S(); // Presumably releases 'p'.
1215 };
1216
foo()1217 S foo() {
1218 S s;
1219 return s;
1220 }
1221
bar1()1222 S bar1() {
1223 return foo(); // no-warning
1224 }
1225
bar2()1226 S bar2() {
1227 return S();
1228 }
1229
bar3(int coin)1230 S bar3(int coin) {
1231 return coin ? S() : foo(); // no-warning
1232 }
1233 } // namespace return_from_top_frame
1234
1235 #if __cplusplus >= 201103L
1236 namespace arguments_of_operators {
1237 struct S {
Sarguments_of_operators::S1238 S() {}
Sarguments_of_operators::S1239 S(const S &) {}
1240 };
1241
test()1242 void test() {
1243 int x = 0;
1244 auto foo = [](S s, int &y) { y = 1; };
1245 foo(S(), x);
1246 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
1247 }
1248 } // namespace arguments_of_operators
1249 #endif // __cplusplus >= 201103L
1250