Clang Project

clang_source_code/test/Analysis/temporaries.cpp
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
24extern bool clang_analyzer_eval(bool);
25extern bool clang_analyzer_warnIfReached();
26void clang_analyzer_checkInlined(bool);
27
28#include "Inputs/system-header-simulator-cxx.h"
29
30struct Trivial {
31  Trivial(int x) : value(x) {}
32  int value;
33};
34
35struct NonTrivial : public Trivial {
36  NonTrivial(int x) : Trivial(x) {}
37  ~NonTrivial();
38};
39
40
41Trivial getTrivial() {
42  return Trivial(42); // no-warning
43}
44
45const 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
50NonTrivial getNonTrivial() {
51  return NonTrivial(42); // no-warning
52}
53
54const NonTrivial &getNonTrivialRef() {
55  return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
56}
57
58namespace 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
90namespace 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
104namespace 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
136namespace 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
486namespace default_param_elided_destructors {
487struct a {
488  ~a();
489};
490struct F {
491  a d;
492  F(char *, a = a());
493};
494void g() {
495  char h[1];
496  for (int i = 0;;)
497    F j(i ? j : h);
498}
499} // namespace default_param_elided_destructors
500
501void 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
517namespace 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
553namespace 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
563namespace CopyToTemporaryCorrectly {
564class Super {
565public:
566  void m() {
567    mImpl();
568  }
569  virtual void mImpl() = 0;
570};
571class Sub : public Super {
572public:
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};
584void run() {
585  int i = 22;
586  Sub(i).m();
587}
588}
589
590namespace test_return_temporary {
591class C {
592  int x, y;
593
594public:
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
601class D: public C {
602public:
603  D() : C(1, 2) {}
604  D(const D &d): C(d.getX(), d.getY()) {}
605};
606
607C returnTemporaryWithVariable() { C c(1, 2); return c; }
608C returnTemporaryWithAnotherFunctionWithVariable() {
609  return returnTemporaryWithVariable();
610}
611C returnTemporaryWithCopyConstructionWithVariable() {
612  return C(returnTemporaryWithVariable());
613}
614
615C returnTemporaryWithConstruction() { return C(1, 2); }
616C returnTemporaryWithAnotherFunctionWithConstruction() {
617  return returnTemporaryWithConstruction();
618}
619C returnTemporaryWithCopyConstructionWithConstruction() {
620  return C(returnTemporaryWithConstruction());
621}
622
623D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
624D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
625  return returnTemporaryWithVariableAndNonTrivialCopy();
626}
627D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
628  return D(returnTemporaryWithVariableAndNonTrivialCopy());
629}
630
631#if __cplusplus >= 201103L
632C returnTemporaryWithBraces() { return {1, 2}; }
633C returnTemporaryWithAnotherFunctionWithBraces() {
634  return returnTemporaryWithBraces();
635}
636C returnTemporaryWithCopyConstructionWithBraces() {
637  return C(returnTemporaryWithBraces());
638}
639#endif // C++11
640
641void 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
697namespace test_temporary_object_expr_without_dtor {
698class C {
699  int x;
700public:
701  C(int x) : x(x) {}
702  int getX() const { return x; }
703};
704
705void test() {
706  clang_analyzer_eval(C(3).getX() == 3); // expected-warning{{TRUE}}
707};
708}
709
710namespace test_temporary_object_expr_with_dtor {
711class C {
712  int x;
713
714public:
715  C(int x) : x(x) {}
716  ~C() {}
717  int getX() const { return x; }
718};
719
720void 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
755namespace test_match_constructors_and_destructors {
756class C {
757public:
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
764void 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
781void 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
791void 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
825void 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
856namespace destructors_for_return_values {
857
858class C {
859public:
860  ~C() {
861    1 / 0; // expected-warning{{Division by zero}}
862  }
863};
864
865C make();
866
867void 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
876void 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
885void 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
896namespace dont_forget_destructor_around_logical_op {
897int glob;
898
899class C {
900public:
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
913C get();
914
915bool is(C);
916
917
918void 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
946namespace temporary_list_crash {
947class C {
948public:
949  C() {}
950  ~C() {}
951};
952
953void test() {
954  std::initializer_list<C>{C(), C()}; // no-crash
955}
956} // namespace temporary_list_crash
957#endif // C++11
958
959namespace implicit_constructor_conversion {
960struct S {
961  int x;
962  S(int x) : x(x) {}
963  ~S() {}
964};
965
966class C {
967  int x;
968
969public:
970  C(const S &s) : x(s.x) {}
971  ~C() {}
972  int getX() const { return x; }
973};
974
975void 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
992namespace pass_references_through {
993class C {
994public:
995  ~C() {}
996};
997
998const C &foo1();
999C &&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.
1003const C &bar1() { return foo1(); } // no-crash
1004C &&bar2() { return foo2(); } // no-crash
1005} // end namespace pass_references_through
1006
1007
1008namespace arguments {
1009int glob;
1010
1011struct 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
1024class C {
1025public:
1026  virtual void bar3(S s) {}
1027};
1028
1029class D: public C {
1030public:
1031  D() {}
1032  virtual void bar3(S s) override { glob = s.x; }
1033};
1034
1035void 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.
1041S bar2(S s) {
1042  glob = s.x;
1043  return S(3);
1044}
1045
1046void bar5(int, ...);
1047
1048void 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
1094namespace ctor_argument {
1095// Stripped down unique_ptr<int>
1096struct 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
1104struct Foo {
1105  Foo(IntPtr);
1106  void bar();
1107
1108  IntPtr i;
1109};
1110
1111void 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
1119namespace operator_implicit_argument {
1120struct S {
1121  bool x;
1122  S(bool x): x(x) {}
1123  operator bool() const { return x; }
1124};
1125
1126void 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
1138namespace argument_lazy_bindings {
1139int glob;
1140
1141struct S {
1142  int x, y, z;
1143};
1144
1145struct T {
1146  S s;
1147  int w;
1148  T(int w): s{5, 6, 7}, w(w) {}
1149};
1150
1151void foo(T t) {
1152  t.s = {1, 2, 3};
1153  glob = t.w;
1154}
1155
1156void bar() {
1157  foo(T(4));
1158  clang_analyzer_eval(glob == 4); // expected-warning{{TRUE}}
1159}
1160} // namespace argument_lazy_bindings
1161#endif
1162
1163namespace operator_argument_cleanup {
1164struct S {
1165  S();
1166};
1167
1168class C {
1169public:
1170  void operator=(S);
1171};
1172
1173void foo() {
1174  C c;
1175  c = S(); // no-crash
1176}
1177} // namespace operator_argument_cleanup
1178
1179namespace argument_decl_lookup {
1180class C {};
1181int foo(C);
1182int bar(C c) { foo(c); }
1183int foo(C c) {}
1184} // namespace argument_decl_lookup
1185
1186namespace argument_virtual_decl_lookup {
1187class C {};
1188
1189struct T  {
1190  virtual void foo(C);
1191};
1192
1193void 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.
1201void T::foo(C) {}
1202} // namespace argument_virtual_decl_lookup
1203
1204namespace union_indirect_field_crash {
1205union U {
1206  struct {
1207    int x;
1208  };
1209};
1210
1211template <typename T> class C {
1212public:
1213  void foo() const {
1214    (void)(true ? U().x : 0);
1215  }
1216};
1217
1218void test() {
1219  C<int> c;
1220  c.foo();
1221}
1222} // namespace union_indirect_field_crash
1223
1224namespace return_from_top_frame {
1225struct 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
1232S foo() {
1233  S s;
1234  return s;
1235}
1236
1237S bar1() {
1238  return foo(); // no-warning
1239}
1240
1241S bar2() {
1242  return S();
1243}
1244
1245S bar3(int coin) {
1246  return coin ? S() : foo(); // no-warning
1247}
1248} // namespace return_from_top_frame
1249