summaryrefslogtreecommitdiffstats
path: root/tests/cxx/badinc.cc
blob: 29867982541db4a7424167c0e559b4673d1183ca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
//===--- badinc.cc - test input file for iwyu -----------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// IWYU_ARGS: -Xiwyu --mapping_file=tests/cxx/badinc.imp -std=gnu++98 -I .

// This is a unittest for include-what-you-use.
//
// NOTE: Historically, all end-to-end testing was done in this file,
// NOTE: which is why it is so large and covers so many things.
// NOTE: However, new tests should *NOT* be added to this file.
// NOTE: Instead, create a new .cc file in this directory (tests/cxx/)
// NOTE: that tests just one aspect of include-what-you-use.
//
// This unittest tries to test most combination of good and bad
// possibilities: functions that are and aren't declared in the
// right place, vars that are and aren't declared in the right
// place, var types that are and aren't declared in the right place.
// We get the list of types-of-interest from
//   https://developer.mozilla.org/En/Dehydra/Object_Reference#Type_Objects
//
// There are several files (this is not necesarily a complete list):
//    badinc.cc: this file, part of the 'compilation unit'.
//    badinc.h: also part of the 'compilation unit'.
//    badinc-inl.h: also part of the 'compilation unit'.
//    badinc-d1.h: directly included from badinc.cc
//    badinc-d2.h: directly included from badinc.h and badinc.cc (ptr only use)
//    badinc-d3.h: included from badinc_d1.h and badinc.h: a direct include
//    badinc-d4.h: included from badinc.h: tests operators and ptr-only
//    badinc-i1.h: included from badinc_d1.h -- an indirect include
//    badinc-i2.h: included from badinc_d2.h and from badinc_i1.h
//    badinc-i3.h: included from badinc_d3.h (forward declarations only).
//    badinc-i4.h: included from badinc_d1.h (macro definitions only).
//    badinc-i5.h: included from badinc_i1.h (unused macro definitions only).
//    badinc-i6.h: included from badinc_i1.h (more macro definitions).
//
// Every IWYU violation is commented, in the line above, by what the
// violation is:
//   // IWYU: <symbol or type name> is...*<file where type is defined>
// The '...*' is just a normal '.*'.  The extra dots are added to improve
// readability.

#define USED_INC    "tests/cxx/badinc-d4.h"
#define UNUSED_INC  <locale>

#if 0
// computed #includes.
#include <locale>
#include "tests/cxx/badinc-d4.h"
#endif

// Some of the #include lines are deliberately formatted wrong, in
// order to test that IWYU handles them correctly.
#include  <math.h>    // not actually used
#include <typeinfo>   // for typeid
#include "tests/cxx/badinc-inl.h"
#include  "tests/cxx/badinc.h"
#include   "tests/cxx/badinc-d1.h"
#include "tests/cxx/badinc-d2.h"
#include  USED_INC    // testing computed #includes
#include  <string>    // not sorted properly (before the #include ""'s).
// The following line is needed, but use a 'keep' pragma anyway.
#include <fstream>    // IWYU pragma: keep
#include <algorithm>  // for find
#include UNUSED_INC
// The following ilne is not needed, but use a 'keep' pragma anyway.
#include <setjmp.h>   // IWYU pragma: keep
#include <clocale>    // for NULL (though we get NULL via badinc.h's stdio.h).
                      // clocale is chosen as it provides NULL but not size_t.
#include <algorithm>  // try #including the same file twice
#include <algorithm>  // ...and then 3 times

// This should given an IWYU error even though MACRO_CALLING_I1_MACRO
// is never actually called.
// IWYU: MACRO_CALLING_I6_FUNCTION is...*badinc-i1.h
#define MACRO_CALLING_I1_MACRO    MACRO_CALLING_I6_FUNCTION

// IWYU: I1_MACRO_SYMBOL_WITHOUT_VALUE is...*badinc-i1.h
#ifdef I1_MACRO_SYMBOL_WITHOUT_VALUE
int i1_macro_symbol_without_value_var;
#endif

// IWYU: I1_MACRO_SYMBOL_WITHOUT_VALUE is...*badinc-i1.h
#ifndef I1_MACRO_SYMBOL_WITHOUT_VALUE
int i1_macro_symbol_without_value_var;
#endif

// IWYU: I1_MACRO_SYMBOL_WITH_VALUE is...*badinc-i1.h
#if I1_MACRO_SYMBOL_WITH_VALUE
int i1_macro_symbol_with_value_var;
#endif

// IWYU: I1_MACRO_SYMBOL_WITH_VALUE0 is...*badinc-i1.h
#if I1_MACRO_SYMBOL_WITH_VALUE0
int 11_macro_symbol_with_value0_var;
// IWYU: I1_MACRO_SYMBOL_WITH_VALUE2 is...*badinc-i1.h
#elif I1_MACRO_SYMBOL_WITH_VALUE2
int i1_macro_symbol_with_value2_var;
#endif

// IWYU: I1_MACRO_SYMBOL_WITHOUT_VALUE is...*badinc-i1.h
#if defined(I1_MACRO_SYMBOL_WITHOUT_VALUE)
int i1_macro_symbol_without_value_var2;
#endif

#if 0
// IWYU: I1_MACRO_SYMBOL_WITHOUT_VALUE is...*badinc-i1.h
#elif defined(I1_MACRO_SYMBOL_WITHOUT_VALUE)
int i1_macro_symbol_without_value_var3;
#endif

// IWYU: I1_MACRO_SYMBOL_WITH_VALUE is...*badinc-i1.h
// IWYU: I1_MACRO_SYMBOL_WITH_VALUE2 is...*badinc-i1.h
#if I1_MACRO_SYMBOL_WITH_VALUE && I1_MACRO_SYMBOL_WITH_VALUE2
int i1_macro_symbol_with_value_and_value2_var;
#endif

// A slightly more complex example.
#if 0
// IWYU: I1_MACRO_SYMBOL_WITH_VALUE is...*badinc-i1.h
// IWYU: I1_MACRO_SYMBOL_WITH_VALUE2 is...*badinc-i1.h
#elif !I1_MACRO_SYMBOL_WITH_VALUE && !(I1_MACRO_SYMBOL_WITH_VALUE2)
int i1_macro_symbol_with_value_and_value2_var2;
#endif

// Test we don't try to report an iwyu violation for a built-in macro
#if __LINE__ || __STDC__ || defined(__cplusplus)
#endif

// Using declarations and statements.
// TODO(csilvers): I don't see a consistent way to say whether
// "i1_ns2" is an iwyu violation or not, since namespaces can be
// re-opened in many different files.  So let this go, even though all
// uses of this namespace are in badinc-i1.h; we'll get the iwyu
// violation later when we try to use symbols from i1_ns2.
// IWYU: i1_ns2 is defined in...*which isn't directly #included.
using namespace i1_ns2;
using i1_ns3::i1_int_global3;
// IWYU: i1_ns4 is...*badinc-i1.h
namespace cc_ns_alias = i1_ns4;
using i1_ns::I1_NamespaceStruct;
// IWYU: i1_ns::I1_NamespaceTemplateFn is...*badinc-i1.h
using i1_ns::I1_NamespaceTemplateFn;
// TODO(csilvers): mark this using declaration as redundant and remove it?
// IWYU: i1_ns::I1_UnusedNamespaceStruct needs a declaration
using i1_ns::I1_UnusedNamespaceStruct;
// TODO(csilvers): mark this using statement as redundant and remove it.
// IWYU: i1_ns5 is defined in...*which isn't directly #included.
using namespace i1_ns5;

// We do some proper forward-declaring here, and also some unnecessary
// forward-declaring.  And of course we leave a lot of necessary
// forward-declaring out.
class I3_ForwardDeclareClass;
template<typename T>
struct I3_SimpleForwardDeclareTemplateStruct;
class I3_UnusedClass;
namespace i3_ns1 { namespace i3_ns2 { namespace i3_ns3 {
struct I3_ForwardDeclareNamespaceStruct;
} } }

class ForwardDeclareOnlyClass;
ForwardDeclareOnlyClass* forward_declare_only;

class MacroClass;

class ForwardDeclareOnlyForTypedefClass;
typedef ForwardDeclareOnlyForTypedefClass NeedFwdDeclarationForThisClass;

// Here's an example of specialization where we never define the base
// class.  IWYU should not ask us to remove the initial declaration!
template <class T> struct Cc_OnlySpecializedStruct;
template<> struct Cc_OnlySpecializedStruct<int> { };
Cc_OnlySpecializedStruct<int>* cc_onlyspecializedstruct_ptr;

// Try a type that only needs a forward-declare because of the language linkage.
extern "C" struct Cc_C_Struct;
struct Cc_C_Struct* cc_c_struct_ptr = NULL;

// The types.
typedef std::string Cc_string;   // Nobody should use this.
// IWYU: I1_Class is...*badinc-i1.h
typedef I1_Class Cc_typedef;
// IWYU: kI1ConstInt is...*badinc-i1.h
// IWYU: I1_Class is...*badinc-i1.h
typedef I1_Class Cc_typedef_array[kI1ConstInt];
// We need the full definition of template types (I1_TemplateClass in
// this case) since we're re-exporting them.  Note we need a full
// definition even of I2_Class, since we don't know if clients will be
// using the no-arg Cc_tpl_typedef ctor, which requires the full
// definition of I2_Class.
// IWYU: I1_Class needs a declaration
// IWYU: I2_Class needs a declaration
// IWYU: I1_TemplateClass is...*badinc-i1.h.*#included\.
// IWYU: I1_TemplateClass is...*badinc-i1.h.*for autocast
// IWYU: I1_TemplateClass is...*badinc-i1.h.*for fn return type
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
typedef I1_TemplateClass<I1_TemplateClass<I1_Class,I2_Class> > Cc_tpl_typedef;
// TODO(csilvers): it would be nice to be able to take this line out and
// still have the above tests pass:
Cc_tpl_typedef cc_tpl_typedef;
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::I2_Class is...*badinc-i2-inl.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
// IWYU: I2_Class::InlFileFn is...*badinc-i2-inl.h
// IWYU: I2_Class::InlFileTemplateFn is...*badinc-i2-inl.h
// IWYU: I2_Class::InlFileStaticFn is...*badinc-i2-inl.h
typedef I2_Class Cc_I2_Class_Typedef;
// IWYU: I1_Struct needs a declaration
// IWYU: OperateOn is...*badinc-i1.h
typedef H_TemplateStruct<I1_Struct> Cc_H_TemplateStruct_I1Class_Typedef;

// IWYU: kI1ConstInt is...*badinc-i1.h
enum Cc_Enum { CC1 = kI1ConstInt };

