[AMDGPU][AsmParser][NFC] Get rid of custom default operand handlers.
[llvm-project.git] / clang / test / Analysis / temporaries.cpp
blob1c0ac38160c2d235e2c439bd62a717ff62de6309
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
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
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
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
24 extern bool clang_analyzer_eval(bool);
25 extern bool clang_analyzer_warnIfReached();
26 void clang_analyzer_checkInlined(bool);
28 #include "Inputs/system-header-simulator-cxx.h"
30 struct Trivial {
31 Trivial(int x) : value(x) {}
32 int value;
35 struct NonTrivial : public Trivial {
36 NonTrivial(int x) : Trivial(x) {}
37 ~NonTrivial();
41 Trivial getTrivial() {
42 return Trivial(42); // no-warning
45 const Trivial &getTrivialRef() {
46 return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
50 NonTrivial getNonTrivial() {
51 return NonTrivial(42); // no-warning
54 const NonTrivial &getNonTrivialRef() {
55 return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
58 namespace rdar13265460 {
59 struct TrivialSubclass : public Trivial {
60 TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
61 int anotherValue;
64 TrivialSubclass getTrivialSub() {
65 TrivialSubclass obj(1);
66 obj.value = 42;
67 obj.anotherValue = -42;
68 return obj;
71 void testImmediate() {
72 TrivialSubclass obj = getTrivialSub();
74 clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
75 clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
77 clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
78 clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
81 void testMaterializeTemporaryExpr() {
82 const TrivialSubclass &ref = getTrivialSub();
83 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
85 const Trivial &baseRef = getTrivialSub();
86 clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
90 namespace rdar13281951 {
91 struct Derived : public Trivial {
92 Derived(int value) : Trivial(value), value2(-value) {}
93 int value2;
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}}
104 namespace compound_literals {
105 struct POD {
106 int x, y;
108 struct HasCtor {
109 HasCtor(int x, int y) : x(x), y(y) {}
110 int x, y;
112 struct HasDtor {
113 int x, y;
114 ~HasDtor();
116 struct HasCtorDtor {
117 HasCtorDtor(int x, int y) : x(x), y(y) {}
118 ~HasCtorDtor();
119 int x, y;
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}}
126 #if __cplusplus >= 201103L
127 clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
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
136 namespace destructors {
137 struct Dtor {
138 ~Dtor();
140 extern bool coin();
141 extern bool check(const Dtor &);
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();
151 #ifdef TEMPORARY_DTORS
152 struct NoReturnDtor {
153 ~NoReturnDtor() __attribute__((noreturn));
156 void noReturnTemp(int *x) {
157 if (! x) NoReturnDtor();
158 *x = 47; // no warning
161 void noReturnInline(int **x) {
162 NoReturnDtor();
165 void callNoReturn() {
166 int *x;
167 noReturnInline(&x);
168 *x = 47; // no warning
171 extern bool check(const NoReturnDtor &);
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
181 void testConsistencyTernary(int i) {
182 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
184 clang_analyzer_eval(true); // expected-warning{{TRUE}}
186 if (i != 5)
187 return;
189 (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
191 clang_analyzer_eval(true); // no warning, unreachable code
194 // Regression test: we used to assert here.
195 // PR16664 and PR18159
196 void testConsistencyNested(int i) {
197 extern bool compute(bool);
199 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
200 clang_analyzer_eval(true); // expected-warning{{TRUE}}
202 if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
203 clang_analyzer_eval(true); // expected-warning{{TRUE}}
205 if (i != 5)
206 return;
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}}
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
223 // PR16664 and PR18159
224 void testConsistencyNestedSimple(bool value) {
225 if (value) {
226 if (!value || check(NoReturnDtor())) {
227 clang_analyzer_eval(true); // no warning, unreachable code
232 // PR16664 and PR18159
233 void testConsistencyNestedComplex(bool value) {
234 if (value) {
235 if (!value || !value || check(NoReturnDtor())) {
236 clang_analyzer_eval(true); // no warning, unreachable code
241 // PR16664 and PR18159
242 void testConsistencyNestedWarning(bool value) {
243 if (value) {
244 if (!value || value || check(NoReturnDtor())) {
245 clang_analyzer_eval(true); // expected-warning{{TRUE}}
249 // PR16664 and PR18159
250 void testConsistencyNestedComplexMidBranch(bool value) {
251 if (value) {
252 if (!value || !value || check(NoReturnDtor()) || value) {
253 clang_analyzer_eval(true); // no warning, unreachable code
258 // PR16664 and PR18159
259 void testConsistencyNestedComplexNestedBranch(bool value) {
260 if (value) {
261 if (!value || (!value || check(NoReturnDtor()) || value)) {
262 clang_analyzer_eval(true); // no warning, unreachable code
267 // PR16664 and PR18159
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
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
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
290 void testTernaryIgnoreNoreturnBranch(bool value) {
291 if (value) {
292 bool b = !value && !value ? check(NoReturnDtor()) : true;
293 clang_analyzer_eval(true); // expected-warning{{TRUE}}
296 void testTernaryTrueBranchReached(bool value) {
297 value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}
298 check(NoReturnDtor());
300 void testTernaryFalseBranchReached(bool value) {
301 value ? check(NoReturnDtor()) :
302 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
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
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}}
321 void testRecursiveFramesStart() { testRecursiveFrames(false); }
323 void testLambdas() {
324 []() { check(NoReturnDtor()); } != nullptr || check(Dtor());
327 void testGnuExpressionStatements(int v) {
328 ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;
329 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
331 ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;
332 clang_analyzer_warnIfReached(); // no warning, unreachable code
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}}
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
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
358 void testBinaryOperatorShortcut(bool value) {
359 if (value) {
360 if (false && false && check(NoReturnDtor()) && true) {
361 clang_analyzer_eval(true);
366 void testIfAtEndOfLoop() {
367 int y = 0;
368 while (true) {
369 if (y > 0) {
370 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
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());
379 void testTernaryAtEndOfLoop() {
380 int y = 0;
381 while (true) {
382 if (y > 0) {
383 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
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());
392 void testNoReturnInComplexCondition() {
393 check(Dtor()) &&
394 (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
395 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
398 void testSequencingOfConditionalTempDtors(bool b) {
399 b || (check(Dtor()), check(NoReturnDtor()));
400 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
403 void testSequencingOfConditionalTempDtors2(bool b) {
404 (b || check(Dtor())), check(NoReturnDtor());
405 clang_analyzer_warnIfReached(); // no warning, unreachable code
408 void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {
409 b || (check(Dtor()) + check(NoReturnDtor()));
410 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
413 void f(Dtor d = Dtor());
414 void testDefaultParameters() {
415 f();
418 struct DefaultParam {
419 DefaultParam(int, const Dtor& d = Dtor());
420 ~DefaultParam();
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);
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);
438 #else // !TEMPORARY_DTORS
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.
444 struct CtorWithNoReturnDtor {
445 CtorWithNoReturnDtor() = default;
447 CtorWithNoReturnDtor(int x) {
448 clang_analyzer_checkInlined(false); // no-warning
451 ~CtorWithNoReturnDtor() __attribute__((noreturn));
454 void testDefaultContructorWithNoReturnDtor() {
455 CtorWithNoReturnDtor();
456 clang_analyzer_warnIfReached(); // no-warning
459 void testLifeExtensionWithNoReturnDtor() {
460 const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();
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
468 #if __cplusplus >= 201103L
469 struct CtorWithNoReturnDtor2 {
470 CtorWithNoReturnDtor2() = default;
472 CtorWithNoReturnDtor2(int x) {
473 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
476 ~CtorWithNoReturnDtor2() __attribute__((noreturn));
478 CtorWithNoReturnDtor2 returnNoReturnDtor() {
479 return {1}; // no-crash
481 #endif
483 #endif // TEMPORARY_DTORS
486 namespace default_param_elided_destructors {
487 struct a {
488 ~a();
490 struct F {
491 a d;
492 F(char *, a = a());
494 void g() {
495 char h[1];
496 for (int i = 0;;)
497 F j(i ? j : h);
499 } // namespace default_param_elided_destructors
501 void testStaticMaterializeTemporaryExpr() {
502 static const Trivial &ref = getTrivial();
503 clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
505 static const Trivial &directRef = Trivial(42);
506 clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
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}}
512 thread_local static const Trivial &threadDirectRef = Trivial(42);
513 clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
514 #endif
517 namespace PR16629 {
518 struct A {
519 explicit A(int* p_) : p(p_) {}
520 int* p;
523 extern void escape(const A*[]);
524 extern void check(int);
526 void callEscape(const A& a) {
527 const A* args[] = { &a };
528 escape(args);
531 void testNoWarning() {
532 int x;
533 callEscape(A(&x));
534 check(x); // Analyzer used to give a "x is uninitialized warning" here
537 void set(const A*a[]) {
538 *a[0]->p = 47;
541 void callSet(const A& a) {
542 const A* args[] = { &a };
543 set(args);
546 void testConsistency() {
547 int x;
548 callSet(A(&x));
549 clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
553 namespace PR32088 {
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);
563 namespace CopyToTemporaryCorrectly {
564 class Super {
565 public:
566 void m() {
567 mImpl();
569 virtual void mImpl() = 0;
571 class Sub : public Super {
572 public:
573 Sub(const int &p) : j(p) {}
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
582 const int &j;
584 void run() {
585 int i = 22;
586 Sub(i).m();
590 namespace test_return_temporary {
591 class C {
592 int x, y;
594 public:
595 C(int x, int y) : x(x), y(y) {}
596 int getX() const { return x; }
597 int getY() const { return y; }
598 ~C() {}
601 class D: public C {
602 public:
603 D() : C(1, 2) {}
604 D(const D &d): C(d.getX(), d.getY()) {}
607 C returnTemporaryWithVariable() { C c(1, 2); return c; }
608 C returnTemporaryWithAnotherFunctionWithVariable() {
609 return returnTemporaryWithVariable();
611 C returnTemporaryWithCopyConstructionWithVariable() {
612 return C(returnTemporaryWithVariable());
615 C returnTemporaryWithConstruction() { return C(1, 2); }
616 C returnTemporaryWithAnotherFunctionWithConstruction() {
617 return returnTemporaryWithConstruction();
619 C returnTemporaryWithCopyConstructionWithConstruction() {
620 return C(returnTemporaryWithConstruction());
623 D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
624 D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
625 return returnTemporaryWithVariableAndNonTrivialCopy();
627 D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
628 return D(returnTemporaryWithVariableAndNonTrivialCopy());
631 #if __cplusplus >= 201103L
632 C returnTemporaryWithBraces() { return {1, 2}; }
633 C returnTemporaryWithAnotherFunctionWithBraces() {
634 return returnTemporaryWithBraces();
636 C returnTemporaryWithCopyConstructionWithBraces() {
637 return C(returnTemporaryWithBraces());
639 #endif // C++11
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}}
646 C c2 = returnTemporaryWithAnotherFunctionWithVariable();
647 clang_analyzer_eval(c2.getX() == 1); // expected-warning{{TRUE}}
648 clang_analyzer_eval(c2.getY() == 2); // expected-warning{{TRUE}}
650 C c3 = returnTemporaryWithCopyConstructionWithVariable();
651 clang_analyzer_eval(c3.getX() == 1); // expected-warning{{TRUE}}
652 clang_analyzer_eval(c3.getY() == 2); // expected-warning{{TRUE}}
654 C c4 = returnTemporaryWithConstruction();
655 clang_analyzer_eval(c4.getX() == 1); // expected-warning{{TRUE}}
656 clang_analyzer_eval(c4.getY() == 2); // expected-warning{{TRUE}}
658 C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
659 clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
660 clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
662 C c6 = returnTemporaryWithCopyConstructionWithConstruction();
663 clang_analyzer_eval(c5.getX() == 1); // expected-warning{{TRUE}}
664 clang_analyzer_eval(c5.getY() == 2); // expected-warning{{TRUE}}
666 #if __cplusplus >= 201103L
668 C c7 = returnTemporaryWithBraces();
669 clang_analyzer_eval(c7.getX() == 1); // expected-warning{{TRUE}}
670 clang_analyzer_eval(c7.getY() == 2); // expected-warning{{TRUE}}
672 C c8 = returnTemporaryWithAnotherFunctionWithBraces();
673 clang_analyzer_eval(c8.getX() == 1); // expected-warning{{TRUE}}
674 clang_analyzer_eval(c8.getY() == 2); // expected-warning{{TRUE}}
676 C c9 = returnTemporaryWithCopyConstructionWithBraces();
677 clang_analyzer_eval(c9.getX() == 1); // expected-warning{{TRUE}}
678 clang_analyzer_eval(c9.getY() == 2); // expected-warning{{TRUE}}
680 #endif // C++11
682 D d1 = returnTemporaryWithVariableAndNonTrivialCopy();
683 clang_analyzer_eval(d1.getX() == 1); // expected-warning{{TRUE}}
684 clang_analyzer_eval(d1.getY() == 2); // expected-warning{{TRUE}}
686 D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy();
687 clang_analyzer_eval(d2.getX() == 1); // expected-warning{{TRUE}}
688 clang_analyzer_eval(d2.getY() == 2); // expected-warning{{TRUE}}
690 D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
691 clang_analyzer_eval(d3.getX() == 1); // expected-warning{{TRUE}}
692 clang_analyzer_eval(d3.getY() == 2); // expected-warning{{TRUE}}
694 } // namespace test_return_temporary
697 namespace test_temporary_object_expr_without_dtor {
698 class C {
699 int x;
700 public:
701 C(int x) : x(x) {}
702 int getX() const { return x; }
705 void test() {
706 clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
710 namespace test_temporary_object_expr_with_dtor {
711 class C {
712 int x;
714 public:
715 C(int x) : x(x) {}
716 ~C() {}
717 int getX() const { return x; }
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
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
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}}
753 } // namespace test_temporary_object_expr
755 namespace test_match_constructors_and_destructors {
756 class C {
757 public:
758 int &x, &y;
759 C(int &_x, int &_y) : x(_x), y(_y) { ++x; }
760 C(const C &c): x(c.x), y(c.y) { ++x; }
761 ~C() { ++y; }
764 void test_simple_temporary() {
765 int x = 0, y = 0;
767 const C &c = C(x, y);
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
781 void test_simple_temporary_with_copy() {
782 int x = 0, y = 0;
784 C c = C(x, y);
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}}
791 void test_ternary_temporary(int coin) {
792 int x = 0, y = 0, z = 0, w = 0;
794 const C &c = coin ? C(x, y) : C(z, w);
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}}
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
825 void test_ternary_temporary_with_copy(int coin) {
826 int x = 0, y = 0, z = 0, w = 0;
828 C c = coin ? C(x, y) : C(z, w);
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}}
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}}
844 } // namespace test_match_constructors_and_destructors
846 namespace destructors_for_return_values {
848 class C {
849 public:
850 ~C() {
851 1 / 0; // expected-warning{{Division by zero}}
855 C make();
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
866 void testLifetimeExtendedCall() {
868 const C &c = make();
869 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
871 // Should have divided by zero in the destructor.
872 clang_analyzer_warnIfReached(); // no-warning
875 void testCopiedCall() {
877 C c = make();
878 // Should have elided the constructor/destructor for the temporary
879 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
881 // Should have divided by zero in the destructor.
882 clang_analyzer_warnIfReached(); // no-warning
884 } // namespace destructors_for_return_values
886 namespace dont_forget_destructor_around_logical_op {
887 int glob;
889 class C {
890 public:
891 ~C() {
892 glob = 1;
893 clang_analyzer_checkInlined(true);
894 #ifdef TEMPORARY_DTORS
895 // expected-warning@-2{{TRUE}}
896 #endif
900 C get();
902 bool is(C);
905 void test(int coin) {
906 // Here temporaries are being cleaned up after && is evaluated. There are two
907 // temporaries: the return value of get() and the elidable copy constructor
908 // of that return value into is(). According to the CFG, we need to cleanup
909 // both of them depending on whether the temporary corresponding to the
910 // return value of get() was initialized. However, we didn't track
911 // temporaries returned from functions, so we took the wrong branch.
912 coin && is(get()); // no-crash
913 if (coin) {
914 clang_analyzer_eval(glob);
915 #ifdef TEMPORARY_DTORS
916 // expected-warning@-2{{TRUE}}
917 #else
918 // expected-warning@-4{{UNKNOWN}}
919 #endif
920 } else {
921 // The destructor is not called on this branch.
922 clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
925 } // namespace dont_forget_destructor_around_logical_op
927 #if __cplusplus >= 201103L
928 namespace temporary_list_crash {
929 class C {
930 public:
931 C() {}
932 ~C() {}
935 void test() {
936 std::initializer_list<C>{C(), C()}; // no-crash
938 } // namespace temporary_list_crash
939 #endif // C++11
941 namespace implicit_constructor_conversion {
942 struct S {
943 int x;
944 S(int x) : x(x) {}
945 ~S() {}
948 class C {
949 int x;
951 public:
952 C(const S &s) : x(s.x) {}
953 ~C() {}
954 int getX() const { return x; }
957 void test() {
958 const C &c1 = S(10);
959 clang_analyzer_eval(c1.getX() == 10);
960 #ifdef TEMPORARY_DTORS
961 // expected-warning@-2{{TRUE}}
962 #else
963 // expected-warning@-4{{UNKNOWN}}
964 #endif
966 S s = 20;
967 clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}
969 C c2 = s;
970 clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}
972 } // end namespace implicit_constructor_conversion
974 namespace pass_references_through {
975 class C {
976 public:
977 ~C() {}
980 const C &foo1();
981 C &&foo2();
983 // In these examples the foo() expression has record type, not reference type.
984 // Don't try to figure out how to perform construction of the record here.
985 const C &bar1() { return foo1(); } // no-crash
986 C &&bar2() { return foo2(); } // no-crash
987 } // end namespace pass_references_through
990 namespace arguments {
991 int glob;
993 struct S {
994 int x;
995 S(int x): x(x) {}
996 S(const S &s) : x(s.x) {}
997 ~S() {}
999 S &operator+(S s) {
1000 glob = s.x;
1001 x += s.x;
1002 return *this;
1006 class C {
1007 public:
1008 virtual void bar3(S s) {}
1011 class D: public C {
1012 public:
1013 D() {}
1014 virtual void bar3(S s) override { glob = s.x; }
1017 void bar1(S s) {
1018 glob = s.x;
1021 // Record-typed calls are a different CFGStmt, let's see if we handle that
1022 // as well.
1023 S bar2(S s) {
1024 glob = s.x;
1025 return S(3);
1028 void bar5(int, ...);
1030 void foo(void (*bar4)(S)) {
1031 bar1(S(1));
1032 clang_analyzer_eval(glob == 1);
1033 #ifdef TEMPORARY_DTORS
1034 // expected-warning@-2{{TRUE}}
1035 #else
1036 // expected-warning@-4{{UNKNOWN}}
1037 #endif
1039 bar2(S(2));
1040 clang_analyzer_eval(glob == 2);
1041 #ifdef TEMPORARY_DTORS
1042 // expected-warning@-2{{TRUE}}
1043 #else
1044 // expected-warning@-4{{UNKNOWN}}
1045 #endif
1047 C *c = new D();
1048 c->bar3(S(3));
1049 // FIXME: Should be TRUE.
1050 clang_analyzer_eval(glob == 3); // expected-warning{{UNKNOWN}}
1051 delete c;
1053 // What if we've no idea what we're calling?
1054 bar4(S(4)); // no-crash
1056 S(5) + S(6);
1057 clang_analyzer_eval(glob == 6);
1058 #ifdef TEMPORARY_DTORS
1059 // expected-warning@-2{{TRUE}}
1060 #else
1061 // expected-warning@-4{{UNKNOWN}}
1062 #endif
1064 // Variadic functions. This will __builtin_trap() because you cannot pass
1065 // an object as a variadic argument.
1066 bar5(7, S(7)); // no-crash
1067 clang_analyzer_warnIfReached(); // no-warning
1069 } // namespace arguments
1071 namespace ctor_argument {
1072 // Stripped down unique_ptr<int>
1073 struct IntPtr {
1074 IntPtr(): i(new int) {}
1075 IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
1076 ~IntPtr() { delete i; }
1078 int *i;
1081 struct Foo {
1082 Foo(IntPtr);
1083 void bar();
1085 IntPtr i;
1088 void bar() {
1089 IntPtr ptr;
1090 int *i = ptr.i;
1091 Foo f(static_cast<IntPtr &&>(ptr));
1092 *i = 99; // no-warning
1094 } // namespace ctor_argument
1096 namespace operator_implicit_argument {
1097 struct S {
1098 bool x;
1099 S(bool x): x(x) {}
1100 operator bool() const { return x; }
1103 void foo() {
1104 if (S(false)) {
1105 clang_analyzer_warnIfReached(); // no-warning
1107 if (S(true)) {
1108 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
1111 } // namespace operator_implicit_argument
1114 #if __cplusplus >= 201103L
1115 namespace argument_lazy_bindings {
1116 int glob;
1118 struct S {
1119 int x, y, z;
1122 struct T {
1123 S s;
1124 int w;
1125 T(int w): s{5, 6, 7}, w(w) {}
1128 void foo(T t) {
1129 t.s = {1, 2, 3};
1130 glob = t.w;
1133 void bar() {
1134 foo(T(4));
1135 clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
1137 } // namespace argument_lazy_bindings
1138 #endif
1140 namespace operator_argument_cleanup {
1141 struct S {
1142 S();
1145 class C {
1146 public:
1147 void operator=(S);
1150 void foo() {
1151 C c;
1152 c = S(); // no-crash
1154 } // namespace operator_argument_cleanup
1156 namespace argument_decl_lookup {
1157 class C {};
1158 int foo(C);
1159 int bar(C c) { foo(c); }
1160 int foo(C c) {}
1161 } // namespace argument_decl_lookup
1163 namespace argument_virtual_decl_lookup {
1164 class C {};
1166 struct T {
1167 virtual void foo(C);
1170 void run() {
1171 T *t;
1172 t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}
1175 // This is after run() because the test is about picking the correct decl
1176 // for the parameter region, which should belong to the correct function decl,
1177 // and the non-definition decl should be found by direct lookup.
1178 void T::foo(C) {}
1179 } // namespace argument_virtual_decl_lookup
1181 namespace union_indirect_field_crash {
1182 union U {
1183 struct {
1184 int x;
1188 template <typename T> class C {
1189 public:
1190 void foo() const {
1191 (void)(true ? U().x : 0);
1195 void test() {
1196 C<int> c;
1197 c.foo();
1199 } // namespace union_indirect_field_crash
1201 namespace return_from_top_frame {
1202 struct S {
1203 int *p;
1204 S() { p = new int; }
1205 S(S &&s) : p(s.p) { s.p = 0; }
1206 ~S(); // Presumably releases 'p'.
1209 S foo() {
1210 S s;
1211 return s;
1214 S bar1() {
1215 return foo(); // no-warning
1218 S bar2() {
1219 return S();
1222 S bar3(int coin) {
1223 return coin ? S() : foo(); // no-warning
1225 } // namespace return_from_top_frame
1227 #if __cplusplus >= 201103L
1228 namespace arguments_of_operators {
1229 struct S {
1230 S() {}
1231 S(const S &) {}
1234 void test() {
1235 int x = 0;
1236 auto foo = [](S s, int &y) { y = 1; };
1237 foo(S(), x);
1238 clang_analyzer_eval(x == 1); // expected-warning{{TRUE}}
1240 } // namespace arguments_of_operators
1241 #endif // __cplusplus >= 201103L