blob: e7c0c6cac630e1353e142fc8e476bba594c700de [file] [log] [blame]
Jordan Rosebc403862013-02-15 00:32:15 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
Jordan Rosebf83e7c2012-08-03 23:08:36 +00002
Jordan Rosebe2e1b12013-07-17 17:16:33 +00003#include "Inputs/system-header-simulator-cxx.h"
4
Jordan Rosebf83e7c2012-08-03 23:08:36 +00005void clang_analyzer_eval(bool);
Jordan Rosede5277f2012-08-31 17:06:49 +00006void clang_analyzer_checkInlined(bool);
Jordan Rose1d3ca252012-07-26 20:04:30 +00007
Jordan Rosebc403862013-02-15 00:32:15 +00008// A simplified version of std::move.
9template <typename T>
10T &&move(T &obj) {
11 return static_cast<T &&>(obj);
12}
13
14
Jordan Rose1d3ca252012-07-26 20:04:30 +000015struct Wrapper {
16 __strong id obj;
17};
18
19void test() {
20 Wrapper w;
21 // force a diagnostic
22 *(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
23}
Jordan Rosebf83e7c2012-08-03 23:08:36 +000024
25
26struct IntWrapper {
27 int x;
28};
29
30void testCopyConstructor() {
31 IntWrapper a;
32 a.x = 42;
33
34 IntWrapper b(a);
35 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
36}
37
38struct NonPODIntWrapper {
39 int x;
40
41 virtual int get();
42};
43
44void testNonPODCopyConstructor() {
45 NonPODIntWrapper a;
46 a.x = 42;
47
48 NonPODIntWrapper b(a);
49 clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
50}
51
Jordan Rose4e79fdf2012-08-15 20:07:17 +000052
53namespace ConstructorVirtualCalls {
54 class A {
55 public:
56 int *out1, *out2, *out3;
57
58 virtual int get() { return 1; }
59
60 A(int *out1) {
61 *out1 = get();
62 }
63 };
64
65 class B : public A {
66 public:
67 virtual int get() { return 2; }
68
69 B(int *out1, int *out2) : A(out1) {
70 *out2 = get();
71 }
72 };
73
74 class C : public B {
75 public:
76 virtual int get() { return 3; }
77
78 C(int *out1, int *out2, int *out3) : B(out1, out2) {
79 *out3 = get();
80 }
81 };
82
83 void test() {
84 int a, b, c;
85
86 C obj(&a, &b, &c);
87 clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
88 clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
89 clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
90
91 clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
92
93 // Sanity check for devirtualization.
94 A *base = &obj;
95 clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
96 }
97}
98
Jordan Rosede5277f2012-08-31 17:06:49 +000099namespace TemporaryConstructor {
100 class BoolWrapper {
101 public:
102 BoolWrapper() {
103 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
104 value = true;
105 }
106 bool value;
107 };
Jordan Rose4e79fdf2012-08-15 20:07:17 +0000108
Jordan Rosede5277f2012-08-31 17:06:49 +0000109 void test() {
110 // PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
111 if (BoolWrapper().value)
112 return;
113 }
114}
Jordan Rose0504a592012-10-01 17:51:35 +0000115
116
117namespace ConstructorUsedAsRValue {
118 using TemporaryConstructor::BoolWrapper;
119
120 bool extractValue(BoolWrapper b) {
121 return b.value;
122 }
123
124 void test() {
125 bool result = extractValue(BoolWrapper());
126 clang_analyzer_eval(result); // expected-warning{{TRUE}}
127 }
128}
Jordan Rosebc403862013-02-15 00:32:15 +0000129
130namespace PODUninitialized {
131 class POD {
132 public:
133 int x, y;
134 };
135
136 class PODWrapper {
137 public:
138 POD p;
139 };
140
141 class NonPOD {
142 public:
143 int x, y;
144
145 NonPOD() {}
146 NonPOD(const NonPOD &Other)
147 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
148 {
149 }
150 NonPOD(NonPOD &&Other)
151 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
152 {
153 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000154
155 NonPOD &operator=(const NonPOD &Other)
156 {
157 x = Other.x;
158 y = Other.y; // expected-warning {{undefined}}
159 return *this;
160 }
161 NonPOD &operator=(NonPOD &&Other)
162 {
163 x = Other.x;
164 y = Other.y; // expected-warning {{undefined}}
165 return *this;
166 }
Jordan Rosebc403862013-02-15 00:32:15 +0000167 };
168
169 class NonPODWrapper {
170 public:
171 class Inner {
172 public:
173 int x, y;
174
175 Inner() {}
176 Inner(const Inner &Other)
177 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
178 {
179 }
180 Inner(Inner &&Other)
181 : x(Other.x), y(Other.y) // expected-warning {{undefined}}
182 {
183 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000184
185 Inner &operator=(const Inner &Other)
186 {
187 x = Other.x; // expected-warning {{undefined}}
188 y = Other.y;
189 return *this;
190 }
191 Inner &operator=(Inner &&Other)
192 {
193 x = Other.x; // expected-warning {{undefined}}
194 y = Other.y;
195 return *this;
196 }
Jordan Rosebc403862013-02-15 00:32:15 +0000197 };
198
199 Inner p;
200 };
201
202 void testPOD() {
203 POD p;
204 p.x = 1;
205 POD p2 = p; // no-warning
206 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
207 POD p3 = move(p); // no-warning
208 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
209
210 // Use rvalues as well.
211 clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
212
213 PODWrapper w;
214 w.p.y = 1;
215 PODWrapper w2 = w; // no-warning
216 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
217 PODWrapper w3 = move(w); // no-warning
218 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
219
220 // Use rvalues as well.
221 clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
222 }
223
224 void testNonPOD() {
225 NonPOD p;
226 p.x = 1;
227 NonPOD p2 = p;
228 }
229
230 void testNonPODMove() {
231 NonPOD p;
232 p.x = 1;
233 NonPOD p2 = move(p);
234 }
235
236 void testNonPODWrapper() {
237 NonPODWrapper w;
238 w.p.y = 1;
239 NonPODWrapper w2 = w;
240 }
241
242 void testNonPODWrapperMove() {
243 NonPODWrapper w;
244 w.p.y = 1;
245 NonPODWrapper w2 = move(w);
246 }
Jordan Rosea8d937e2013-03-16 02:14:06 +0000247
248 // Not strictly about constructors, but trivial assignment operators should
249 // essentially work the same way.
250 namespace AssignmentOperator {
251 void testPOD() {
252 POD p;
253 p.x = 1;
254 POD p2;
255 p2 = p; // no-warning
256 clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
257 POD p3;
258 p3 = move(p); // no-warning
259 clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
260
261 PODWrapper w;
262 w.p.y = 1;
263 PODWrapper w2;
264 w2 = w; // no-warning
265 clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
266 PODWrapper w3;
267 w3 = move(w); // no-warning
268 clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
269 }
270
271 void testReturnValue() {
272 POD p;
273 p.x = 1;
274 POD p2;
275 clang_analyzer_eval(&(p2 = p) == &p2); // expected-warning{{TRUE}}
276
277 PODWrapper w;
278 w.p.y = 1;
279 PODWrapper w2;
280 clang_analyzer_eval(&(w2 = w) == &w2); // expected-warning{{TRUE}}
281 }
282
283 void testNonPOD() {
284 NonPOD p;
285 p.x = 1;
286 NonPOD p2;
287 p2 = p;
288 }
289
290 void testNonPODMove() {
291 NonPOD p;
292 p.x = 1;
293 NonPOD p2;
294 p2 = move(p);
295 }
296
297 void testNonPODWrapper() {
298 NonPODWrapper w;
299 w.p.y = 1;
300 NonPODWrapper w2;
301 w2 = w;
302 }
303
304 void testNonPODWrapperMove() {
305 NonPODWrapper w;
306 w.p.y = 1;
307 NonPODWrapper w2;
308 w2 = move(w);
309 }
310 }
Jordan Rosebc403862013-02-15 00:32:15 +0000311}
Jordan Roseecee1652013-04-03 01:39:08 +0000312
313namespace ArrayMembers {
314 struct Primitive {
315 int values[3];
316 };
317
318 void testPrimitive() {
319 Primitive a = { { 1, 2, 3 } };
320
321 clang_analyzer_eval(a.values[0] == 1); // expected-warning{{TRUE}}
322 clang_analyzer_eval(a.values[1] == 2); // expected-warning{{TRUE}}
323 clang_analyzer_eval(a.values[2] == 3); // expected-warning{{TRUE}}
324
325 Primitive b = a;
326
327 clang_analyzer_eval(b.values[0] == 1); // expected-warning{{TRUE}}
328 clang_analyzer_eval(b.values[1] == 2); // expected-warning{{TRUE}}
329 clang_analyzer_eval(b.values[2] == 3); // expected-warning{{TRUE}}
330
331 Primitive c;
332 c = b;
333
334 clang_analyzer_eval(c.values[0] == 1); // expected-warning{{TRUE}}
335 clang_analyzer_eval(c.values[1] == 2); // expected-warning{{TRUE}}
336 clang_analyzer_eval(c.values[2] == 3); // expected-warning{{TRUE}}
337 }
338
339 struct NestedPrimitive {
340 int values[2][3];
341 };
342
343 void testNestedPrimitive() {
344 NestedPrimitive a = { { { 0, 0, 0 }, { 1, 2, 3 } } };
345
346 clang_analyzer_eval(a.values[1][0] == 1); // expected-warning{{TRUE}}
347 clang_analyzer_eval(a.values[1][1] == 2); // expected-warning{{TRUE}}
348 clang_analyzer_eval(a.values[1][2] == 3); // expected-warning{{TRUE}}
349
350 NestedPrimitive b = a;
351
352 clang_analyzer_eval(b.values[1][0] == 1); // expected-warning{{TRUE}}
353 clang_analyzer_eval(b.values[1][1] == 2); // expected-warning{{TRUE}}
354 clang_analyzer_eval(b.values[1][2] == 3); // expected-warning{{TRUE}}
355
356 NestedPrimitive c;
357 c = b;
358
359 clang_analyzer_eval(c.values[1][0] == 1); // expected-warning{{TRUE}}
360 clang_analyzer_eval(c.values[1][1] == 2); // expected-warning{{TRUE}}
361 clang_analyzer_eval(c.values[1][2] == 3); // expected-warning{{TRUE}}
362 }
363
364 struct POD {
365 IntWrapper values[3];
366 };
367
368 void testPOD() {
369 POD a = { { { 1 }, { 2 }, { 3 } } };
370
371 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
372 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
373 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
374
375 POD b = a;
376
377 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{TRUE}}
378 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{TRUE}}
379 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{TRUE}}
380
381 POD c;
382 c = b;
383
384 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{TRUE}}
385 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{TRUE}}
386 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{TRUE}}
387 }
388
389 struct NestedPOD {
390 IntWrapper values[2][3];
391 };
392
393 void testNestedPOD() {
394 NestedPOD a = { { { { 0 }, { 0 }, { 0 } }, { { 1 }, { 2 }, { 3 } } } };
395
396 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
397 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
398 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
399
400 NestedPOD b = a;
401
402 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{TRUE}}
403 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{TRUE}}
404 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{TRUE}}
405
406 NestedPOD c;
407 c = b;
408
409 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{TRUE}}
410 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{TRUE}}
411 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{TRUE}}
412 }
413
414 struct NonPOD {
415 NonPODIntWrapper values[3];
416 };
417
418 void testNonPOD() {
419 NonPOD a;
420 a.values[0].x = 1;
421 a.values[1].x = 2;
422 a.values[2].x = 3;
423
424 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
425 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
426 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
427
428 NonPOD b = a;
429
430 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
431 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
432 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
433
434 NonPOD c;
435 c = b;
436
437 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
438 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
439 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
440 }
441
442 struct NestedNonPOD {
443 NonPODIntWrapper values[2][3];
444 };
445
446 void testNestedNonPOD() {
447 NestedNonPOD a;
448 a.values[0][0].x = 0;
449 a.values[0][1].x = 0;
450 a.values[0][2].x = 0;
451 a.values[1][0].x = 1;
452 a.values[1][1].x = 2;
453 a.values[1][2].x = 3;
454
455 clang_analyzer_eval(a.values[1][0].x == 1); // expected-warning{{TRUE}}
456 clang_analyzer_eval(a.values[1][1].x == 2); // expected-warning{{TRUE}}
457 clang_analyzer_eval(a.values[1][2].x == 3); // expected-warning{{TRUE}}
458
459 NestedNonPOD b = a;
460
461 clang_analyzer_eval(b.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
462 clang_analyzer_eval(b.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
463 clang_analyzer_eval(b.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
464
465 NestedNonPOD c;
466 c = b;
467
468 clang_analyzer_eval(c.values[1][0].x == 1); // expected-warning{{UNKNOWN}}
469 clang_analyzer_eval(c.values[1][1].x == 2); // expected-warning{{UNKNOWN}}
470 clang_analyzer_eval(c.values[1][2].x == 3); // expected-warning{{UNKNOWN}}
471 }
472
473 struct NonPODDefaulted {
474 NonPODIntWrapper values[3];
475
476 NonPODDefaulted() = default;
477 NonPODDefaulted(const NonPODDefaulted &) = default;
478 NonPODDefaulted &operator=(const NonPODDefaulted &) = default;
479 };
480
481 void testNonPODDefaulted() {
482 NonPODDefaulted a;
483 a.values[0].x = 1;
484 a.values[1].x = 2;
485 a.values[2].x = 3;
486
487 clang_analyzer_eval(a.values[0].x == 1); // expected-warning{{TRUE}}
488 clang_analyzer_eval(a.values[1].x == 2); // expected-warning{{TRUE}}
489 clang_analyzer_eval(a.values[2].x == 3); // expected-warning{{TRUE}}
490
491 NonPODDefaulted b = a;
492
493 clang_analyzer_eval(b.values[0].x == 1); // expected-warning{{UNKNOWN}}
494 clang_analyzer_eval(b.values[1].x == 2); // expected-warning{{UNKNOWN}}
495 clang_analyzer_eval(b.values[2].x == 3); // expected-warning{{UNKNOWN}}
496
497 NonPODDefaulted c;
498 c = b;
499
500 clang_analyzer_eval(c.values[0].x == 1); // expected-warning{{UNKNOWN}}
501 clang_analyzer_eval(c.values[1].x == 2); // expected-warning{{UNKNOWN}}
502 clang_analyzer_eval(c.values[2].x == 3); // expected-warning{{UNKNOWN}}
503 }
504};
Jordan Rose1fc91112013-06-25 01:55:59 +0000505
506namespace VirtualInheritance {
507 int counter;
508
509 struct base {
510 base() {
511 ++counter;
512 }
513 };
514
515 struct virtual_subclass : public virtual base {
516 virtual_subclass() {}
517 };
518
519 struct double_subclass : public virtual_subclass {
520 double_subclass() {}
521 };
522
523 void test() {
524 counter = 0;
525 double_subclass obj;
526 clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
527 }
528
529 struct double_virtual_subclass : public virtual virtual_subclass {
530 double_virtual_subclass() {}
531 };
532
533 void testVirtual() {
534 counter = 0;
535 double_virtual_subclass obj;
536 clang_analyzer_eval(counter == 1); // expected-warning{{TRUE}}
537 }
538}
Jordan Rosebe35df12013-06-25 01:56:08 +0000539
540namespace ZeroInitialization {
541 struct raw_pair {
542 int p1;
543 int p2;
544 };
545
546 void testVarDecl() {
547 raw_pair p{};
548 clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
549 clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
550 }
551
552 void testTemporary() {
553 clang_analyzer_eval(raw_pair().p1 == 0); // expected-warning{{TRUE}}
554 clang_analyzer_eval(raw_pair().p2 == 0); // expected-warning{{TRUE}}
555 }
556
557 void testArray() {
558 raw_pair p[2] = {};
559 clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{TRUE}}
560 clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{TRUE}}
561 clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{TRUE}}
562 clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{TRUE}}
563 }
564
565 void testNew() {
566 // FIXME: Pending proper implementation of constructors for 'new'.
567 raw_pair *pp = new raw_pair();
568 clang_analyzer_eval(pp->p1 == 0); // expected-warning{{UNKNOWN}}
569 clang_analyzer_eval(pp->p2 == 0); // expected-warning{{UNKNOWN}}
570 }
571
572 void testArrayNew() {
573 // FIXME: Pending proper implementation of constructors for 'new[]'.
574 raw_pair *p = new raw_pair[2]();
575 clang_analyzer_eval(p[0].p1 == 0); // expected-warning{{UNKNOWN}}
576 clang_analyzer_eval(p[0].p2 == 0); // expected-warning{{UNKNOWN}}
577 clang_analyzer_eval(p[1].p1 == 0); // expected-warning{{UNKNOWN}}
578 clang_analyzer_eval(p[1].p2 == 0); // expected-warning{{UNKNOWN}}
579 }
580
581 struct initializing_pair {
582 public:
583 int x;
584 raw_pair y;
585 initializing_pair() : x(), y() {}
586 };
587
588 void testFieldInitializers() {
589 initializing_pair p;
590 clang_analyzer_eval(p.x == 0); // expected-warning{{TRUE}}
591 clang_analyzer_eval(p.y.p1 == 0); // expected-warning{{TRUE}}
592 clang_analyzer_eval(p.y.p2 == 0); // expected-warning{{TRUE}}
593 }
594
595 struct subclass : public raw_pair {
596 subclass() = default;
597 };
598
599 void testSubclass() {
600 subclass p;
601 clang_analyzer_eval(p.p1 == 0); // expected-warning{{garbage}}
602 }
603
604 struct initializing_subclass : public raw_pair {
605 initializing_subclass() : raw_pair() {}
606 };
607
608 void testInitializingSubclass() {
609 initializing_subclass p;
610 clang_analyzer_eval(p.p1 == 0); // expected-warning{{TRUE}}
611 clang_analyzer_eval(p.p2 == 0); // expected-warning{{TRUE}}
612 }
613
614 struct pair_wrapper {
615 pair_wrapper() : p() {}
616 raw_pair p;
617 };
618
619 struct virtual_subclass : public virtual pair_wrapper {
620 virtual_subclass() {}
621 };
622
623 struct double_virtual_subclass : public virtual_subclass {
624 double_virtual_subclass() {
625 // This previously caused a crash because the pair_wrapper subobject was
626 // initialized twice.
627 }
628 };
Jordan Rosed8dfae62013-09-11 16:46:50 +0000629
630 class Empty {
631 public:
632 Empty();
633 };
634
635 class PairContainer : public Empty {
636 raw_pair p;
637 public:
638 PairContainer() : Empty(), p() {
639 // This previously caused a crash because the empty base class looked
640 // like an initialization of 'p'.
641 }
642 PairContainer(int) : Empty(), p() {
643 // Test inlining something else here.
644 }
645 };
646
647 class PairContainerContainer {
648 int padding;
649 PairContainer pc;
650 public:
651 PairContainerContainer() : pc(1) {}
652 };
Jordan Rosebe35df12013-06-25 01:56:08 +0000653}
Jordan Rosebe2e1b12013-07-17 17:16:33 +0000654
655namespace InitializerList {
656 struct List {
657 bool usedInitializerList;
658
659 List() : usedInitializerList(false) {}
660 List(std::initializer_list<int>) : usedInitializerList(true) {}
661 };
662
663 void testStatic() {
664 List defaultCtor;
665 clang_analyzer_eval(!defaultCtor.usedInitializerList); // expected-warning{{TRUE}}
666
667 List list{1, 2};
668 clang_analyzer_eval(list.usedInitializerList); // expected-warning{{TRUE}}
669 }
670
671 void testDynamic() {
672 List *list = new List{1, 2};
673 // FIXME: When we handle constructors with 'new', this will be TRUE.
674 clang_analyzer_eval(list->usedInitializerList); // expected-warning{{UNKNOWN}}
675 }
676}
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700677
678namespace PR19579 {
679 class C {};
680
681 void f() {
682 C();
683 int a;
684
685 extern void use(int);
686 use(a); // expected-warning{{uninitialized}}
687 }
688
689 void g() {
690 struct S {
691 C c;
692 int i;
693 };
694
695 // This order triggers the initialization of the inner "a" after the
696 // constructor for "C" is run, which used to confuse the analyzer
697 // (is "C()" the initialization of "a"?).
698 struct S s = {
699 C(),
700 ({
701 int a, b = 0;
702 0;
703 })
704 };
705 }
706}