struct Cc_Struct {
  // IWYU: kI1ConstInt is...*badinc-i1.h
  int a : kI1ConstInt;
  float b;
  // IWYU: I1_Enum is...*badinc-i1.h
  I1_Enum d;
};

// This is best instantiated with T=I1_Class. :-)
template<class T> class Cc_TypenameTemplateStruct {
  typename T::I1_Class_int a;
  struct T::NestedStruct c;
};

// Needs full type information for CC_Subclass's (implicit) dtor of scoped_ptr.
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_ThisClassIsOnlySubclassed is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
class Cc_Subclass : public I2_ThisClassIsOnlySubclassed {
 public:
  // IWYU: I1_MemberPtr is...*badinc-i1.h
  Cc_Subclass() : ptr_(&I1_MemberPtr::a), scoped_ptr_() {
    // IWYU: I1_MemberPtr is...*badinc-i1.h
    I1_MemberPtr m;
    (m.*ptr_)();
    a();   // defined in the superclass
  }
  // IWYU: I1_MemberPtr is...*badinc-i1.h
  int (I1_MemberPtr::*ptr_)();
  // IWYU: I2_Class needs a declaration
  H_ScopedPtr<I2_Class> scoped_ptr_;

  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  int foo() throw(I1_Class, I2_Class);
};

// IWYU: I2_ThisClassIsOnlySubclassed is...*badinc-i2.h
class MultipleInheritanceSubclass : public I2_ThisClassIsOnlySubclassed,
                                    // IWYU: I2_Class is...*badinc-i2.h
                                    virtual I2_Class {
 public:
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Struct is...*badinc-i2.h
  // IWYU: I2_MACRO is...*badinc-i2.h
  MultipleInheritanceSubclass() : I2_Class(I2_Struct().a + I2_MACRO) { }
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  ~MultipleInheritanceSubclass() { }
};

// This template struct is never instantiated, and neither is the
// struct that includes it as a member.  Even so, we should call its
// methods to be instantiated for our testing, so we notice the
// requirement for I1_Class's full type (via the default constructor).
template<class T> struct NeverCalledTemplateStruct {
  NeverCalledTemplateStruct() { T t; }
};
// IWYU: I1_Class is...*badinc-i1.h
struct NeverCalledStruct {
  // IWYU: I1_Class needs a declaration
  NeverCalledTemplateStruct<I1_Class> c;
};

struct Cc_DeclOrderStruct {
  void Fn() {
    // This should not require a fwd-decl even though it's not defined
    // until after its use: that's legal inside a class/struct.
    NestedStructDefinedAfterUse* n;
    (void)n;
  }
  struct NestedStructDefinedAfterUse {};
};

// IWYU: I1_Enum is...*badinc-i1.h
template<class T, I1_Enum E = I11> struct Cc_TemplateStruct { };
// IWYU: I1_Enum is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
template<I1_Enum E> struct Cc_TemplateStruct<I1_Class, E> { I1_Class i; };
// IWYU: I1_Class needs a declaration
// IWYU: I1_Enum is...*badinc-i1.h
template<> struct Cc_TemplateStruct<I1_Class, I12> { I1_Class* i; };
// TODO(csilvers): I1_Class is technically forward-declarable.
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
template<class T = I1_Class, I1_Enum E = I11> class Cc_DeclareOnlyTemplateClass;

// IWYU: I2_Class needs a declaration
const I2_Class& Cc_Function(
    // IWYU: I1_Class is...*badinc-i1.h
    I1_Class) {
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  static I2_Class retval;   // something we can safely return a reference to
  return retval;
}

// Now try the same, but with templatized functions (which can't have
// default arguments, who knew?)
// IWYU: I1_Enum is...*badinc-i1.h
template<class T, I1_Enum E> int Cc_TemplateFunction() { return T().a(); }
// IWYU: I1_Class needs a declaration
// IWYU: I1_Enum is...*badinc-i1.h
template<> int Cc_TemplateFunction<I1_Class, I12>() { return 3; }
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
template<> int Cc_TemplateFunction<I1_Class, I13>() { return I1_Class().a(); }
// IWYU: I1_Enum is...*badinc-i1.h
template<class T, I1_Enum E> T Cc_DeclareOnlyTemplateFunction();
// TODO(csilvers): also test calling these functions, including an
//                 implicit specialization.

template<class T> int Cc_TemplateNewer() { new T; return 0; }

// Here's a tricky example of template specialization taken from
// http://msdn.microsoft.com/en-us/library/3967w96f%28VS.80%29.aspx
template <class T> struct Cc_PTS {
  enum { IsPointer = 0, IsPointerToDataMember = 0 };
};
template <class T> struct Cc_PTS<T*> {
  enum { IsPointer = 1, IsPointerToDataMember = 0 };
};
template <class T, class U> struct Cc_PTS<T U::*> {
  enum { IsPointer = 0, IsPointerToDataMember = 1 };
};

template<class T,int> class Cc_TemplateSubclass : public H_TemplateTypedef { };

// Let's test that we detect overloaded functions correctly when all
// overloads are in the same file, and then when they're in different files.
template<typename T> void CallOverloadedFunctionSameFile(T t) {
  // IWYU: I1_OverloadedFunction is...*badinc-i1.h
  I1_OverloadedFunction(t);
}

template<typename T> void CallOverloadedFunctionDifferentFiles(T t) {
  // Since this method is overloaded in several places, we do the iwyu
  // check at the instantiation site, not here.
  I1_And_I2_OverloadedFunction(t);
}

template<typename T> void CallOverloadWithUsingShadowDecl(T t) {
  // This is only defined in one place, but because we get to it via
  // a using expression, it generates a UsingShadowExpr.  Make sure we
  // "see through" that properly.
  // IWYU: i1_ns::I1_NamespaceTemplateFn is...*badinc-i1.h
  I1_NamespaceTemplateFn(t);
}

// This is defining a class declared in badinc-i1.h, but I think it's
// correct that it's not an IWYU violation to leave out badinc-i1.h.
class I1_DefinedInCc_Class {
 public:
  // IWYU: I1_Enum is...*badinc-i1.h
  I1_Enum i1_enum;
};

// For function declarations, we don't need complete type info for
// arguments.  But we do for the return type unless we explicitly
// say we don't want to (by providing a forward-declare).
// IWYU: I1_Class is...*badinc-i1.h.*for fn return type
// IWYU: I1_Class needs a declaration
// IWYU: I2_Struct needs a declaration
I1_Class Cc_DeclareOnlyFn(I2_Struct i2_class);

// IWYU: I2_Struct needs a declaration
I3_ForwardDeclareClass Cc_DeclareOnlyFnWithFwdDecl(I2_Struct i2_class);


class Cc_DeclareOnlyClass {
  // IWYU: I1_Class needs a declaration
  Cc_DeclareOnlyClass(I1_Class);
  // IWYU: I2_Struct needs a declaration
  I3_ForwardDeclareClass DeclareOnlyFn(I2_Struct);
};

// The implicit constructor for i1tc uses I2_Class.
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
struct Cc_ImplicitConstructorStruct {
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  I1_TemplateClass<I1_Class, I2_Class> i1tc;
};

// The implicit destructor for i1tc uses I2_Class.
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
struct Cc_ImplicitInitializerStruct {
  // The implicit initializer of i1tc creates an I2_Class in the I1_TC ctor
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  Cc_ImplicitInitializerStruct() {}
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  I1_TemplateClass<I1_Class, I2_Class> i1tc;
};

// The implicit destructor for sp uses I2_Class.
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
struct Cc_ImplicitDestructorStruct {
  Cc_ImplicitDestructorStruct() : sp() { }
  // IWYU: I2_Class needs a declaration
  H_ScopedPtr<I2_Class> sp;
};

// IWYU: EmptyDestructorClass is...*badinc-i1.h
EmptyDestructorClass::~EmptyDestructorClass() { }
// IWYU: I2_Enum is...*badinc-i2.h
I2_Enum H_Class::ff_ = I22;
// IWYU: I2_Enum is...*badinc-i2.h
int H_Class::f(I2_Enum i2_enum) { return 1; }
// IWYU: I2_Enum is...*badinc-i2.h
/*static*/ int H_Class::static_out_of_line(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = NULL;
  return 1;
}
// IWYU: I2_Enum is...*badinc-i2.h
int H_Class::H_NestedStruct::nested(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = 0;
  return 1;
}
// IWYU: I2_Enum is...*badinc-i2.h
int H_Class::H_NestedStruct::static_nested(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = 0;
  return 1;
}
class H_Class::H_Class_UnusedSubdecl {};
void H_Class::DefinedInBadincCc() {}
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Struct is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
H_Pimpl_ExplicitCtorDtor::~H_Pimpl_ExplicitCtorDtor() {}

template<typename FOO> FOO H_TemplateClass<FOO>::h_template_foo_static_;
template<typename FOO>
// IWYU: I2_Enum is...*badinc-i2.h
FOO H_TemplateClass<FOO>::static_out_of_line(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = NULL;
  return FOO();
}
template<typename FOO>
// IWYU: I2_Enum is...*badinc-i2.h
int H_TemplateClass<FOO>::H_TplNestedStruct::tplnested(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = NULL;
  return 1;
}
template<typename FOO>
// IWYU: I2_Enum is...*badinc-i2.h
FOO H_TemplateClass<FOO>::H_TplNestedStruct::static_tplnested(I2_Enum i2_enum) {
  // IWYU: I1_Class needs a declaration
  I1_Class* i1_class;
  i1_class = NULL;
  return FOO();
}

// IWYU: I2_Class is...*badinc-i2.h
int I2_Class::CcFileFn() { return 1; }

// IWYU: I2_TemplateClass is...*badinc-i2.h
template<typename FOO> int I2_TemplateClass<FOO>::CcFileFn() {
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  // IWYU: I2_TemplateClass needs a declaration
  // IWYU: I2_TemplateClass::I2_TemplateClass<.*> is...*badinc-i2-inl.h
  I2_TemplateClass<int>* ptr = new I2_TemplateClass<int>(42, "hi");  // NewExpr

  // IWYU: I2_TemplateClass is...*badinc-i2.h
  // IWYU: I2_TemplateClass::I2_TemplateClass<.*> is...*badinc-i2-inl.h
  // IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
  I2_TemplateClass<int> x(42, "hi");  // CXXConstructExpr
  (void)x;

  // IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  delete ptr;  // CXXDeleteExpr

  // IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  delete this;  // CXXDeleteExpr

  // IWYU: I2_TemplateClass::InlFileTemplateClassFn is...*badinc-i2-inl.h
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  return InlFileTemplateClassFn();  // CXXMemberCallExpr
}


// Let's make some global variables of various types.

