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