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     clang_analyzer_checkInlined(true);
894 #ifdef TEMPORARY_DTORS
895     // expected-warning@-2{{TRUE}}
896 #endif
897   }
898 };
899 
900 C get();
901 
902 bool is(C);
903 
904 
test(int coin)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}}
923   }
924 }
925 } // namespace dont_forget_destructor_around_logical_op
926 
927 #if __cplusplus >= 201103L
928 namespace temporary_list_crash {
929 class C {
930 public:
C()931   C() {}
~C()932   ~C() {}
933 };
934 
test()935 void test() {
936   std::initializer_list<C>{C(), C()}; // no-crash
937 }
938 } // namespace temporary_list_crash
939 #endif // C++11
940 
941 namespace implicit_constructor_conversion {
942 struct S {
943   int x;
Simplicit_constructor_conversion::S944   S(int x) : x(x) {}
~Simplicit_constructor_conversion::S945   ~S() {}
946 };
947 
948 class C {
949   int x;
950 
951 public:
C(const S & s)952   C(const S &s) : x(s.x) {}
~C()953   ~C() {}
getX() const954   int getX() const { return x; }
955 };
956 
test()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
965 
966   S s = 20;
967   clang_analyzer_eval(s.x == 20); // expected-warning{{TRUE}}
968 
969   C c2 = s;
970   clang_analyzer_eval(c2.getX() == 20); // expected-warning{{TRUE}}
971 }
972 } // end namespace implicit_constructor_conversion
973 
974 namespace pass_references_through {
975 class C {
976 public:
~C()977   ~C() {}
978 };
979 
980 const C &foo1();
981 C &&foo2();
982 
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.
bar1()985 const C &bar1() { return foo1(); } // no-crash
bar2()986 C &&bar2() { return foo2(); } // no-crash
987 } // end namespace pass_references_through
988 
989 
990 namespace arguments {
991 int glob;
992 
993 struct S {
994   int x;
Sarguments::S995   S(int x): x(x) {}
Sarguments::S996   S(const S &s) : x(s.x) {}
~Sarguments::S997   ~S() {}
998 
operator +arguments::S999   S &operator+(S s) {
1000     glob = s.x;
1001     x += s.x;
1002     return *this;
1003   }
1004 };
1005 
1006 class C {
1007 public:
bar3(S s)1008   virtual void bar3(S s) {}
1009 };
1010 
1011 class D: public C {
1012 public:
D()1013   D() {}
bar3(S s)1014   virtual void bar3(S s) override { glob = s.x; }
1015 };
1016 
bar1(S s)1017 void bar1(S s) {
1018   glob = s.x;
1019 }
1020 
1021 // Record-typed calls are a different CFGStmt, let's see if we handle that
1022 // as well.
bar2(S s)1023 S bar2(S s) {
1024   glob = s.x;
1025   return S(3);
1026 }
1027 
1028 void bar5(int, ...);
1029 
foo(void (* bar4)(S))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
1038 
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
1046 
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;
1052 
1053   // What if we've no idea what we're calling?
1054   bar4(S(4)); // no-crash
1055 
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
1063 
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
1068 }
1069 } // namespace arguments
1070 
1071 namespace ctor_argument {
1072 // Stripped down unique_ptr<int>
1073 struct IntPtr {
IntPtrctor_argument::IntPtr1074   IntPtr(): i(new int) {}
IntPtrctor_argument::IntPtr1075   IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
~IntPtrctor_argument::IntPtr1076   ~IntPtr() { delete i; }
1077 
1078   int *i;
1079 };
1080 
1081 struct Foo {
1082   Foo(IntPtr);
1083   void bar();
1084 
1085   IntPtr i;
1086 };
1087 
bar()1088 void bar() {
1089   IntPtr ptr;
1090   int *i = ptr.i;
1091   Foo f(static_cast<IntPtr &&>(ptr));
1092   *i = 99; // no-warning
1093 }
1094 } // namespace ctor_argument
1095 
1096 namespace operator_implicit_argument {
1097 struct S {
1098   bool x;
Soperator_implicit_argument::S1099   S(bool x): x(x) {}
operator booloperator_implicit_argument::S1100   operator bool() const { return x; }
1101 };
1102 
foo()1103 void foo() {
1104   if (S(false)) {
1105     clang_analyzer_warnIfReached(); // no-warning
1106   }
1107   if (S(true)) {
1108     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
1109   }
1110 }
1111 } // namespace operator_implicit_argument
1112 
1113 
1114 #if __cplusplus >= 201103L
1115 namespace argument_lazy_bindings {
1116 int glob;
1117 
1118 struct S {
1119   int x, y, z;
1120 };
1121 
1122 struct T {
1123   S s;
1124   int w;
Targument_lazy_bindings::T1125   T(int w): s{5, 6, 7}, w(w) {}
1126 };
1127 
foo(T t)1128 void foo(T t) {
1129   t.s = {1, 2, 3};
1130   glob = t.w;
1131 }
1132 
bar()1133 void bar() {
1134   foo(T(4));
1135   clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
1136 }
1137 } // namespace argument_lazy_bindings
1138 #endif
1139 
1140 namespace operator_argument_cleanup {
1141 struct S {
1142   S();
1143 };
1144 
1145 class C {
1146 public:
1147   void operator=(S);
1148 };
1149 
foo()1150 void foo() {
1151   C c;
1152   c = S(); // no-crash
1153 }
1154 } // namespace operator_argument_cleanup
1155 
1156 namespace argument_decl_lookup {
1157 class C {};
1158 int foo(C);
bar(C c)1159 int bar(C c) { foo(c); }
foo(C c)1160 int foo(C c) {}
1161 } // namespace argument_decl_lookup
1162 
1163 namespace argument_virtual_decl_lookup {
1164 class C {};
1165 
1166 struct T  {
1167   virtual void foo(C);
1168 };
1169 
run()1170 void run() {
1171   T *t;
1172   t->foo(C()); // no-crash // expected-warning{{Called C++ object pointer is uninitialized}}
1173 }
1174 
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.
foo(C)1178 void T::foo(C) {}
1179 } // namespace argument_virtual_decl_lookup
1180 
1181 namespace union_indirect_field_crash {
1182 union U {
1183   struct {
1184     int x;
1185   };
1186 };
1187 
1188 template <typename T> class C {
1189 public:
foo() const1190   void foo() const {
1191     (void)(true ? U().x : 0);
1192   }
1193 };
1194 
test()1195 void test() {
1196   C<int> c;
1197   c.foo();
1198 }
1199 } // namespace union_indirect_field_crash
1200 
1201 namespace return_from_top_frame {
1202 struct S {
1203   int *p;
Sreturn_from_top_frame::S1204   S() { p = new int; }
Sreturn_from_top_frame::S1205   S(S &&s) : p(s.p) { s.p = 0; }
1206   ~S();  // Presumably releases 'p'.
1207 };
1208 
foo()1209 S foo() {
1210   S s;
1211   return s;
1212 }
1213 
bar1()1214 S bar1() {
1215   return foo(); // no-warning
1216 }
1217 
bar2()1218 S bar2() {
1219   return S();
1220 }
1221 
bar3(int coin)1222 S bar3(int coin) {
1223   return coin ? S() : foo(); // no-warning
1224 }
1225 } // namespace return_from_top_frame
1226 
1227 #if __cplusplus >= 201103L
1228 namespace arguments_of_operators {
1229 struct S {
Sarguments_of_operators::S1230   S() {}
Sarguments_of_operators::S1231   S(const S &) {}
1232 };
1233 
test()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}}
1239 }
1240 } // namespace arguments_of_operators
1241 #endif // __cplusplus >= 201103L
1242