// badinc.cc
Cc_Struct cc_struct;
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
Cc_TypenameTemplateStruct<I1_Class> cc_typename_template_struct;
Cc_Enum cc_enum = CC1;
Cc_Subclass cc_subclass;
MultipleInheritanceSubclass cc_multipleinheritancesubclass;
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
int cc_template_function_val = Cc_TemplateFunction<I1_Class, I11>();
int cc_tricky_template_function_val =
    // IWYU: I1_Class needs a declaration
    // IWYU: kI1ConstInt is...*badinc-i1.h
    // IWYU: I1_Enum is...*badinc-i1.h
    Cc_TemplateFunction<I1_Class, kI1ConstInt == 4 ? I12 : I13>();  // is I13
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
int cc_tpl_newer = Cc_TemplateNewer<I1_Class>();
// IWYU: I1_Class needs a declaration
int cc_ptr_check1 = Cc_PTS<I1_Class>::IsPointer;
// IWYU: I1_Class needs a declaration
int cc_ptr_check2 = Cc_PTS<I1_Class*>::IsPointer;
// IWYU: I1_Class needs a declaration
int cc_ptr_check3 = Cc_PTS<int I1_Class::*>::IsPointer;

// badinc.h
H_Typedef h_typedef;
// TODO(csilvers): it would be nice to be able to remove this and
//   still have all tests pass.  As it is, we need this to instantiate
//   the template's underlying type, which we need to find its violations.
// We are responsible for the underlying type of this typedef because
// the .h file has signalled (by forward-declaring the underlying type,
// and not directly including it) that it doesn't want responsibility.
// IWYU: I2_TypedefOnly_Class is...*badinc-i2.h
H_I1_Class_Typedef h_i1_class_typedef;
H_I2Enum_Set h_i2enum_set;
H_I2Enum_Set* h_i2enum_set_ptr;
H_Class h_class;
H_Class h_class2(2);
H_StructPtr h_structptr;
H_TemplateClass<H_Enum> h_templateclass1(H1);
// IWYU: I1_Enum is...*badinc-i1.h
H_TemplateClass<I1_Enum> h_templateclass2(I11);
// IWYU: I1_Struct needs a declaration
H_TemplateStruct<I1_Struct> h_template_struct;
// IWYU: I1_Struct needs a declaration
H_TemplateStructHelper<I1_Struct> h_template_struct_helper;
// IWYU: I1_Struct needs a declaration
H_TemplateStruct<I1_Struct>* h_template_struct_ptr;
// IWYU: I1_Struct needs a declaration
H_TemplateStruct<I1_Struct, Cc_Struct> h_template_struct2;
// We need full type info for i1_templateclass because we never
// fwd-declare a class with default template parameters.
// IWYU: I1_TemplateClass is...*badinc-i1.h
H_TemplateStruct<I1_TemplateClass<int> > h_template_struct_tplclass_arg;
// TODO(csilvers): this should be attributed to the .h, since it comes
// via a default template argument.
// IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
H_TemplateTemplateClass<> h_templatetemplateclass;
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class needs a declaration
// IWYU: I2_TemplateFn is...*badinc-i2.h
H_FunctionPtr h_functionpointer = I2_TemplateFn<I2_Class*>;
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class needs a declaration
// IWYU: I2_TemplateFn is...*badinc-i2.h
H_FunctionPtr h_functionpointer_amp = &((I2_TemplateFn<I2_Class*>));
H_FunctionPtr &h_functionpointer_ref = h_functionpointer;
// IWYU: H_Class::H_Class_DefinedInI1 is...*badinc-i1.h
H_Class::H_Class_DefinedInI1 h_class_subclass_in_i1;
// Note: H_Class::H_Class_DefinedInI1 is forward-declared in badinc.h,
// hence we get it for free.
H_Class::H_Class_DefinedInI1* h_class_subclass_in_i1_ptr;
// This requires the full type for two reasons: because of the
// H_ScopedPtr typedef and because we "own" the destructor call.
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
H_ScopedPtr<I1_Class> h_scoped_ptr;
// This should also require I1_Class, because of the scoped_ptr it holds.
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
H_ScopedPtrHolder<I1_Class> h_scoped_ptr_holder;

InlH_FunctionPtr inlh_functionptr = InlH_Function();  // badinc-inl.h

D1_Class d1_class;       // badinc-d1.h
D1_TemplateClass<D1_Enum> d1_templateclass1(D11);
// IWYU: I2_Enum is...*badinc-i2.h
D1_TemplateClass<I2_Enum> d1_templateclass2(I2_LAST);
// IWYU: I2_Enum is...*badinc-i2.h
D1_TemplateClass<I2_Enum> *d1_templateclass2_ptr;
// IWYU: I2_Enum is...*badinc-i2.h
D1_TemplateClass<I2_Enum> &d1_templateclass_ref = d1_templateclass2;
D1_TemplateStructWithDefaultParam<D1_Enum> d1_templatestructwithdefaultparam;
int d1_fn = D1Function();

// IWYU: D2_ForwardDeclareClass needs a declaration
D2_ForwardDeclareClass* d2_forward_declare_class;   // badinc-d2.h
D2_Subclass* d2_subclass_ptr_array[10];
// The reinterpret-cast here should mean we don't need the full type.
D2_Class& d2_classref = reinterpret_cast<D2_Class&>(*d2_subclass_ptr_array[0]);

// IWYU: d3_namespace::D3_Struct needs a declaration
d3_namespace::D3_Struct* d3_struct_ptr;   // badinc-d3.h

// Now the expected errors: badinc-i1.h and badinc_i2.h
// IWYU: I1_Enum is...*badinc-i1.h
I1_Enum i1_enum;
// IWYU: I1_Typedef is...*badinc-i1.h
I1_Typedef i1_typedef;
// IWYU: I1_Struct is...*badinc-i1.h
I1_Struct i1_struct;
// IWYU: i1_ns::I1_NamespaceStruct is...*badinc-i1.h
I1_NamespaceStruct i1_namespace_struct;
// IWYU: I1_Union is...*badinc-i1.h
I1_Union i1_union;
// IWYU: I1_UnnamedStruct is...*badinc-i1.h
I1_UnnamedStruct i1_unnamedstruct;
// Test having this ns class forward-declared first, then used fully.
// IWYU: I1_NamespaceClass needs a declaration
i1_ns::I1_NamespaceClass* i1_namespace_class_ptr;
// A declaration which includes namespace-qualification cannot serve
// as a forward-declaration.
// IWYU: i1_ns::I1_NamespaceClass needs a declaration
class i1_ns::I1_NamespaceClass* i1_namespace_class_ptr2;
// IWYU: i1_ns::I1_NamespaceClass is...*badinc-i1.h
i1_ns::I1_NamespaceClass i1_namespace_class;
// As above, a namespace-qualified friend declaration requires a
// previous full declaration.
// IWYU: I1_NamespaceClass needs a declaration
class FriendsNamespaceClass { friend class i1_ns::I1_NamespaceClass; };
namespace i1_ns {
// No forward declaration needed if no namespace-qualification.
class FriendsNamespaceClassInNS { friend class I1_NamespaceClass; };
}  // namespace i1_ns

// IWYU: I1_Class is...*badinc-i1.h
I1_Class i1_class;
// IWYU: I1_Class is...*badinc-i1.h
I1_Class i1_class_init(5);
// IWYU: I1_Class is...*badinc-i1.h
I1_Class i1_class_array[10];
// IWYU: I1_Class needs a declaration
// IWYU: kI1ConstInt is...*badinc-i1.h
I1_Class *i1_class_array_ptr[kI1ConstInt];
// IWYU: I1_Class needs a declaration
I1_Class *i1_class_ptr;
// IWYU: I1_Class needs a declaration
I1_Class &i1_class_ref = i1_class;
// IWYU: I1_Class is...*badinc-i1.h
I1_Class::NestedStruct *i1_nestedstruct_ptr;
// Even adding an explicit 'struct' doesn't make it fwd-declarable.
// IWYU: I1_Class is...*badinc-i1.h
struct I1_Class::NestedStruct *i1_nestedstruct_ptr2;
// IWYU: I1_Class is...*badinc-i1.h
I1_Class::NestedStruct i1_nestedstruct;
// IWYU: I1_Class is...*badinc-i1.h
struct I1_Class::NestedStruct i1_nestedstruct2;

// IWYU: I1_Base needs a declaration
I1_Base *i1_base_ptr;

// I1_Enum is here twice because we need it in two places: once for
// the I1_TemplateClass<I1_Enum> object, and once in the constructor.
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
I1_TemplateClass<I1_Enum> i1_templateclass(I11);
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<int> i1_templateclass2(10);
// IWYU: I1_Class needs a declaration
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<I1_Class*> i1_templateclass3(NULL);
// We need full type info for i1_templateclass because we never
// fwd-declare a class with default template parameters.
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
I1_TemplateClass<I1_Class>* i1_templateclass_ptr;
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<I1_Class> i1_templateclass_object;
// IWYU: std::vector is...*<vector>
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
I1_TemplateClass<std::vector<I1_Class> > i1_nested_templateclass(i1_union);
// We need full type info for i1_templateclass because we never
// fwd-declare a class with default template parameters.
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
// IWYU: std::vector is...*<vector>
I1_TemplateClass<std::vector<I1_Class> >* i1_nested_templateclass_ptr;
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
// IWYU: std::vector is...*<vector>
I1_TemplateClass<std::vector<I1_Class>*> i1_nested_templateclass_ptr2(NULL);
// IWYU: I1_TemplateSubclass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I2_Class needs a declaration
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
I1_TemplateSubclass<I1_Class, I2_Class> i1_template_subclass;
// IWYU: I1_Enum is...*badinc-i1.h
// IWYU: std::vector is...*<vector>
std::vector<I1_Enum> enum_vec;
// IWYU: std::vector is...*<vector>
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
I1_TemplateClass<std::vector<I1_Enum> > i1_nested_templateclass_enum(enum_vec);
// We need full type info for i1_templateclass because we never
// fwd-declare a class with default template parameters.
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
// IWYU: std::vector is...*<vector>
I1_TemplateClass<std::vector<I1_Enum> >* i1_nested_templateclass_enum_ptr;
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_Enum is...*badinc-i1.h
// IWYU: std::vector is...*<vector>
I1_TemplateClass<std::vector<I1_Enum>*> i1_nested_templateclass_enum_ptr2(NULL);
// Note: we have to avoid the most vexing parse, here!
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<D1_I1_Typedef> i1_tplclass_with_typedef((D1_I1_Typedef()));
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<D1_I1_Typedef*> i1_templateclass_with_typedef_ptr(NULL);
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<D1_Enum> i1_templateclass_d(D11);
// I1_Class is needed as a used template arg to this template-constructor.
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I2_Struct needs a declaration
// IWYU: I2_Struct is...*badinc-i2.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
I1_TemplateClass<I2_Struct> i1_templateclass_tpl_ctor(i1_class, true);
// Accessing a macro in the same file should still cause an iwyu warning.
// The trick here is that the NNS doesn't have its own location info.
#define CC_DEFINE_VAR(typ)  typ cc_define_var ## __LINE__
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I2_Class is...*badinc-i2.h
// IWYU: I2_Class needs a declaration
CC_DEFINE_VAR(I1_TemplateClass<I2_Class>::I1_TemplateClass_int);

// IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
I1_TemplateMethodOnlyClass<I1_Class> i1_template_method_only_class;
// IWYU: I2_TemplateClass needs a declaration
// IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
// IWYU: I1_Class needs a declaration
I1_TemplateMethodOnlyClass<I2_TemplateClass<const I1_Class> > i1_tpl_tpl_class;
// IWYU: I1_TemplateClassFwdDeclaredInD2 needs a declaration
I1_TemplateClassFwdDeclaredInD2<int, float>* i1_tpl_class_fwd_declared_in_d2;
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_TypedefOnly_Class is...*badinc-i1.h
I1_TypedefOnly_Class<I1_Class> i1_typedefonly_class;
// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
// IWYU: I1_TypedefOnly_Class is...*badinc-i1.h
I1_TypedefOnly_Class<I1_Class>::i i1_typedefonly_class_int;
// IWYU: I1_I2_Class_Typedef is...*badinc-i1.h
int i1_i2_class_typedef_int = I1_I2_Class_Typedef::s;

// IWYU: I1_Subclass is...*badinc-i1.h
I1_Subclass i1_subclass;

// IWYU: I1_ManyPtrStruct needs a declaration
I1_ManyPtrStruct ***i1_manyptrstruct_ptr_ptr_ptr;
// IWYU: I1_ClassPtr is...*badinc-i1.h
I1_ClassPtr i1_classptr;
// IWYU: I1_FunctionPtr is...*badinc-i1.h
// IWYU: I1_Function is...*badinc-i1.h
I1_FunctionPtr i1_functionptr = I1_Function;
// IWYU: I1_FunctionPtr is...*badinc-i1.h
I1_FunctionPtr *i1_functionptr_ptr = &i1_functionptr;
// IWYU: I1_ForwardDeclareClass needs a declaration
I1_ForwardDeclareClass* i1_forwarddeclareptr;
// IWYU: I1_Function is...*badinc-i1.h
int i1_function_value = I1_Function(0);

// Two different uses of an indirect global.  The first is a function call
// which is exposed in the compiler-generated function for global
// constructors/destructors.  The second is similar, but it requires no
// call since its a simple initialization.
// IWYU: i1_GlobalFunction is...*badinc-i1.h
int i1_globalfunctionval = i1_GlobalFunction();
// IWYU: i1_GlobalFunction is...*badinc-i1.h
int (*i1_globalfunctionptr)(void) = i1_GlobalFunction;
// IWYU: i1_GlobalFunction is...*badinc-i1.h
int (*i1_globalfunctionptr2)(void) = &i1_GlobalFunction;

// IWYU: I2_InlFileClass is...*badinc-i2-inl.h
I2_InlFileClass i2_inlfileclass;
// IWYU: I2_InlFileTemplateClass is...*badinc-i2-inl.h
I2_InlFileTemplateClass<int> i2_inlfiletemplateclass;
// IWYU: I2_Class...*badinc-i2.h
// IWYU: I2_Class::I2_Class...*badinc-i2-inl.h
// IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
I2_Class i2_class_with_inl_constructor("calling ctor in badinc-i2-inl.h");
// IWYU: I2_TemplateClass...*badinc-i2.h
// IWYU: I2_TemplateClass::I2_TemplateClass<.*> is...*badinc-i2-inl.h
// IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
I2_TemplateClass<int> i2_template_class_with_inl_constructor(4, "inl ctor");
// We don't need a fwd-decl of I2_TypedefOnly_Class; we get that via badinc.h
// IWYU: I1_Class needs a declaration
I2_TypedefOnly_Class<I1_Class>* i1_typedefonly_class_ptr;

// Not an iwyu violation because I explicitly forward-declared this class.
I3_ForwardDeclareClass* i3_forwarddeclareclass;
// IWYU: I3_ForwardDeclareStruct needs a declaration
I3_ForwardDeclareStruct* i3_forwarddeclarestruct;
// Not an iwyu violation because I explicitly forward-declared this class.
I3_SimpleForwardDeclareTemplateStruct<int>* i3_simpleforwarddeclaretplstruct;
// IWYU: I3_ForwardDeclareTemplateStruct needs a declaration
I3_ForwardDeclareTemplateStruct<int, 4, 'b'>* i3_forwarddeclaretemplatestruct;
// Not an iwyu violation because I explicitly forward-declared this class.
i3_ns1::i3_ns2::i3_ns3::I3_ForwardDeclareNamespaceStruct* i3_fdns_struct;
// IWYU: I3_ForwardDeclareNamespaceTemplateStruct needs a declaration
i3_ns1::i3_ns2::i3_ns3::I3_ForwardDeclareNamespaceTemplateStruct<H_Enum, 2>*
  i3_fdtns_struct;

// IWYU: I3_UnnamedNamespaceStruct needs a declaration
i3_ns1::I3_UnnamedNamespaceStruct* i3_unnamed_namespace_struct;

// This shouldn't cause weird iwyu issues between us and badinc.h.
H_USE_CLASS(MacroClass);
// This shouldn't cause badinc.h to need to include us for Cc_Subclass.
H_CREATE_VAR(Cc_Subclass);
// We should be credited for use of I1_Class even though it's in the macro.
// IWYU: I1_Class is...*badinc-i1.h
int identity_i1_class_a = H_IDENTITY(i1_class).a();

// Violations within a namespace (both named an unnamed)
namespace cc_ns {
// IWYU: I1_Typedef is...*badinc-i1.h
I1_Typedef i1_typedef;
}
namespace {
// IWYU: I1_Union is...*badinc-i1.h
I1_Union i1_unnamed_union;
}

// I3_ForwardDeclareClass is not an iwyu violation, because I
// explicitly forward-declare it above.
// IWYU: I3_ForwardDeclareStruct needs a declaration
// IWYU: I1_Class needs a declaration
float SimpleFunction(I3_ForwardDeclareClass* a, I3_ForwardDeclareStruct* b)
    throw(I3_ForwardDeclareClass*, I1_Class*);

// IWYU: I3_ForwardDeclareStruct needs a declaration
// IWYU: I1_Class needs a declaration
float SimpleFunction(I3_ForwardDeclareClass* a, I3_ForwardDeclareStruct* b)
    throw(I3_ForwardDeclareClass*, I1_Class*) {
  return 1.0;
}
float simple_function = SimpleFunction(NULL, NULL);

// IWYU: I3_ForwardDeclareStruct needs a declaration
template<bool Foo> int SimpleConstantTemplateFunction()
    throw(I3_ForwardDeclareStruct&) {
  return Foo;
}
bool simple_constant_template_function = SimpleConstantTemplateFunction<5<3>();

// Let's test the code that distinguishes pointers (and references), a bit.
// IWYU: I3_ForwardDeclareStruct needs a declaration
int SimpleUnusedFunction(const I3_ForwardDeclareStruct& a) {
  return 1;
}
// IWYU: I3_ForwardDeclareStruct needs a declaration
int SimpleUnusedFunction2(I3_ForwardDeclareStruct* a) {
  return 2;
}
// IWYU: I3_ForwardDeclareStruct needs a declaration
int SimpleUnusedFunction3(I3_ForwardDeclareStruct& a,
                          // IWYU: I3_ForwardDeclareStruct needs a declaration
                          I3_ForwardDeclareStruct* b,
                          // IWYU: I3_ForwardDeclareStruct needs a declaration
                          I3_ForwardDeclareStruct** c) {
  return (SimpleUnusedFunction(a) +
          SimpleUnusedFunction(*b) +
          SimpleUnusedFunction(**c) +
          SimpleUnusedFunction2(*c));
}

// Test that we properly detect we need badinc-d4 for operator<<
// (even though we only need a forward-declare for D4_ClassForOperator).
int TestOperator(const D4_ClassForOperator& d4_classop) {
  return 1 << d4_classop;
}

// Test we properly find both uses (one ptr-only and one not) when on same line.
// IWYU: I1_PtrAndUseOnSameLine is...*badinc-i1.h
// IWYU: I1_PtrAndUseOnSameLine needs a declaration
int TestSameLine(I1_PtrAndUseOnSameLine* i1_ptruse) { return i1_ptruse->a(); }

// Test casting: try passing in an I1_SubclassesI2Class* here.
// IWYU: I2_Class needs a declaration
void FunctionTakesI2_Class(I2_Class* d2c) { }

template class D1_TemplateClass<D1_StructPtr>;  // instantiate a few templates
// IWYU: I1_ClassPtr is...*badinc-i1.h
template class D1_TemplateClass<I1_ClassPtr>;
// IWYU: I1_TemplateClass is...*badinc-i1.h
template class I1_TemplateClass<int>;
// IWYU: I1_TemplateClass is...*badinc-i1.h
// IWYU: I1_ClassPtr is...*badinc-i1.h
template class I1_TemplateClass<I1_ClassPtr>;

// Test typedefs on various types of instantiations.
// First, make sure the implicit instantiation instantiates some methods too.
// IWYU: I2_TemplateClass is...*badinc-i2.h
int i2_tpl_class_a = i2_template_class_with_inl_constructor.a();
// IWYU: I2_TemplateClass is...*badinc-i2.h
// IWYU: I2_TemplateClass::I2_TemplateClass<.*> is...*badinc-i2-inl.h
// IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
// IWYU: I2_TemplateClass::InlFileTemplateClassFn is...*badinc-i2-inl.h
typedef I2_TemplateClass<int> Cc_typedef_implicit_instantiation;
// Make sure we can do the same typedef multiple times.
// IWYU: I2_TemplateClass is...*badinc-i2.h
// IWYU: I2_TemplateClass::I2_TemplateClass<.*> is...*badinc-i2-inl.h
// IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
// IWYU: I2_TemplateClass::InlFileTemplateClassFn is...*badinc-i2-inl.h
typedef I2_TemplateClass<int> Cc_typedef_implicit_instantiation2;
// IWYU: I1_ClassPtr is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
typedef I1_TemplateClass<I1_ClassPtr> Cc_typedef_explicit_instantiation;
// IWYU: I1_ClassPtr is...*badinc-i1.h
// IWYU: I1_TemplateClass is...*badinc-i1.h
typedef I1_TemplateClass<I1_ClassPtr> Cc_typedef_explicit_instantiation2;
// IWYU: I1_TemplateClass is...*badinc-i1.h
typedef I1_TemplateClass<char> Cc_typedef_no_previous_instantiation;
// IWYU: I1_TemplateClass is...*badinc-i1.h
typedef I1_TemplateClass<char> Cc_typedef_no_previous_instantiation2;

