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 {
31   Trivial(int x) : value(x) {}
32   int value;
33 };
34 
35 struct NonTrivial : public Trivial {
36   NonTrivial(int x) : Trivial(x) {}
37   ~NonTrivial();
38 };
39 
40 
41 Trivial getTrivial() {
42   return Trivial(42); // no-warning
43 }
44 
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 
50 NonTrivial getNonTrivial() {
51   return NonTrivial(42); // no-warning
52 }
53 
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 {
60     TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
61     int anotherValue;
62   };
63 
64   TrivialSubclass getTrivialSub() {
65     TrivialSubclass obj(1);
66     obj.value = 42;
67     obj.anotherValue = -42;
68     return obj;
69   }
70 
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 
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 {
92     Derived(int value) : Trivial(value), value2(-value) {}
93     int value2;
94   };
95 
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 {
109     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 {
117     HasCtorDtor(int x, int y) : x(x), y(y) {}
118     ~HasCtorDtor();
119     int x, y;
120   };
121 
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 
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 
156   void noReturnTemp(int *x) {
157     if (! x) NoReturnDtor();
158     *x = 47; // no warning
159   }
160 
161   void noReturnInline(int **x) {
162     NoReturnDtor();
163   }
164 
165   void callNoReturn() {
166     int *x;
167     noReturnInline(&x);
168     *x = 47; // no warning
169   }
170 
171   extern bool check(const NoReturnDtor &);
172 
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 
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
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
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
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
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
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
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
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 
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   }
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   }
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   }
296   void testTernaryTrueBranchReached(bool value) {
297     value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}
298             check(NoReturnDtor());
299   }
300   void testTernaryFalseBranchReached(bool value) {
301     value ? check(NoReturnDtor()) :
302             clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
303   }
304 
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 
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   }
321   void testRecursiveFramesStart() { testRecursiveFrames(false); }
322 
323   void testLambdas() {
324     []() { check(NoReturnDtor()); } != nullptr || check(Dtor());
325   }
326 
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 
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 
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 
358   void testBinaryOperatorShortcut(bool value) {
359     if (value) {
360       if (false && false && check(NoReturnDtor()) && true) {
361         clang_analyzer_eval(true);
362       }
363     }
364   }
365 
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 
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 
392   void testNoReturnInComplexCondition() {
393     check(Dtor()) &&
394         (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
395     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
396   }
397 
398   void testSequencingOfConditionalTempDtors(bool b) {
399     b || (check(Dtor()), check(NoReturnDtor()));
400     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
401   }
402 
403   void testSequencingOfConditionalTempDtors2(bool b) {
404     (b || check(Dtor())), check(NoReturnDtor());
405     clang_analyzer_warnIfReached();  // no warning, unreachable code
406   }
407 
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());
414   void testDefaultParameters() {
415     f();
416   }
417 
418   struct DefaultParam {
419     DefaultParam(int, const Dtor& d = Dtor());
420     ~DefaultParam();
421   };
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   }
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 
447     CtorWithNoReturnDtor(int x) {
448       clang_analyzer_checkInlined(false); // no-warning
449     }
450 
451     ~CtorWithNoReturnDtor() __attribute__((noreturn));
452   };
453 
454   void testDefaultContructorWithNoReturnDtor() {
455     CtorWithNoReturnDtor();
456     clang_analyzer_warnIfReached();  // no-warning
457   }
458 
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 
472     CtorWithNoReturnDtor2(int x) {
473       clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
474     }
475 
476     ~CtorWithNoReturnDtor2() __attribute__((noreturn));
477   };
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 };
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 
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 {
519     explicit A(int* p_) : p(p_) {}
520     int* p;
521   };
522 
523   extern void escape(const A*[]);
524   extern void check(int);
525 
526   void callEscape(const A& a) {
527     const A* args[] = { &a };
528     escape(args);
529   }
530 
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 
537   void set(const A*a[]) {
538     *a[0]->p = 47;
539   }
540 
541   void callSet(const A& a) {
542     const A* args[] = { &a };
543     set(args);
544   }
545 
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 {
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:
566   void m() {
567     mImpl();
568   }
569   virtual void mImpl() = 0;
570 };
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
580     }
581   }
582   const int &j;
583 };
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:
595   C(int x, int y) : x(x), y(y) {}
596   int getX() const { return x; }
597   int getY() const { return y; }
598   ~C() {}
599 };
600 
601 class D: public C {
602 public:
603   D() : C(1, 2) {}
604   D(const D &d): C(d.getX(), d.getY()) {}
605 };
606 
607 C returnTemporaryWithVariable() { C c(1, 2); return c; }
608 C returnTemporaryWithAnotherFunctionWithVariable() {
609   return returnTemporaryWithVariable();
610 }
611 C returnTemporaryWithCopyConstructionWithVariable() {
612   return C(returnTemporaryWithVariable());
613 }
614 
615 C returnTemporaryWithConstruction() { return C(1, 2); }
616 C returnTemporaryWithAnotherFunctionWithConstruction() {
617   return returnTemporaryWithConstruction();
618 }
619 C returnTemporaryWithCopyConstructionWithConstruction() {
620   return C(returnTemporaryWithConstruction());
621 }
622 
623 D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
624 D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
625   return returnTemporaryWithVariableAndNonTrivialCopy();
626 }
627 D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
628   return D(returnTemporaryWithVariableAndNonTrivialCopy());
629 }
630 
631 #if __cplusplus >= 201103L
632 C returnTemporaryWithBraces() { return {1, 2}; }
633 C returnTemporaryWithAnotherFunctionWithBraces() {
634   return returnTemporaryWithBraces();
635 }
636 C returnTemporaryWithCopyConstructionWithBraces() {
637   return C(returnTemporaryWithBraces());
638 }
639 #endif // C++11
640 
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:
701   C(int x) : x(x) {}
702   int getX() const { return x; }
703 };
704 
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:
715   C(int x) : x(x) {}
716   ~C() {}
717   int getX() const { return x; }
718 };
719 
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;
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; }
762 };
763 
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 
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 
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 
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 #if __cplusplus < 201703L
834     clang_analyzer_eval(y == 1); // expected-warning{{TRUE}}
835 #else
836     // FIXME: Destructor called twice in C++17?
837     clang_analyzer_eval(y == 2); // expected-warning{{TRUE}}
838 #endif
839     clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
840     clang_analyzer_eval(w == 0); // expected-warning{{TRUE}}
841 
842   } else {
843     clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
844     clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
845     clang_analyzer_eval(z == 1); // expected-warning{{TRUE}}
846 #if __cplusplus < 201703L
847     clang_analyzer_eval(w == 1); // expected-warning{{TRUE}}
848 #else
849     // FIXME: Destructor called twice in C++17?
850     clang_analyzer_eval(w == 2); // expected-warning{{TRUE}}
851 #endif
852   }
853 }
854 } // namespace test_match_constructors_and_destructors
855 
856 namespace destructors_for_return_values {
857 
858 class C {
859 public:
860   ~C() {
861     1 / 0; // expected-warning{{Division by zero}}
862   }
863 };
864 
865 C make();
866 
867 void testFloatingCall() {
868   make();
869   // Should have divided by zero in the destructor.
870   clang_analyzer_warnIfReached();
871 #ifndef TEMPORARY_DTORS
872     // expected-warning@-2{{REACHABLE}}
873 #endif
874 }
875 
876 void testLifetimeExtendedCall() {
877   {
878     const C &c = make();
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 
885 void testCopiedCall() {
886   {
887     C c = make();
888     // Should have elided the constructor/destructor for the temporary
889     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
890   }
891   // Should have divided by zero in the destructor.
892   clang_analyzer_warnIfReached(); // no-warning
893 }
894 } // namespace destructors_for_return_values
895 
896 namespace dont_forget_destructor_around_logical_op {
897 int glob;
898 
899 class C {
900 public:
901   ~C() {
902     glob = 1;
903     // FIXME: Why is destructor not inlined in C++17
904     clang_analyzer_checkInlined(true);
905 #ifdef TEMPORARY_DTORS
906 #if __cplusplus < 201703L
907     // expected-warning@-3{{TRUE}}
908 #endif
909 #endif
910   }
911 };
912 
913 C get();
914 
915 bool is(C);
916 
917 
918 void test(int coin) {
919   // Here temporaries are being cleaned up after && is evaluated. There are two
920   // temporaries: the return value of get() and the elidable copy constructor
921   // of that return value into is(). According to the CFG, we need to cleanup
922   // both of them depending on whether the temporary corresponding to the
923   // return value of get() was initialized. However, we didn't track
924   // temporaries returned from functions, so we took the wrong branch.
925   coin && is(get()); // no-crash
926   if (coin) {
927     // FIXME: Why is destructor not inlined in C++17
928     clang_analyzer_eval(glob);
929 #ifdef TEMPORARY_DTORS
930 #if __cplusplus < 201703L
931     // expected-warning@-3{{TRUE}}
932 #else
933     // expected-warning@-5{{UNKNOWN}}
934 #endif
935 #else
936     // expected-warning@-8{{UNKNOWN}}
937 #endif
938   } else {
939     // The destructor is not called on this branch.
940     clang_analyzer_eval(glob); // expected-warning{{UNKNOWN}}
941   }
942 }
943 } // namespace dont_forget_destructor_around_logical_op
944 
945 #if __cplusplus >= 201103L
946 namespace temporary_list_crash {
947 class C {
948 public:
949   C() {}
950   ~C() {}
951 };
952 
953 void test() {
954   std::initializer_list<C>{C(), C()}; // no-crash
955 }
956 } // namespace temporary_list_crash
957 #endif // C++11
958 
959 namespace implicit_constructor_conversion {
960 struct S {
961   int x;
962   S(int x) : x(x) {}
963   ~S() {}
964 };
965 
966 class C {
967   int x;
968 
969 public:
970   C(const S &s) : x(s.x) {}
971   ~C() {}
972   int getX() const { return x; }
973 };
974 
975 void test() {
976   const C &c1 = S(10);
977   clang_analyzer_eval(c1.getX() == 10);
978 #ifdef TEMPORARY_DTORS
979   // expected-warning@-2{{TRUE}}
980 #else
981   // expected-warning@-4{{UNKNOWN}}
982 #endif
983 
984   S s = 20;
985   clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}
986 
987   C c2 = s;
988   clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}
989 }
990 } // end namespace implicit_constructor_conversion
991 
992 namespace pass_references_through {
993 class C {
994 public:
995   ~C() {}
996 };
997 
998 const C &foo1();
999 C &&foo2();
1000 
1001 // In these examples the foo() expression has record type, not reference type.
1002 // Don't try to figure out how to perform construction of the record here.
1003 const C &bar1() { return foo1(); } // no-crash
1004 C &&bar2() { return foo2(); } // no-crash
1005 } // end namespace pass_references_through
1006 
1007 
1008 namespace arguments {
1009 int glob;
1010 
1011 struct S {
1012   int x;
1013   S(int x): x(x) {}
1014   S(const S &s) : x(s.x) {}
1015   ~S() {}
1016 
1017   S &operator+(S s) {
1018     glob = s.x;
1019     x += s.x;
1020     return *this;
1021   }
1022 };
1023 
1024 class C {
1025 public:
1026   virtual void bar3(S s) {}
1027 };
1028 
1029 class D: public C {
1030 public:
1031   D() {}
1032   virtual void bar3(S s) override { glob = s.x; }
1033 };
1034 
1035 void bar1(S s) {
1036   glob = s.x;
1037 }
1038 
1039 // Record-typed calls are a different CFGStmt, let's see if we handle that
1040 // as well.
1041 S bar2(S s) {
1042   glob = s.x;
1043   return S(3);
1044 }
1045 
1046 void bar5(int, ...);
1047 
1048 void foo(void (*bar4)(S)) {
1049   bar1(S(1));
1050   clang_analyzer_eval(glob == 1);
1051 #ifdef TEMPORARY_DTORS
1052   // expected-warning@-2{{TRUE}}
1053 #else
1054   // expected-warning@-4{{UNKNOWN}}
1055 #endif
1056 
1057   bar2(S(2));
1058   // FIXME: Why are we losing information in C++17?
1059   clang_analyzer_eval(glob == 2);
1060 #ifdef TEMPORARY_DTORS
1061 #if __cplusplus < 201703L
1062   // expected-warning@-3{{TRUE}}
1063 #else
1064   // expected-warning@-5{{UNKNOWN}}
1065 #endif
1066 #else
1067   // expected-warning@-8{{UNKNOWN}}
1068 #endif
1069 
1070   C *c = new D();
1071   c->bar3(S(3));
1072   // FIXME: Should be TRUE.
1073   clang_analyzer_eval(glob == 3); // expected-warning{{UNKNOWN}}
1074   delete c;
1075 
1076   // What if we've no idea what we're calling?
1077   bar4(S(4)); // no-crash
1078 
1079   S(5) + S(6);
1080   clang_analyzer_eval(glob == 6);
1081 #ifdef TEMPORARY_DTORS
1082   // expected-warning@-2{{TRUE}}
1083 #else
1084   // expected-warning@-4{{UNKNOWN}}
1085 #endif
1086 
1087   // Variadic functions. This will __builtin_trap() because you cannot pass
1088   // an object as a variadic argument.
1089   bar5(7, S(7)); // no-crash
1090   clang_analyzer_warnIfReached(); // no-warning
1091 }
1092 } // namespace arguments
1093 
1094 namespace ctor_argument {
1095 // Stripped down unique_ptr<int>
1096 struct IntPtr {
1097   IntPtr(): i(new int) {}
1098   IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
1099   ~IntPtr() { delete i; }
1100 
1101   int *i;
1102 };
1103 
1104 struct Foo {
1105   Foo(IntPtr);
1106   void bar();
1107 
1108   IntPtr i;
1109 };
1110 
1111 void bar() {
1112   IntPtr ptr;
1113   int *i = ptr.i;
1114   Foo f(static_cast<IntPtr &&>(ptr));
1115   *i = 99; // no-warning
1116 }
1117 } // namespace ctor_argument
1118 
1119 namespace operator_implicit_argument {
1120 struct S {
1121   bool x;
1122   S(bool x): x(x) {}
1123   operator bool() const { return x; }
1124 };
1125 
1126 void foo() {
1127   if (S(false)) {
1128     clang_analyzer_warnIfReached(); // no-warning
1129   }
1130   if (S(true)) {
1131     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
1132   }
1133 }
1134 } // namespace operator_implicit_argument
1135 
1136 
1137 #if __cplusplus >= 201103L
1138 namespace argument_lazy_bindings {
1139 int glob;
1140 
1141 struct S {
1142   int x, y, z;
1143 };
1144 
1145 struct T {
1146   S s;
1147   int w;
1148   T(int w): s{5, 6, 7}, w(w) {}
1149 };
1150 
1151 void foo(T t) {
1152   t.s = {1, 2, 3};
1153   glob = t.w;
1154 }
1155 
1156 void bar() {
1157   foo(T(4));
1158   clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
1159 }
1160 } // namespace argument_lazy_bindings
1161 #endif
1162 
1163 namespace operator_argument_cleanup {
1164 struct S {
1165   S();
1166 };
1167 
1168 class C {
1169 public:
1170   void operator=(S);
1171 };
1172 
1173 void foo() {
1174   C c;
1175   c = S(); // no-crash
1176 }
1177 } // namespace operator_argument_cleanup
1178 
1179 namespace argument_decl_lookup {
1180 class C {};
1181 int foo(C);
1182 int bar(C c) { foo(c); }
1183 int foo(C c) {}
1184 } // namespace argument_decl_lookup
1185 
1186 namespace argument_virtual_decl_lookup {
1187 class C {};
1188 
1189 struct T  {
1190   virtual void foo(C);
1191 };
1192 
1193 void run() {
1194   T *t;
1195   t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}
1196 }
1197 
1198 // This is after run() because the test is about picking the correct decl
1199 // for the parameter region, which should belong to the correct function decl,
1200 // and the non-definition decl should be found by direct lookup.
1201 void T::foo(C) {}
1202 } // namespace argument_virtual_decl_lookup
1203 
1204 namespace union_indirect_field_crash {
1205 union U {
1206   struct {
1207     int x;
1208   };
1209 };
1210 
1211 template <typename T> class C {
1212 public:
1213   void foo() const {
1214     (void)(true ? U().x : 0);
1215   }
1216 };
1217 
1218 void test() {
1219   C<int> c;
1220   c.foo();
1221 }
1222 } // namespace union_indirect_field_crash
1223 
1224 namespace return_from_top_frame {
1225 struct S {
1226   int *p;
1227   S() { p = new int; }
1228   S(S &&s) : p(s.p) { s.p = 0; }
1229   ~S();  // Presumably releases 'p'.
1230 };
1231 
1232 S foo() {
1233   S s;
1234   return s;
1235 }
1236 
1237 S bar1() {
1238   return foo(); // no-warning
1239 }
1240 
1241 S bar2() {
1242   return S();
1243 }
1244 
1245 S bar3(int coin) {
1246   return coin ? S() : foo(); // no-warning
1247 }
1248 } // namespace return_from_top_frame
1249