xref: /aosp_15_r20/external/clang/test/Analysis/temporaries.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++03 %s
2*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -w -std=c++11 %s
3*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -DTEMPORARY_DTORS -verify -w -analyzer-config cfg-temporary-dtors=true %s -std=c++11
4*67e74705SXin Li 
5*67e74705SXin Li extern bool clang_analyzer_eval(bool);
6*67e74705SXin Li extern bool clang_analyzer_warnIfReached();
7*67e74705SXin Li 
8*67e74705SXin Li struct Trivial {
TrivialTrivial9*67e74705SXin Li   Trivial(int x) : value(x) {}
10*67e74705SXin Li   int value;
11*67e74705SXin Li };
12*67e74705SXin Li 
13*67e74705SXin Li struct NonTrivial : public Trivial {
NonTrivialNonTrivial14*67e74705SXin Li   NonTrivial(int x) : Trivial(x) {}
15*67e74705SXin Li   ~NonTrivial();
16*67e74705SXin Li };
17*67e74705SXin Li 
18*67e74705SXin Li 
getTrivial()19*67e74705SXin Li Trivial getTrivial() {
20*67e74705SXin Li   return Trivial(42); // no-warning
21*67e74705SXin Li }
22*67e74705SXin Li 
getTrivialRef()23*67e74705SXin Li const Trivial &getTrivialRef() {
24*67e74705SXin Li   return Trivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'Trivial' returned to caller}}
25*67e74705SXin Li }
26*67e74705SXin Li 
27*67e74705SXin Li 
getNonTrivial()28*67e74705SXin Li NonTrivial getNonTrivial() {
29*67e74705SXin Li   return NonTrivial(42); // no-warning
30*67e74705SXin Li }
31*67e74705SXin Li 
getNonTrivialRef()32*67e74705SXin Li const NonTrivial &getNonTrivialRef() {
33*67e74705SXin Li   return NonTrivial(42); // expected-warning {{Address of stack memory associated with temporary object of type 'NonTrivial' returned to caller}}
34*67e74705SXin Li }
35*67e74705SXin Li 
36*67e74705SXin Li namespace rdar13265460 {
37*67e74705SXin Li   struct TrivialSubclass : public Trivial {
TrivialSubclassrdar13265460::TrivialSubclass38*67e74705SXin Li     TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
39*67e74705SXin Li     int anotherValue;
40*67e74705SXin Li   };
41*67e74705SXin Li 
getTrivialSub()42*67e74705SXin Li   TrivialSubclass getTrivialSub() {
43*67e74705SXin Li     TrivialSubclass obj(1);
44*67e74705SXin Li     obj.value = 42;
45*67e74705SXin Li     obj.anotherValue = -42;
46*67e74705SXin Li     return obj;
47*67e74705SXin Li   }
48*67e74705SXin Li 
testImmediate()49*67e74705SXin Li   void testImmediate() {
50*67e74705SXin Li     TrivialSubclass obj = getTrivialSub();
51*67e74705SXin Li 
52*67e74705SXin Li     clang_analyzer_eval(obj.value == 42); // expected-warning{{TRUE}}
53*67e74705SXin Li     clang_analyzer_eval(obj.anotherValue == -42); // expected-warning{{TRUE}}
54*67e74705SXin Li 
55*67e74705SXin Li     clang_analyzer_eval(getTrivialSub().value == 42); // expected-warning{{TRUE}}
56*67e74705SXin Li     clang_analyzer_eval(getTrivialSub().anotherValue == -42); // expected-warning{{TRUE}}
57*67e74705SXin Li   }
58*67e74705SXin Li 
testMaterializeTemporaryExpr()59*67e74705SXin Li   void testMaterializeTemporaryExpr() {
60*67e74705SXin Li     const TrivialSubclass &ref = getTrivialSub();
61*67e74705SXin Li     clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
62*67e74705SXin Li 
63*67e74705SXin Li     const Trivial &baseRef = getTrivialSub();
64*67e74705SXin Li     clang_analyzer_eval(baseRef.value == 42); // expected-warning{{TRUE}}
65*67e74705SXin Li   }
66*67e74705SXin Li }
67*67e74705SXin Li 
68*67e74705SXin Li namespace rdar13281951 {
69*67e74705SXin Li   struct Derived : public Trivial {
Derivedrdar13281951::Derived70*67e74705SXin Li     Derived(int value) : Trivial(value), value2(-value) {}
71*67e74705SXin Li     int value2;
72*67e74705SXin Li   };
73*67e74705SXin Li 
test()74*67e74705SXin Li   void test() {
75*67e74705SXin Li     Derived obj(1);
76*67e74705SXin Li     obj.value = 42;
77*67e74705SXin Li     const Trivial * const &pointerRef = &obj;
78*67e74705SXin Li     clang_analyzer_eval(pointerRef->value == 42); // expected-warning{{TRUE}}
79*67e74705SXin Li   }
80*67e74705SXin Li }
81*67e74705SXin Li 
82*67e74705SXin Li namespace compound_literals {
83*67e74705SXin Li   struct POD {
84*67e74705SXin Li     int x, y;
85*67e74705SXin Li   };
86*67e74705SXin Li   struct HasCtor {
HasCtorcompound_literals::HasCtor87*67e74705SXin Li     HasCtor(int x, int y) : x(x), y(y) {}
88*67e74705SXin Li     int x, y;
89*67e74705SXin Li   };
90*67e74705SXin Li   struct HasDtor {
91*67e74705SXin Li     int x, y;
92*67e74705SXin Li     ~HasDtor();
93*67e74705SXin Li   };
94*67e74705SXin Li   struct HasCtorDtor {
HasCtorDtorcompound_literals::HasCtorDtor95*67e74705SXin Li     HasCtorDtor(int x, int y) : x(x), y(y) {}
96*67e74705SXin Li     ~HasCtorDtor();
97*67e74705SXin Li     int x, y;
98*67e74705SXin Li   };
99*67e74705SXin Li 
test()100*67e74705SXin Li   void test() {
101*67e74705SXin Li     clang_analyzer_eval(((POD){1, 42}).y == 42); // expected-warning{{TRUE}}
102*67e74705SXin Li     clang_analyzer_eval(((HasDtor){1, 42}).y == 42); // expected-warning{{TRUE}}
103*67e74705SXin Li 
104*67e74705SXin Li #if __cplusplus >= 201103L
105*67e74705SXin Li     clang_analyzer_eval(((HasCtor){1, 42}).y == 42); // expected-warning{{TRUE}}
106*67e74705SXin Li 
107*67e74705SXin Li     // FIXME: should be TRUE, but we don't inline the constructors of
108*67e74705SXin Li     // temporaries because we can't model their destructors yet.
109*67e74705SXin Li     clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); // expected-warning{{UNKNOWN}}
110*67e74705SXin Li #endif
111*67e74705SXin Li   }
112*67e74705SXin Li }
113*67e74705SXin Li 
114*67e74705SXin Li namespace destructors {
115*67e74705SXin Li   struct Dtor {
116*67e74705SXin Li     ~Dtor();
117*67e74705SXin Li   };
118*67e74705SXin Li   extern bool coin();
119*67e74705SXin Li   extern bool check(const Dtor &);
120*67e74705SXin Li 
testPR16664andPR18159Crash()121*67e74705SXin Li   void testPR16664andPR18159Crash() {
122*67e74705SXin Li     // Regression test: we used to assert here when tmp dtors are enabled.
123*67e74705SXin Li     // PR16664 and PR18159
124*67e74705SXin Li     if (coin() && (coin() || coin() || check(Dtor()))) {
125*67e74705SXin Li       Dtor();
126*67e74705SXin Li     }
127*67e74705SXin Li   }
128*67e74705SXin Li 
129*67e74705SXin Li #ifdef TEMPORARY_DTORS
130*67e74705SXin Li   struct NoReturnDtor {
131*67e74705SXin Li     ~NoReturnDtor() __attribute__((noreturn));
132*67e74705SXin Li   };
133*67e74705SXin Li 
noReturnTemp(int * x)134*67e74705SXin Li   void noReturnTemp(int *x) {
135*67e74705SXin Li     if (! x) NoReturnDtor();
136*67e74705SXin Li     *x = 47; // no warning
137*67e74705SXin Li   }
138*67e74705SXin Li 
noReturnInline(int ** x)139*67e74705SXin Li   void noReturnInline(int **x) {
140*67e74705SXin Li     NoReturnDtor();
141*67e74705SXin Li   }
142*67e74705SXin Li 
callNoReturn()143*67e74705SXin Li   void callNoReturn() {
144*67e74705SXin Li     int *x;
145*67e74705SXin Li     noReturnInline(&x);
146*67e74705SXin Li     *x = 47; // no warning
147*67e74705SXin Li   }
148*67e74705SXin Li 
149*67e74705SXin Li   extern bool check(const NoReturnDtor &);
150*67e74705SXin Li 
testConsistencyIf(int i)151*67e74705SXin Li   void testConsistencyIf(int i) {
152*67e74705SXin Li     if (i != 5)
153*67e74705SXin Li       return;
154*67e74705SXin Li     if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
155*67e74705SXin Li       clang_analyzer_eval(true); // no warning, unreachable code
156*67e74705SXin Li     }
157*67e74705SXin Li   }
158*67e74705SXin Li 
testConsistencyTernary(int i)159*67e74705SXin Li   void testConsistencyTernary(int i) {
160*67e74705SXin Li     (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
161*67e74705SXin Li 
162*67e74705SXin Li     clang_analyzer_eval(true);  // expected-warning{{TRUE}}
163*67e74705SXin Li 
164*67e74705SXin Li     if (i != 5)
165*67e74705SXin Li       return;
166*67e74705SXin Li 
167*67e74705SXin Li     (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
168*67e74705SXin Li 
169*67e74705SXin Li     clang_analyzer_eval(true); // no warning, unreachable code
170*67e74705SXin Li   }
171*67e74705SXin Li 
172*67e74705SXin Li   // Regression test: we used to assert here.
173*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNested(int i)174*67e74705SXin Li   void testConsistencyNested(int i) {
175*67e74705SXin Li     extern bool compute(bool);
176*67e74705SXin Li 
177*67e74705SXin Li     if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
178*67e74705SXin Li       clang_analyzer_eval(true);  // expected-warning{{TRUE}}
179*67e74705SXin Li 
180*67e74705SXin Li     if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
181*67e74705SXin Li       clang_analyzer_eval(true);  // expected-warning{{TRUE}}
182*67e74705SXin Li 
183*67e74705SXin Li     if (i != 5)
184*67e74705SXin Li       return;
185*67e74705SXin Li 
186*67e74705SXin Li     if (compute(i == 5 &&
187*67e74705SXin Li                 (i == 4 || compute(true) ||
188*67e74705SXin Li                  compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
189*67e74705SXin Li         i != 4) {
190*67e74705SXin Li       clang_analyzer_eval(true);  // expected-warning{{TRUE}}
191*67e74705SXin Li     }
192*67e74705SXin Li 
193*67e74705SXin Li     if (compute(i == 5 &&
194*67e74705SXin Li                 (i == 4 || i == 4 ||
195*67e74705SXin Li                  compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
196*67e74705SXin Li         i != 4) {
197*67e74705SXin Li       clang_analyzer_eval(true);  // no warning, unreachable code
198*67e74705SXin Li     }
199*67e74705SXin Li   }
200*67e74705SXin Li 
201*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedSimple(bool value)202*67e74705SXin Li   void testConsistencyNestedSimple(bool value) {
203*67e74705SXin Li     if (value) {
204*67e74705SXin Li       if (!value || check(NoReturnDtor())) {
205*67e74705SXin Li         clang_analyzer_eval(true); // no warning, unreachable code
206*67e74705SXin Li       }
207*67e74705SXin Li     }
208*67e74705SXin Li   }
209*67e74705SXin Li 
210*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedComplex(bool value)211*67e74705SXin Li   void testConsistencyNestedComplex(bool value) {
212*67e74705SXin Li     if (value) {
213*67e74705SXin Li       if (!value || !value || check(NoReturnDtor())) {
214*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
215*67e74705SXin Li       }
216*67e74705SXin Li     }
217*67e74705SXin Li   }
218*67e74705SXin Li 
219*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedWarning(bool value)220*67e74705SXin Li   void testConsistencyNestedWarning(bool value) {
221*67e74705SXin Li     if (value) {
222*67e74705SXin Li       if (!value || value || check(NoReturnDtor())) {
223*67e74705SXin Li         clang_analyzer_eval(true); // expected-warning{{TRUE}}
224*67e74705SXin Li       }
225*67e74705SXin Li     }
226*67e74705SXin Li   }
227*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedComplexMidBranch(bool value)228*67e74705SXin Li   void testConsistencyNestedComplexMidBranch(bool value) {
229*67e74705SXin Li     if (value) {
230*67e74705SXin Li       if (!value || !value || check(NoReturnDtor()) || value) {
231*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
232*67e74705SXin Li       }
233*67e74705SXin Li     }
234*67e74705SXin Li   }
235*67e74705SXin Li 
236*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedComplexNestedBranch(bool value)237*67e74705SXin Li   void testConsistencyNestedComplexNestedBranch(bool value) {
238*67e74705SXin Li     if (value) {
239*67e74705SXin Li       if (!value || (!value || check(NoReturnDtor()) || value)) {
240*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
241*67e74705SXin Li       }
242*67e74705SXin Li     }
243*67e74705SXin Li   }
244*67e74705SXin Li 
245*67e74705SXin Li   // PR16664 and PR18159
testConsistencyNestedVariableModification(bool value)246*67e74705SXin Li   void testConsistencyNestedVariableModification(bool value) {
247*67e74705SXin Li     bool other = true;
248*67e74705SXin Li     if (value) {
249*67e74705SXin Li       if (!other || !value || (other = false) || check(NoReturnDtor()) ||
250*67e74705SXin Li           !other) {
251*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
252*67e74705SXin Li       }
253*67e74705SXin Li     }
254*67e74705SXin Li   }
255*67e74705SXin Li 
testTernaryNoReturnTrueBranch(bool value)256*67e74705SXin Li   void testTernaryNoReturnTrueBranch(bool value) {
257*67e74705SXin Li     if (value) {
258*67e74705SXin Li       bool b = value && (value ? check(NoReturnDtor()) : true);
259*67e74705SXin Li       clang_analyzer_eval(true);  // no warning, unreachable code
260*67e74705SXin Li     }
261*67e74705SXin Li   }
testTernaryNoReturnFalseBranch(bool value)262*67e74705SXin Li   void testTernaryNoReturnFalseBranch(bool value) {
263*67e74705SXin Li     if (value) {
264*67e74705SXin Li       bool b = !value && !value ? true : check(NoReturnDtor());
265*67e74705SXin Li       clang_analyzer_eval(true);  // no warning, unreachable code
266*67e74705SXin Li     }
267*67e74705SXin Li   }
testTernaryIgnoreNoreturnBranch(bool value)268*67e74705SXin Li   void testTernaryIgnoreNoreturnBranch(bool value) {
269*67e74705SXin Li     if (value) {
270*67e74705SXin Li       bool b = !value && !value ? check(NoReturnDtor()) : true;
271*67e74705SXin Li       clang_analyzer_eval(true);  // expected-warning{{TRUE}}
272*67e74705SXin Li     }
273*67e74705SXin Li   }
testTernaryTrueBranchReached(bool value)274*67e74705SXin Li   void testTernaryTrueBranchReached(bool value) {
275*67e74705SXin Li     value ? clang_analyzer_warnIfReached() : // expected-warning{{REACHABLE}}
276*67e74705SXin Li             check(NoReturnDtor());
277*67e74705SXin Li   }
testTernaryFalseBranchReached(bool value)278*67e74705SXin Li   void testTernaryFalseBranchReached(bool value) {
279*67e74705SXin Li     value ? check(NoReturnDtor()) :
280*67e74705SXin Li             clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
281*67e74705SXin Li   }
282*67e74705SXin Li 
testLoop()283*67e74705SXin Li   void testLoop() {
284*67e74705SXin Li     for (int i = 0; i < 10; ++i) {
285*67e74705SXin Li       if (i < 3 && (i >= 2 || check(NoReturnDtor()))) {
286*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
287*67e74705SXin Li       }
288*67e74705SXin Li     }
289*67e74705SXin Li   }
290*67e74705SXin Li 
testRecursiveFrames(bool isInner)291*67e74705SXin Li   bool testRecursiveFrames(bool isInner) {
292*67e74705SXin Li     if (isInner ||
293*67e74705SXin Li         (clang_analyzer_warnIfReached(), false) || // expected-warning{{REACHABLE}}
294*67e74705SXin Li         check(NoReturnDtor()) ||
295*67e74705SXin Li         testRecursiveFrames(true)) {
296*67e74705SXin Li       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
297*67e74705SXin Li     }
298*67e74705SXin Li   }
testRecursiveFramesStart()299*67e74705SXin Li   void testRecursiveFramesStart() { testRecursiveFrames(false); }
300*67e74705SXin Li 
testLambdas()301*67e74705SXin Li   void testLambdas() {
302*67e74705SXin Li     []() { check(NoReturnDtor()); } != nullptr || check(Dtor());
303*67e74705SXin Li   }
304*67e74705SXin Li 
testGnuExpressionStatements(int v)305*67e74705SXin Li   void testGnuExpressionStatements(int v) {
306*67e74705SXin Li     ({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;
307*67e74705SXin Li     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
308*67e74705SXin Li 
309*67e74705SXin Li     ({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;
310*67e74705SXin Li     clang_analyzer_warnIfReached();  // no warning, unreachable code
311*67e74705SXin Li   }
312*67e74705SXin Li 
testGnuExpressionStatementsDestructionPoint(int v)313*67e74705SXin Li   void testGnuExpressionStatementsDestructionPoint(int v) {
314*67e74705SXin Li     // In normal context, the temporary destructor runs at the end of the full
315*67e74705SXin Li     // statement, thus the last statement is reached.
316*67e74705SXin Li     (++v, check(NoReturnDtor()), v == 42),
317*67e74705SXin Li         clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
318*67e74705SXin Li 
319*67e74705SXin Li     // GNU expression statements execute temporary destructors within the
320*67e74705SXin Li     // blocks, thus the last statement is not reached.
321*67e74705SXin Li     ({ ++v; check(NoReturnDtor()); v == 42; }),
322*67e74705SXin Li         clang_analyzer_warnIfReached();  // no warning, unreachable code
323*67e74705SXin Li   }
324*67e74705SXin Li 
testMultipleTemporaries(bool value)325*67e74705SXin Li   void testMultipleTemporaries(bool value) {
326*67e74705SXin Li     if (value) {
327*67e74705SXin Li       // FIXME: Find a way to verify construction order.
328*67e74705SXin Li       // ~Dtor should run before ~NoReturnDtor() because construction order is
329*67e74705SXin Li       // guaranteed by comma operator.
330*67e74705SXin Li       if (!value || check((NoReturnDtor(), Dtor())) || value) {
331*67e74705SXin Li         clang_analyzer_eval(true);  // no warning, unreachable code
332*67e74705SXin Li       }
333*67e74705SXin Li     }
334*67e74705SXin Li   }
335*67e74705SXin Li 
testBinaryOperatorShortcut(bool value)336*67e74705SXin Li   void testBinaryOperatorShortcut(bool value) {
337*67e74705SXin Li     if (value) {
338*67e74705SXin Li       if (false && false && check(NoReturnDtor()) && true) {
339*67e74705SXin Li         clang_analyzer_eval(true);
340*67e74705SXin Li       }
341*67e74705SXin Li     }
342*67e74705SXin Li   }
343*67e74705SXin Li 
testIfAtEndOfLoop()344*67e74705SXin Li   void testIfAtEndOfLoop() {
345*67e74705SXin Li     int y = 0;
346*67e74705SXin Li     while (true) {
347*67e74705SXin Li       if (y > 0) {
348*67e74705SXin Li         clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
349*67e74705SXin Li       }
350*67e74705SXin Li       ++y;
351*67e74705SXin Li       // Test that the CFG gets hooked up correctly when temporary destructors
352*67e74705SXin Li       // are handled after a statically known branch condition.
353*67e74705SXin Li       if (true) (void)0; else (void)check(NoReturnDtor());
354*67e74705SXin Li     }
355*67e74705SXin Li   }
356*67e74705SXin Li 
testTernaryAtEndOfLoop()357*67e74705SXin Li   void testTernaryAtEndOfLoop() {
358*67e74705SXin Li     int y = 0;
359*67e74705SXin Li     while (true) {
360*67e74705SXin Li       if (y > 0) {
361*67e74705SXin Li         clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
362*67e74705SXin Li       }
363*67e74705SXin Li       ++y;
364*67e74705SXin Li       // Test that the CFG gets hooked up correctly when temporary destructors
365*67e74705SXin Li       // are handled after a statically known branch condition.
366*67e74705SXin Li       true ? (void)0 : (void)check(NoReturnDtor());
367*67e74705SXin Li     }
368*67e74705SXin Li   }
369*67e74705SXin Li 
testNoReturnInComplexCondition()370*67e74705SXin Li   void testNoReturnInComplexCondition() {
371*67e74705SXin Li     check(Dtor()) &&
372*67e74705SXin Li         (check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
373*67e74705SXin Li     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
374*67e74705SXin Li   }
375*67e74705SXin Li 
testSequencingOfConditionalTempDtors(bool b)376*67e74705SXin Li   void testSequencingOfConditionalTempDtors(bool b) {
377*67e74705SXin Li     b || (check(Dtor()), check(NoReturnDtor()));
378*67e74705SXin Li     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
379*67e74705SXin Li   }
380*67e74705SXin Li 
testSequencingOfConditionalTempDtors2(bool b)381*67e74705SXin Li   void testSequencingOfConditionalTempDtors2(bool b) {
382*67e74705SXin Li     (b || check(Dtor())), check(NoReturnDtor());
383*67e74705SXin Li     clang_analyzer_warnIfReached();  // no warning, unreachable code
384*67e74705SXin Li   }
385*67e74705SXin Li 
testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b)386*67e74705SXin Li   void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {
387*67e74705SXin Li     b || (check(Dtor()) + check(NoReturnDtor()));
388*67e74705SXin Li     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
389*67e74705SXin Li   }
390*67e74705SXin Li 
391*67e74705SXin Li   void f(Dtor d = Dtor());
testDefaultParameters()392*67e74705SXin Li   void testDefaultParameters() {
393*67e74705SXin Li     f();
394*67e74705SXin Li   }
395*67e74705SXin Li 
396*67e74705SXin Li   struct DefaultParam {
397*67e74705SXin Li     DefaultParam(int, const Dtor& d = Dtor());
398*67e74705SXin Li     ~DefaultParam();
399*67e74705SXin Li   };
testDefaultParamConstructorsInLoops()400*67e74705SXin Li   void testDefaultParamConstructorsInLoops() {
401*67e74705SXin Li     while (true) {
402*67e74705SXin Li       // FIXME: This exact pattern triggers the temporary cleanup logic
403*67e74705SXin Li       // to fail when adding a 'clean' state.
404*67e74705SXin Li       DefaultParam(42);
405*67e74705SXin Li       DefaultParam(42);
406*67e74705SXin Li     }
407*67e74705SXin Li   }
testDefaultParamConstructorsInTernariesInLoops(bool value)408*67e74705SXin Li   void testDefaultParamConstructorsInTernariesInLoops(bool value) {
409*67e74705SXin Li     while (true) {
410*67e74705SXin Li       // FIXME: This exact pattern triggers the temporary cleanup logic
411*67e74705SXin Li       // to visit the bind-temporary logic with a state that already has that
412*67e74705SXin Li       // temporary marked as executed.
413*67e74705SXin Li       value ? DefaultParam(42) : DefaultParam(42);
414*67e74705SXin Li     }
415*67e74705SXin Li   }
416*67e74705SXin Li #endif // TEMPORARY_DTORS
417*67e74705SXin Li }
418*67e74705SXin Li 
testStaticMaterializeTemporaryExpr()419*67e74705SXin Li void testStaticMaterializeTemporaryExpr() {
420*67e74705SXin Li   static const Trivial &ref = getTrivial();
421*67e74705SXin Li   clang_analyzer_eval(ref.value == 42); // expected-warning{{TRUE}}
422*67e74705SXin Li 
423*67e74705SXin Li   static const Trivial &directRef = Trivial(42);
424*67e74705SXin Li   clang_analyzer_eval(directRef.value == 42); // expected-warning{{TRUE}}
425*67e74705SXin Li 
426*67e74705SXin Li #if __has_feature(cxx_thread_local)
427*67e74705SXin Li   thread_local static const Trivial &threadRef = getTrivial();
428*67e74705SXin Li   clang_analyzer_eval(threadRef.value == 42); // expected-warning{{TRUE}}
429*67e74705SXin Li 
430*67e74705SXin Li   thread_local static const Trivial &threadDirectRef = Trivial(42);
431*67e74705SXin Li   clang_analyzer_eval(threadDirectRef.value == 42); // expected-warning{{TRUE}}
432*67e74705SXin Li #endif
433*67e74705SXin Li }
434*67e74705SXin Li 
435*67e74705SXin Li namespace PR16629 {
436*67e74705SXin Li   struct A {
APR16629::A437*67e74705SXin Li     explicit A(int* p_) : p(p_) {}
438*67e74705SXin Li     int* p;
439*67e74705SXin Li   };
440*67e74705SXin Li 
441*67e74705SXin Li   extern void escape(const A*[]);
442*67e74705SXin Li   extern void check(int);
443*67e74705SXin Li 
callEscape(const A & a)444*67e74705SXin Li   void callEscape(const A& a) {
445*67e74705SXin Li     const A* args[] = { &a };
446*67e74705SXin Li     escape(args);
447*67e74705SXin Li   }
448*67e74705SXin Li 
testNoWarning()449*67e74705SXin Li   void testNoWarning() {
450*67e74705SXin Li     int x;
451*67e74705SXin Li     callEscape(A(&x));
452*67e74705SXin Li     check(x); // Analyzer used to give a "x is uninitialized warning" here
453*67e74705SXin Li   }
454*67e74705SXin Li 
set(const A * a[])455*67e74705SXin Li   void set(const A*a[]) {
456*67e74705SXin Li     *a[0]->p = 47;
457*67e74705SXin Li   }
458*67e74705SXin Li 
callSet(const A & a)459*67e74705SXin Li   void callSet(const A& a) {
460*67e74705SXin Li     const A* args[] = { &a };
461*67e74705SXin Li     set(args);
462*67e74705SXin Li   }
463*67e74705SXin Li 
testConsistency()464*67e74705SXin Li   void testConsistency() {
465*67e74705SXin Li     int x;
466*67e74705SXin Li     callSet(A(&x));
467*67e74705SXin Li     clang_analyzer_eval(x == 47); // expected-warning{{TRUE}}
468*67e74705SXin Li   }
469*67e74705SXin Li }
470