class Cc_Class {
  friend class I2_Class;
  // IWYU: I1_Class is...*badinc-i1.h
  friend struct I1_Class::NestedStruct;
  template<class T> friend class I2_TemplateClass;
  // IWYU: I2_TemplateClass needs a declaration
  friend class I2_TemplateClass<int>;
  // IWYU: I1_Class is...*badinc-i1.h
  template<class T> friend struct I1_Class::NestedTemplateStruct;
};

void Cc_ForwardDeclare_Function() {
  class I2_Class;
}

// This class template fully uses its type parameter.
template <typename T> class Cc_TemplateFullyUse {
 private:
  T value_;
};

// This class template doesn't fully use its type parameter.
template <typename T> class Cc_TemplatePartiallyUse {
 private:
  Cc_TemplateFullyUse<T>* ptr_;  // shouldn't require T's full type
};

// IWYU: I1_Class needs a declaration
Cc_TemplatePartiallyUse<I1_Class> cc_template_class1;

template <typename T>
class Cc_TemplateDerived
    : public Cc_TemplateFullyUse<T> {  // test traversing the base class
};

// IWYU: I1_Class needs a declaration
// IWYU: I1_Class is...*badinc-i1.h
Cc_TemplateDerived<I1_Class> cc_template_derived1;

// The following three classes test the fix for http://llvm.org/PR8403.

template <class A>
struct CC_TemplateStruct2 { };

class CC_Class2 {
  struct CC_TemplateStruct2<int> x;
};

// We require full type info for default template parameters, even
// when it's not strictly necessary, just to avoid potential trouble.
// (Users shouldn't have to worry about instantiating default params.)
// IWYU: I1_Class is...*badinc-i1.h
template <class A, class B = I1_Class>
class CC_TemplateClass {
 public:
  struct CC_TemplateStruct2<A> x;
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  typedef I1_TemplateClass<A> i1_typedef;

  // Let's throw in per-class operator new/delete.
  // IWYU: size_t is...*((<stddef.h>)|(stdio.h)|(string.h)|(time.h)|(wchar.h))
  void* operator new(size_t size) {
    B b;
    (void)b;
    return ::operator new(4);
  }
  void operator delete(void* p) {
    A a;
    (void)a;
    ::operator delete(p);
  }
  // Test deleting a dependent type
  void DeleteAnA() {
    A a; delete a;   // A had better be a pointer type!
  }
};

// This should stay untouched by iwyu.
#include "tests/cxx/badinc2.c"

int main() {
  // Some of the above as local variables as well
  Cc_Struct local_cc_struct = {};
  Cc_string local_cc_string;
  H_Class local_h_class;
  // IWYU: I2_Enum is...*badinc-i2.h
  D1_TemplateClass<I2_Enum> local_d1_template_class(I21);
  // IWYU: I1_Enum is...*badinc-i1.h
  I1_Enum local_i1_enum = I11;
  // IWYU: I1_UnnamedStruct is...*badinc-i1.h
  I1_UnnamedStruct local_i1_unnamed_struct = {};
  D1_Subclass local_d1_subclass;
  // IWYU: I2_Class needs a declaration
  I2_Class* local_i2_class_ptr = 0;  // ptr-only in this .cc, non-ptr in .h
  // IWYU: I2_TemplateClass...*badinc-i2.h
  // IWYU: I2_TemplateClass::~I2_TemplateClass<.*> is...*badinc-i2-inl.h
  I2_TemplateClass<int> local_i2_template_class(1);
  // IWYU: I1_PtrDereferenceStruct needs a declaration
  const I1_PtrDereferenceStruct* const local_i1_ptrdereference_struct = 0;
  // IWYU: I1_PtrDereferenceClass needs a declaration
  I1_PtrDereferenceClass* local_i1_ptrdereference_class = 0;
  int x;
  // va_list is normally in <stdarg.h>, but we already have <stdio.h>
  // available, so mappings will source it from there.
  // IWYU: va_list is...*<stdio.h>
  va_list vl;
  D1_I1_Typedef d1_i1_typedef;
  // IWYU: i1_int is...*badinc-i1.h
  int vararray[i1_int];
  std::fstream fs;

  isascii('a');   // declared in <ctype.h> which is #included by badinc.h
  (void)(errno);  // declared in <errno.h> which is #included by badinc.h
  // Test we don't give an iwyu warning for the built-in __builtin_expect
  // IWYU: I1_Enum is...*badinc-i1.h
  if (__builtin_expect(local_i1_enum == I11, false)) (void)local_i1_enum;

  // IWYU: i1_int_global is...*badinc-i1.h
  x = i1_ns::i1_int_global;
  // IWYU: i1_ns::i1_subns::i1_int_globalsub is...*badinc-i1.h
  x = i1_ns::i1_subns::i1_int_globalsub;
  // IWYU: i1_ns2::i1_int_global2 is...*badinc-i1.h
  x = i1_int_global2;
  // IWYU: i1_ns2::i1_subns::i1_int_global2sub is...*badinc-i1.h
  x = i1_subns::i1_int_global2sub;
  // IWYU: i1_ns3::i1_int_global3 is...*badinc-i1.h
  x = i1_int_global3;
  // IWYU: i1_ns3::i1_subns::i1_int_global3sub is...*badinc-i1.h
  x = i1_ns3::i1_subns::i1_int_global3sub;
  // IWYU: i1_ns4::i1_int_global4 is...*badinc-i1.h
  x = cc_ns_alias::i1_int_global4;
  // IWYU: i1_ns4::i1_subns::i1_int_global4sub is...*badinc-i1.h
  x = cc_ns_alias::i1_subns::i1_int_global4sub;

  // Reference all the local variables, to avoid not-used errors.
  // IWYU: fprintf is...*<stdio.h>
  // IWYU: stdout is...*<stdio.h>
  fprintf(stdout, "%d", local_cc_struct.a);  // test a global in stdio.h too
  // IWYU: printf is...*<stdio.h>
  printf("%d", local_cc_struct.a);
  (void)Cc_typedef(4);
  // Not an iwyu violation, because Cc_typedef is responsible for its members.
  Cc_typedef::s();
  Cc_typedef::I1_Class_int Cc_typedef_int = 0;
  Cc_typedef::NestedStruct Cc_typedef_struct;
  Cc_typedef::NestedStruct::NestedStructTypedef Cc_typedef_nested_int = 0;
  local_h_class.a();
  // a() returns a FOO, which in this case is I2_Enum.
  local_d1_template_class.a();
  (void)(local_i1_enum);
  // Typedef of unnamed type always provides that type, and it should be
  // included due to variable declaration.
  (void)(local_i1_unnamed_struct.a);
  local_d1_subclass.a();
  (void)(local_i2_class_ptr);
  // IWYU: I1_PtrDereferenceStruct is...*badinc-i1.h
  (void)(local_i1_ptrdereference_struct->a);
  // Make the last ref to local_i1_ptrdereference_struct
  // fwd-declarable.  This tests that if we do non-fwd-decl-use
  // followed by fwd-decl-use, we correctly say it can't be fwd-declared.
  (void)(local_i1_ptrdereference_struct);
  // IWYU: I1_PtrDereferenceClass is...*badinc-i1.h
  local_i1_ptrdereference_class->a();

  // Calling an overloaded function.  In the first two cases,
  // CallOverloadedFunctionSameFile() is responsible for the call,
  // since it's just a single file.  In the second two cases, we
  // can't know the file required until now (when the templated
  // function is instantiated).
  CallOverloadedFunctionSameFile(5);
  CallOverloadedFunctionSameFile(5.0f);
  // IWYU: I1_And_I2_OverloadedFunction is...*badinc-i1.h
  CallOverloadedFunctionDifferentFiles(5);
  // IWYU: I1_And_I2_OverloadedFunction is...*badinc-i2.h
  CallOverloadedFunctionDifferentFiles(5.0f);
  // This should not be an IWYU violation either: the iwyu use is in the fn.
  CallOverloadWithUsingShadowDecl(5);

  // Calling operator<< when the first argument is a macro.  We should
  // still detect that operator<< is being used here, and not in the
  // macro-definition file.
  // IWYU: I1_MACRO_LOGGING_CLASS is...*badinc-i1.h
  // IWYU: I2_OperatorDefinedInI1Class::operator<< is...*badinc-i1.h
  I1_MACRO_LOGGING_CLASS << 1;

  // Calling a template method can cause the template arg to be non-fwd-decl.
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  i1_template_method_only_class.a();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  i1_template_method_only_class.b();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  i1_template_method_only_class.c<I2_Class>();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  i1_template_method_only_class.c<I2_Class*>();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  i1_template_method_only_class.d<I2_Class>();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  i1_template_method_only_class.d<I2_Class*>();
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  i1_template_method_only_class.e(local_i2_class_ptr);
  // IWYU: std::vector is...*<vector>
  // IWYU: I2_Class needs a declaration
  std::vector<I2_Class>* i2_class_vector = NULL;
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: std::vector is...*<vector>
  i1_template_method_only_class.e(i2_class_vector);
  // Four different ways of making the same function call.
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  i1_template_method_only_class.s(local_i2_class_ptr);
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  i1_template_method_only_class.s<I2_Class*>(local_i2_class_ptr);
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  I1_TemplateMethodOnlyClass<I1_Class>::s(local_i2_class_ptr);
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  I1_TemplateMethodOnlyClass<I1_Class>::s<I2_Class*>(local_i2_class_ptr);
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  I1_TemplateMethodOnlyClass<I2_Class>::t<I1_Class>();
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  I1_TemplateMethodOnlyClass<I2_Class>::tt<I1_TemplateClass>();
  // Try the static calls again, but this time with a typedef tpl arg.
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  I1_TemplateMethodOnlyClass<Cc_typedef>::s(local_i2_class_ptr);
  // IWYU: I1_TemplateMethodOnlyClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  I1_TemplateMethodOnlyClass<Cc_typedef>::s<I2_Class*>(local_i2_class_ptr);

  // The result of static_cast depends on the relation between the
  // source and target type, and thus requires the full target type
  // whenever source and target types aren't the same.
  // IWYU: I1_Class needs a declaration
  (void)(static_cast<I1_Class*>(i1_class_ptr));     // same type
  // IWYU: I1_Class needs a declaration
  (void)(static_cast<I1_Class**>(&i1_class_ptr));   // same type
  // IWYU: I1_Base needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(static_cast<I1_Base*>(i1_class_ptr));
  // IWYU: I1_Base needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(static_cast<I1_Base&>(i1_class_ref));
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Base needs a declaration
  (void)(static_cast<I1_Base&>(i1_class));
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(static_cast<I1_Class*>(i1_base_ptr));
  // Full type information isn't needed since 0 isn't a pointer.
  // IWYU: I1_Class needs a declaration
  (void)(static_cast<I1_Class*>(0));
  // IWYU: I1_Class needs a declaration
  (void)(static_cast<I1_Class**>(0));

  // For implicit cast, we need to know whether the source type is
  // derived from the target type, and thus need the full type of the
  // former.
  // IWYU: I1_Class is...*badinc-i1.h
  i1_base_ptr = i1_class_ptr;
  // IWYU: I1_SubclassesI2Class needs a declaration
  I1_SubclassesI2Class* i1_subclasses_i2_ptr = 0;
  // IWYU: I1_SubclassesI2Class is...*badinc-i1.h
  FunctionTakesI2_Class(i1_subclasses_i2_ptr);
  // We don't need to know full type info if one pointer is a built-in type.
  void* void_ptr = i1_class_ptr;
  // Also tests reference-casts.
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Base needs a declaration
  const I1_Base& i1_base_implicit_cast1 = i1_class_ref;
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Base needs a declaration
  const I1_Base& i1_base_implicit_cast2 = i1_class;

  // dynamic_cast requires the full type of the source and target.
  // They may be siblings, which is why we can't say the target
  // brings in the source, like we can for a normal down-cast.
  // IWYU: I1_Base is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  i1_class_ptr = dynamic_cast<I1_Class*>(i1_base_ptr);
  // IWYU: I1_SiblingClass needs a declaration
  I1_SiblingClass* i1_sibling_class_ptr = 0;
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_SiblingClass needs a declaration
  // IWYU: I1_SiblingClass is...*badinc-i1.h
  i1_sibling_class_ptr = dynamic_cast<I1_SiblingClass*>(i1_class_ptr);

  // const_cast doesn't require the full type.
  // IWYU: I1_Class needs a declaration
  const I1_Class* const_i1_class_ptr = 0;
  // IWYU: I1_Class needs a declaration
  i1_class_ptr = const_cast<I1_Class*>(const_i1_class_ptr);

  // reinterpret_cast doesn't require the full type.
  // IWYU: I1_Class needs a declaration
  i1_class_ptr = reinterpret_cast<I1_Class*>(i1_base_ptr);

  // C-style cast doesn't require the full type either, according
  // to the language, but we ask for full type when it's an up-cast
  // or a down-cast.
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  i1_class_ptr = (I1_Class*)(i1_base_ptr);

  // Constructor casts require the full to-type (to call its constructor).
  // IWYU: I2_Struct is...*badinc-i2.h
  I2_Struct ctor_cast_struct_nonref;
  // IWYU: I2_Struct needs a declaration
  I2_Struct& ctor_cast_struct = ctor_cast_struct_nonref;
  // IWYU: I2_Union is...*badinc-i2.h
  I2_Union ctor_cast_union_nonref;
  // IWYU: I2_Union needs a declaration
  I2_Union& ctor_cast_union = ctor_cast_union_nonref;
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  I2_Class i2_class_from_struct = ctor_cast_struct;   // ctor takes a reference
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  I2_Class i2_class_from_union = ctor_cast_union;   // ctor takes a value

  // User-defined casts need the full from-type (to call its operator totype()).
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_UnionFunction is...*badinc-i2.h
  I2_UnionFunction(*local_i2_class_ptr);

  // Even dereferencing doesn't require the full type.
  (void)(*i1_class_ptr);

  // IWYU: I1_PtrDereferenceStatic is...*badinc-i1.h
  (void)(I1_PtrDereferenceStatic::a);
  // IWYU: I1_StaticMethod is...*badinc-i1.h
  I1_StaticMethod::a();

  // Reference some of the global variables.
  (void)(__PRETTY_FUNCTION__);
  (void)(cc_struct.b);
  d1_class.a();
  (void)(cc_struct.b);
  (void)(cc_subclass.a());
  // IWYU: OperateOn is...*badinc-i1.h
  h_template_struct.a();
  // This tests a bug in clang where an implicit template instantiation
  // of a partial specialization gave the wrong location information.
  // In this case, OperateOn<I1_TemplateClass<T> > is in badinc-i1.h,
  // which is what we should report, *not* the OperateOn<T> in badinc.h.
  // IWYU: OperateOn is...*badinc-i1.h
  h_template_struct_tplclass_arg.a();
  h_scoped_ptr.get();
  // Not an iwyu violation, since we never use the dereferenced type.
  (void)(*h_scoped_ptr);
  // IWYU: I1_Class is...*badinc-i1.h ?
  (*h_scoped_ptr).a();
  // IWYU: I1_Class is...*badinc-i1.h
  h_scoped_ptr->a();
  // IWYU: I1_Enum is...*badinc-i1.h
  D1Function(I12);
  // TODO(csilvers): should we be warning about I2_Struct?
  // IWYU: I1_Union is...*badinc-i1.h
  // IWYU: I1_Struct is...*badinc-i1.h
  (void)(i1_union.a->a);
  // IWYU: I1_Class is...*badinc-i1.h
  I1_Class::s();
  // IWYU: I2_Struct is...*badinc-i2.h
  // IWYU: I2_Function is...*badinc-i2.h
  (void)(I2_Function(local_i2_class_ptr).b);
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::InlFileFn is...*badinc-i2-inl.h
  local_i2_class_ptr->InlFileFn();
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::InlFileStaticFn is...*badinc-i2-inl.h
  local_i2_class_ptr->InlFileStaticFn();
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::InlFileStaticFn is...*badinc-i2-inl.h
  I2_Class::InlFileStaticFn();
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::InlFileTemplateFn is...*badinc-i2-inl.h
  local_i2_class_ptr->InlFileTemplateFn<int>();
  // IWYU: I2_Class is...*badinc-i2.h
  local_i2_class_ptr->AnotherTranslationUnitFn();
  // IWYU: I2_Class is...*badinc-i2.h
  local_i2_class_ptr->CcFileFn();
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  // IWYU: I2_TemplateClass::InlFileTemplateClassFn is...*badinc-i2-inl.h
  local_i2_template_class.InlFileTemplateClassFn();
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  local_i2_template_class.a();
  // TODO(csilvers): this first error is wrong, due to a bug in
  // IntendsToProvide.  The file defining this template method *should* be
  // providing badinc-i2-inl.h, but isn't (iwyu will suggest we add it).
  // So we don't detect that file as responsible for these symbols, and not us.
  // IWYU: I2_TemplateClass::InlFileTemplateClassFn is...*badinc-i2-inl.h
  // IWYU: I2_TemplateClass is...*badinc-i2.h
  local_i2_template_class.CcFileFn();
  // IWYU: InlFileFreeFn is...*badinc-i2-inl.h
  InlFileFreeFn();
  // IWYU: InlFileFreeTemplateFn is...*badinc-i2-inl.h
  InlFileFreeTemplateFn<float>();
  // IWYU: InlFileFreeTemplateFn is...*badinc-i2-inl.h
  InlFileFreeTemplateFn<int>();     // a specialization
  // IWYU: inlfile_var is...*badinc-i2-inl.h
  (void)(inlfile_var);
  // TODO(csilvers): IWYU: I1_FunctionPtr is...*badinc-i1.h
  (**i1_functionptr_ptr)(&i1_class);
  (void)(x);
  (void)(i1_class_array);
  d1_i1_typedef.a();
  D1_I1_Typedef().a();
  MACRO_CALLING_I4_FUNCTION;
  // IWYU: MACRO_CALLING_I6_FUNCTION is...*badinc-i1.h
  MACRO_CALLING_I6_FUNCTION;
  // IWYU: kI1ConstInt is...*badinc-i1.h
  (void)(kI1ConstInt);

  Cc_string().length();

  // IWYU: kI1ConstInt is...*badinc-i1.h
  (void)(sizeof(kI1ConstInt));
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(sizeof(I1_Class));
  // IWYU: I1_Class is...*badinc-i1.h
  typeof(I1_Class) another_i1_class;
  (void)(another_i1_class);
  // IWYU: I1_Class needs a declaration
  typeof(I1_Class*) another_i1_class_ptr;
  (void)(another_i1_class_ptr);
  // IWYU: kI1ConstInt is...*badinc-i1.h
  typeof(kI1ConstInt) another_const_int = 1;
  (void)(another_const_int);
  // This is a C standard macro, but is implemented via a gcc extension too.
  // IWYU: offsetof is...*<stddef.h>
  // IWYU: I1_Struct is...*badinc-i1.h
  (void)(offsetof(I1_Struct, c));
  // IWYU: kI1ConstInt is...*badinc-i1.h
  typeid(kI1ConstInt).name();
  // IWYU: I1_Class is...*badinc-i1.h
  typeid(I1_Class).name();
  // This is an extension for gcc and msvc.
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(__is_enum(I1_Class));

  // Check out template iwyu determinations.
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  I1_const_ptr<I1_Class> local_i1_const_ptr(NULL);
  // Needs I1_const_ptr because it calls its operator*().
  // IWYU: I1_const_ptr is...*badinc-i1.h
  (void)(*local_i1_const_ptr);
  // IWYU: I1_const_ptr is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  local_i1_const_ptr->a();
  // IWYU: I1_const_ptr is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  local_i1_const_ptr.del();
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  local_i1_const_ptr.indirect_del();
  // This calls *ptr_, but in a free function.
  // IWYU: operator== is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  (void)(local_i1_const_ptr == i1_class);
  // IWYU: operator== is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  (void)(i1_class == local_i1_const_ptr);
  // Also check the default (implicit) operator=
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  I1_const_ptr<I1_Class> local_i1_const_ptr2(NULL);
  // IWYU: I1_const_ptr is...*badinc-i1.h
  local_i1_const_ptr2 = local_i1_const_ptr;

  // We need the full I1_Class definition for the destructor.
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  (void)I1_const_ptr<I1_Class>(NULL);
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_const_ptr is...*badinc-i1.h
  I1_const_ptr<I1_Class*> local_i1_const_ptrptr(NULL);
  // TODO(csilvers): IWYU: I1_Class needs a declaration
  // IWYU: I1_const_ptr is...*badinc-i1.h
  (void)(*local_i1_const_ptrptr);
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_const_ptr is...*badinc-i1.h
  local_i1_const_ptrptr.deref_a();
  // This calls through to deref_a.
  // IWYU: I1_const_ptr is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  (void)(~local_i1_const_ptrptr);

  // IWYU: std::vector is...*<vector>
  // IWYU: I2_Enum is...*badinc-i2.h
  std::vector<I2_Enum> local_enum_vector;
  // IWYU: I2_Enum is...*badinc-i2.h
  // IWYU: std::vector is...*<vector>
  local_enum_vector.push_back(I21);
  // IWYU: std::vector is...*<vector>
  // IWYU: I2_Enum is...*badinc-i2.h
  for (std::vector<I2_Enum>::iterator it = local_enum_vector.begin();
       // IWYU: std::vector is...*<vector>
       it != local_enum_vector.end(); ++it) {
    // IWYU: std::vector is...*<vector>
    std::find(local_enum_vector.begin(), local_enum_vector.end(), *it);
  }
  // string also uses __normal_iterator.  Let's also verify that
  // adding two strings doesn't bring in a requirement for <memory>
  std::string s = std::string("aaa") + "bbb";
  for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
    std::find(s.begin(), s.end(), *it);
  }
  for (Cc_string::iterator it = local_cc_string.begin();
       it != local_cc_string.end(); ++it) {
    std::find(local_cc_string.begin(), local_cc_string.end(), *it);
  }

  // This should result in an iwyu to #include <list>, not
  // forward-declare it, as STL types cannot be forward declared.
  // IWYU: std::list is...*<list>
  std::list<int>* list_ptr;
  list_ptr = 0;

  // IWYU: std::vector is...*<vector>
  // IWYU: I2_Enum is...*badinc-i2.h
  std::vector<I2_Enum>* newed_vector
      // IWYU: std::vector is...*<vector>
      // IWYU: I2_Enum is...*badinc-i2.h
      = new std::vector<I2_Enum>;
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: kI1ConstInt is...*badinc-i1.h
  I1_Class* newed_i1_class_array = new I1_Class[kI1ConstInt];
  // IWYU: std::vector is...*<vector>
  delete newed_vector;
  // IWYU: I1_Class is...*badinc-i1.h
  delete[] newed_i1_class_array;
  // IWYU: I1_Class is...*badinc-i1.h
  delete[] ((((newed_i1_class_array))));
  // IWYU: I1_Base needs a declaration
  // IWYU: I1_Base is...*badinc-i1.h
  // IWYU: I1_Class is...*badinc-i1.h
  delete[] static_cast<I1_Base*>(newed_i1_class_array);

  // Make sure constructor is analyzed when we new, and destructor is
  // analyzed when we delete.
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I1_Struct needs a declaration
  I1_TemplateClass<I2_Class, I1_Struct>* newed_i1_template_class
      // IWYU: I1_Struct needs a declaration
      // IWYU: I1_Struct is...*badinc-i1.h
      // IWYU: I1_TemplateClass is...*badinc-i1.h
      // IWYU: I2_Class needs a declaration
      // IWYU: I2_Class is...*badinc-i2.h
      = new I1_TemplateClass<I2_Class, I1_Struct>;
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I1_Struct needs a declaration
  I1_TemplateClass<I2_Class, I1_Struct>* newed_i1_template_class_array
      // IWYU: I1_Struct needs a declaration
      // IWYU: I1_Struct is...*badinc-i1.h
      // IWYU: I1_TemplateClass is...*badinc-i1.h
      // IWYU: I2_Class needs a declaration
      // IWYU: I2_Class is...*badinc-i2.h
      // IWYU: kI1ConstInt is...*badinc-i1.h
      = new I1_TemplateClass<I2_Class, I1_Struct>[kI1ConstInt];
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I1_Struct needs a declaration
  I1_TemplateClass<I2_Class, I1_Struct>* newed_i1_template_class_ctor
      // IWYU: I1_Struct needs a declaration
      // IWYU: I1_TemplateClass is...*badinc-i1.h
      // IWYU: I2_Class needs a declaration
      // IWYU: I2_Class is...*badinc-i2.h
      = new I1_TemplateClass<I2_Class, I1_Struct>(i1_union);
  // IWYU: I1_Class needs a declaration
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: i1_ns::I1_NamespaceClass is...*badinc-i1.h
  I1_Class* i1_class_tpl_ctor = new I1_Class(&i1_namespace_class, 1);

  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_Struct is...*badinc-i1.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  delete newed_i1_template_class;
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_Struct is...*badinc-i1.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  delete[] newed_i1_template_class_array;
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_Struct is...*badinc-i1.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  delete newed_i1_template_class_ctor;
  // IWYU: I1_Class is...*badinc-i1.h
  delete i1_class_tpl_ctor;
  // Check that we discover constructor/destructor locations as well.
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::I2_Class is...*badinc-i2-inl.h
  local_i2_class_ptr = new I2_Class("inl.h constructor");
  // IWYU: I2_Class is...*badinc-i2.h
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  delete local_i2_class_ptr;
  // Make sure we do this check even when it's via a template parameter.
  // (We need full type info for i1_templateclass because we never
  // fwd-declare a class with default template parameters.)
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I1_Enum is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  I1_TemplateClass<I1_Enum, I2_Class>* local_i1_template_class_for_inl = NULL;
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class is...*badinc-i2.h
  local_i1_template_class_for_inl->new_delete_bar();
  // Test per-class operator new
  // IWYU: I1_Struct needs a declaration
  // IWYU: I2_Struct needs a declaration
  CC_TemplateClass<I1_Struct, I2_Struct>* cc_template_class =
      // IWYU: I1_Struct needs a declaration
      // IWYU: I2_Struct needs a declaration
      // IWYU: I2_Struct is...*badinc-i2.h
      new CC_TemplateClass<I1_Struct,I2_Struct>;
  // IWYU: I1_Struct is...*badinc-i1.h
  delete cc_template_class;

  // While we're at it, make sure we get the same thing when creating
  // a local variable and a temporary, as we do when calling new/delete.
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: i1_ns::I1_NamespaceClass is...*badinc-i1.h
  I1_Class i1_class_tpl_ctor_local(&i1_namespace_class, 1);
  // We need the full type of I1_NamespaceClass because the ctor is a template.
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: i1_ns::I1_NamespaceClass is...*badinc-i1.h
  (void)I1_Class(&i1_namespace_class, 1);
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_Struct needs a declaration
  // IWYU: I1_Struct is...*badinc-i1.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  I1_TemplateClass<I2_Class, I1_Struct> local_i1_templateclass(i1_union);
  // IWYU: I2_Class::~I2_Class is...*badinc-i2-inl.h
  // IWYU: I1_Struct needs a declaration
  // IWYU: I1_Struct is...*badinc-i1.h
  // IWYU: I1_TemplateClass is...*badinc-i1.h
  // IWYU: I2_Class needs a declaration
  // IWYU: I2_Class is...*badinc-i2.h
  (void)I1_TemplateClass<I2_Class, I1_Struct>(i1_union);

  (void)(*(new int(4)));
  (void)((new int[10])[0]);
  // Make sure we don't claim i2_newed and i2_deleted are "ptr only".
  // IWYU: I2_ThisClassIsOnlyNewed needs a declaration
  I2_ThisClassIsOnlyNewed* i2_newed = 0;
  // IWYU: I2_ThisClassIsOnlyDeleted needs a declaration
  I2_ThisClassIsOnlyDeleted* i2_deleted = 0;
  // IWYU: I2_ThisClassIsOnlyDeletedPtr needs a declaration
  I2_ThisClassIsOnlyDeletedPtr** i2_deleted_ptr = 0;
  // IWYU: I2_ThisClassIsOnlyNewed is...*badinc-i2.h
  i2_newed = new I2_ThisClassIsOnlyNewed;
  // IWYU: I2_ThisClassIsOnlyDeleted is...*badinc-i2.h
  delete i2_deleted;
  delete i2_deleted_ptr;
  delete i2_deleted_ptr;  // make sure each delete doesn't eat up a star

  // Make sure we don't claim set::iterator is defined in map.
  // IWYU: std::set is...*<set>
  std::set<int> localset;
  // IWYU: std::set is...*<set>
  std::set<int>::iterator it_set = localset.begin();

  // Lots of weird stuff can happen with iterators, especially regarding const.
  // IWYU: std::vector is...*<vector>
  std::vector<float> float_vector;
  // IWYU: std::vector is...*<vector>
  std::vector<float>::const_iterator float_it = float_vector.begin();
  // IWYU: std::vector is...*<vector>
  const std::vector<float>::const_iterator float_constit = float_vector.begin();
  // IWYU: std::vector is...*<vector>
  (void)(float_it == float_constit);
  // IWYU: std::vector is...*<vector>
  (void)(float_constit == float_it);
  // IWYU: std::vector is...*<vector>
  std::vector<float>::const_iterator float_forit;
  // IWYU: std::vector is...*<vector>
  for (float_forit = float_vector.begin(); ;) ;
  // IWYU: std::vector is...*<vector>
  for (std::vector<float>::const_iterator it = float_vector.begin(); ;) ;
  // IWYU: std::vector is...*<vector>
  for (const std::vector<float>::const_iterator it = float_vector.begin(); ;) ;
  // We special-case vector<>::iterator.  Make sure it holds for
  // reverse_iterator too.
  // IWYU: std::vector is...*<vector>
  for (std::vector<float>::reverse_iterator
           // IWYU: std::vector is...*<vector>
           float_reverse_it = float_vector.rbegin();
       // IWYU: std::vector is...*<vector>
       float_reverse_it != float_vector.rbegin();
       // IWYU: std::vector is...*<vector>
       ++float_reverse_it) ;
  // IWYU: std::vector is...*<vector>
  for (std::vector<float>::const_reverse_iterator
           // IWYU: std::vector is...*<vector>
           float_const_reverse_it = float_vector.rbegin();
       // IWYU: std::vector is...*<vector>
       float_const_reverse_it != float_vector.rend();
       // IWYU: std::vector is...*<vector>
       ++float_const_reverse_it) ;

  // Also test while and if initializers.
  // IWYU: I1_Class needs a declaration
  while (I1_Class* i = NULL) {
  }
  // IWYU: I1_Class needs a declaration
  if (I1_Class* i = NULL) i = NULL;

  // Test some macros, including one we shouldn't mark as in-use.
  // IWYU: MACRO_CALLING_I2_FUNCTION is...*badinc-i2.h
  MACRO_CALLING_I2_FUNCTION;
  // Here are some uses of UNUSED_MACRO that we should not find:
  /*
    UNUSED_MACRO
  */
  (void)("#include \\\"UNUSED_MACRO\"");

  // Test if and while.
  // IWYU: I1_Function is...*badinc-i1.h
  if (I1_Function(0)) {        // returns an I1Enum
    // IWYU: I2_Struct is...*badinc-i2.h
    // IWYU: I2_Function is...*badinc-i2.h
    while (I2_Function(0)) ;   // returns a I2_Struct, converted to a bool
  }

  // Test calling virtual methods.
  // IWYU: I2_Subclass needs a declaration
  I2_Subclass* i2_subclass = 0;
  // IWYU: I2_Subclass is...*badinc-i2.h
  i2_subclass->Impl();
  // IWYU: I2_Subclass is...*badinc-i2.h
  i2_subclass->Abstract();
  // IWYU: I2_Subclass is...*badinc-i2.h
  i2_subclass->BaseOnly();
  // IWYU: I2_Subclass is...*badinc-i2.h
  i2_subclass->NonvirtualBaseOnly();

  // Test templatized functions.
  H_TemplateFunction(1);
  // IWYU: I1_Enum is...*badinc-i1.h
  H_TemplateFunction(I11);
  // IWYU: I1_Enum is...*badinc-i1.h
  H_TemplateFunction<int>(I11);
  // IWYU: I1_Class needs a declaration
  H_TemplateFunction<I1_Class*>(&i1_class);
  H_TemplateFunction(&i1_class);
  // IWYU: I2_Enum is...*badinc-i2.h
  h_templateclass2.static_out_of_line(I22);
  // IWYU: I2_Enum is...*badinc-i2.h
  h_templateclass2.static_inline(I22);
  // IWYU: I2_Enum is...*badinc-i2.h
  h_templateclass2.h_nested_struct.tplnested(I22);
  // TODO: I1_Enum should be reported here as a full use but isn't,
  // because we are not properly handling the dependent type FOO in
  // the nested struct.
  // IWYU: I2_Enum is...*badinc-i2.h
  h_templateclass2.h_nested_struct.static_tplnested(I22);
  // This should not cause warnings for the i2_class destructor
  h_templateclass2.uses_i2class();
  // IWYU: I1_TemplateFunction is...*badinc-i1.h
  I1_TemplateFunction(i1_class_ptr);
  // IWYU: I1_TemplateFunction is...*badinc-i1.h
  // IWYU: I1_Class needs a declaration
  I1_TemplateFunction<I1_Class*>(i1_class_ptr);
  // Try again, but with a typedef
  Cc_typedef cc_typedef;
  // IWYU: I1_TemplateFunction is...*badinc-i1.h
  I1_TemplateFunction(cc_typedef);
  // IWYU: I1_TemplateFunction is...*badinc-i1.h
  I1_TemplateFunction<Cc_typedef>(cc_typedef);
  // IWYU: I1_TemplateFunction is...*badinc-i1.h
  I1_TemplateFunction<Cc_typedef>(i1_class);

  // IWYU: I1_Class is...*badinc-i1.h
  i1_class.I1_ClassTemplateFunction(&i1_struct);
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Struct needs a declaration
  i1_class_ptr->I1_ClassTemplateFunction<I1_Struct*>(&i1_struct);
  // IWYU: I1_Class is...*badinc-i1.h
  I1_Class::I1_StaticClassTemplateFunction(&i1_struct);
  // IWYU: I1_Class is...*badinc-i1.h
  // IWYU: I1_Struct needs a declaration
  I1_Class::I1_StaticClassTemplateFunction<I1_Struct*>(&i1_struct);

  // Test default (compiler-defined) copy constructor/operator=/operator==
  // IWYU: I1_Enum is...*badinc-i1.h
  D1_CopyClass local_d1_copy_class(D1CopyClassFn(I11));
  // IWYU: I1_Enum is...*badinc-i1.h
  local_d1_copy_class = D1CopyClassFn(I12);
  local_d1_copy_class.a();

  // Check use of a macro inside an #ifdef.
  // IWYU: I2_MACRO is...*badinc-i2.h
#ifdef I2_MACRO
  // IWYU: kI1ConstInt is...*badinc-i1.h
  int i2_macro_var = kI1ConstInt;
#endif

  return 0;
}

// TODO(csilvers): the delete of <locale> should be line 56, not 35
// Some notes:
// * We do not need to #include badinc-i2.h, badinc_i2-inl.h, set,
//   stdio.h, or vector, because badinc.h is adding them for us.
// * We *do* need to #include ctype.h, even though badinc.h #includes
//   it, because badinc.h is removing that dependency.
// * We're removing <algorithm> twice because it's in the file 3 times.
/**** IWYU_SUMMARY

tests/cxx/badinc.cc should add these lines:
#include <ctype.h>
#include <stddef.h>
#include <list>
#include "tests/cxx/badinc-i1.h"
class D2_Class;
class D2_ForwardDeclareClass;
class D2_Subclass;
class I1_ForwardDeclareClass;
namespace d3_namespace { struct D3_Struct; }
namespace i3_ns1 { namespace i3_ns2 { namespace i3_ns3 { template <typename A, int B> struct I3_ForwardDeclareNamespaceTemplateStruct; } } }
namespace i3_ns1 { namespace { struct I3_UnnamedNamespaceStruct; } }
struct I3_ForwardDeclareStruct;
template <typename A, int B, char C> struct I3_ForwardDeclareTemplateStruct;

tests/cxx/badinc.cc should remove these lines:
- #include <math.h>  // lines XX-XX
- #include <algorithm>  // lines XX-XX
- #include <algorithm>  // lines XX-XX
- #include <clocale>  // lines XX-XX
- #include <locale>  // lines XX-XX
- #include "tests/cxx/badinc-d2.h"  // lines XX-XX
- class Cc_ForwardDeclare_Function::I2_Class;  // lines XX-XX
- class I3_UnusedClass;  // lines XX-XX
- template <class T = I1_Class, I1_Enum E = I11> class Cc_DeclareOnlyTemplateClass;  // lines XX-XX

The full include-list for tests/cxx/badinc.cc:
#include "tests/cxx/badinc.h"
#include "tests/cxx/badinc-inl.h"
#include <ctype.h>  // for isascii
#include <setjmp.h>
#include <stddef.h>  // for offsetof
#include <algorithm>  // for find
#include <fstream>  // for fstream
#include <list>  // for list
#include <string>  // for basic_string, operator+, string
#include <typeinfo>  // for type_info
#include "tests/cxx/badinc-d1.h"  // for D1CopyClassFn, D1Function, D1_Class, D1_CopyClass, D1_Enum, D1_I1_Typedef, D1_StructPtr, D1_Subclass, D1_TemplateClass, D1_TemplateStructWithDefaultParam, MACRO_CALLING_I4_FUNCTION
#include "tests/cxx/badinc-d4.h"  // for D4_ClassForOperator, operator<<
#include "tests/cxx/badinc-i1.h"  // for EmptyDestructorClass, H_Class::H_Class_DefinedInI1, I1_And_I2_OverloadedFunction, I1_Base, I1_Class, I1_ClassPtr, I1_Enum, I1_Function, I1_FunctionPtr, I1_I2_Class_Typedef, I1_MACRO_LOGGING_CLASS, I1_MACRO_SYMBOL_WITHOUT_VALUE, I1_MACRO_SYMBOL_WITH_VALUE, I1_MACRO_SYMBOL_WITH_VALUE0, I1_MACRO_SYMBOL_WITH_VALUE2, I1_ManyPtrStruct (ptr only), I1_MemberPtr, I1_NamespaceClass, I1_NamespaceStruct, I1_NamespaceTemplateFn, I1_OverloadedFunction, I1_PtrAndUseOnSameLine, I1_PtrDereferenceClass, I1_PtrDereferenceStatic, I1_PtrDereferenceStruct, I1_SiblingClass, I1_StaticMethod, I1_Struct, I1_Subclass, I1_SubclassesI2Class, I1_TemplateClass, I1_TemplateClassFwdDeclaredInD2 (ptr only), I1_TemplateFunction, I1_TemplateMethodOnlyClass, I1_TemplateSubclass, I1_Typedef, I1_TypedefOnly_Class, I1_Union, I1_UnnamedStruct, I1_UnusedNamespaceStruct (ptr only), I1_const_ptr, I2_OperatorDefinedInI1Class::operator<<, MACRO_CALLING_I6_FUNCTION, OperateOn, i1_GlobalFunction, i1_int, i1_int_global, i1_int_global2, i1_int_global2sub, i1_int_global3, i1_int_global3sub, i1_int_global4, i1_int_global4sub, i1_int_globalsub, i1_ns2, i1_ns4, i1_ns5, kI1ConstInt, operator==
#include "tests/cxx/badinc2.c"
class D2_Class;
class D2_ForwardDeclareClass;
class D2_Subclass;
class ForwardDeclareOnlyClass;  // lines XX-XX
class ForwardDeclareOnlyForTypedefClass;  // lines XX-XX
class I1_ForwardDeclareClass;
class I3_ForwardDeclareClass;  // lines XX-XX
class MacroClass;  // lines XX-XX
namespace d3_namespace { struct D3_Struct; }
namespace i3_ns1 { namespace i3_ns2 { namespace i3_ns3 { struct I3_ForwardDeclareNamespaceStruct; } } }  // lines XX-XX
namespace i3_ns1 { namespace i3_ns2 { namespace i3_ns3 { template <typename A, int B> struct I3_ForwardDeclareNamespaceTemplateStruct; } } }
namespace i3_ns1 { namespace { struct I3_UnnamedNamespaceStruct; } }
struct Cc_C_Struct;  // lines XX-XX
struct I3_ForwardDeclareStruct;
template <class T> struct Cc_OnlySpecializedStruct;  // lines XX-XX
template <typename A, int B, char C> struct I3_ForwardDeclareTemplateStruct;
template <typename T> struct I3_SimpleForwardDeclareTemplateStruct;  // lines XX-XX+1

***** IWYU_SUMMARY */

// TODO(csilvers): some new tests to add:
//   29) .h fwd-declares a class and .cc does as well.  Do we attribute to .cc?
//   30) forward-declare a class while inside a namespace.
//   31) "using foo::bar; Baz* x;" forward declare foo::bar::Baz properly?
//   32) "namespace b = foo::bar; b::Baz* x; forward declare Baz properly?
//   34) no mystruct fwd-decl for 'struct mystruct { mystruct* next; } myvar;'
//   41) template<class T, class V=hash<T> > void fn(), call fn<OperateOn>
//   43) *foo, where foo is a typedef to a pointer to an iwyu type.
//   44) typedef Foo Bar[sizeof(Baz)] -- make sure it says we need full type
//       info for Baz.
//   45) Define a global operator-new in badinc-i1.h and call it from badinc.cc