mirror of
https://github.com/github/codeql.git
synced 2026-05-17 12:47:08 +02:00
Compare commits
889 Commits
codeql-cli
...
codeql-cli
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9798fcddfa | ||
|
|
098dfb4242 | ||
|
|
a002f59f58 | ||
|
|
478a105e21 | ||
|
|
cd1f196848 | ||
|
|
222aa41bbf | ||
|
|
08ef31d452 | ||
|
|
41a527cf72 | ||
|
|
700f383bab | ||
|
|
e27aad9d6c | ||
|
|
af7fe89c5a | ||
|
|
5f5a87e2c7 | ||
|
|
75cc1d8f75 | ||
|
|
f8a0b6cd22 | ||
|
|
0afda68ba1 | ||
|
|
7cc01ea8b5 | ||
|
|
67c557115b | ||
|
|
fe0f766994 | ||
|
|
da8005dbd3 | ||
|
|
b0da1ef892 | ||
|
|
1fb4e13e0a | ||
|
|
e56cd0b498 | ||
|
|
7f2f6f14e7 | ||
|
|
b2c7c57815 | ||
|
|
66d13dc0d5 | ||
|
|
20df63f26d | ||
|
|
591565a0db | ||
|
|
5e14b5cca7 | ||
|
|
b2988e5516 | ||
|
|
986aa74db7 | ||
|
|
c55b0982f7 | ||
|
|
365b10183f | ||
|
|
20254c3d0a | ||
|
|
cafd08521e | ||
|
|
7cfe78a52d | ||
|
|
4ada83c0ba | ||
|
|
6614e037ae | ||
|
|
b8372c2f95 | ||
|
|
49a5a39395 | ||
|
|
3bcfbcdf68 | ||
|
|
234763efa6 | ||
|
|
3d20897725 | ||
|
|
e145b81f58 | ||
|
|
109e45e112 | ||
|
|
3fb024164b | ||
|
|
90888e592f | ||
|
|
7eb41140ab | ||
|
|
e6943ce98e | ||
|
|
99bc050366 | ||
|
|
bb317bc558 | ||
|
|
30a813ab08 | ||
|
|
3b9bd16097 | ||
|
|
26b76171ca | ||
|
|
a8b69e5b55 | ||
|
|
569f3c9b78 | ||
|
|
f662cceb0b | ||
|
|
8f70c9f950 | ||
|
|
44b734e120 | ||
|
|
8e229ac31b | ||
|
|
6a3b9e10eb | ||
|
|
fec9626fe7 | ||
|
|
a95aad51bd | ||
|
|
d12743d7c3 | ||
|
|
061575ff77 | ||
|
|
eb27428514 | ||
|
|
77db0cf547 | ||
|
|
72af8ac1e2 | ||
|
|
4f336820de | ||
|
|
ef804c018d | ||
|
|
77451de9a3 | ||
|
|
9359bea7b5 | ||
|
|
5e940cd46f | ||
|
|
e96cbeb00a | ||
|
|
c084a9b27a | ||
|
|
d45e9101ba | ||
|
|
0e9f8c4b97 | ||
|
|
b6dc2acc71 | ||
|
|
e2f671e327 | ||
|
|
6ecbb400d7 | ||
|
|
01af74aeda | ||
|
|
3680681e8b | ||
|
|
d76bb49b6a | ||
|
|
a0bad3ce15 | ||
|
|
a362ce083d | ||
|
|
c95d219c84 | ||
|
|
db685e5fc4 | ||
|
|
e24fa4705a | ||
|
|
ddb50b8120 | ||
|
|
ca7fa2e7c8 | ||
|
|
b71c41018c | ||
|
|
5bc8804242 | ||
|
|
88b51e6ad3 | ||
|
|
881d86321e | ||
|
|
f5d776571b | ||
|
|
df9c756369 | ||
|
|
d2a0b9a66c | ||
|
|
c265113073 | ||
|
|
ca5456a54a | ||
|
|
9e03a211a5 | ||
|
|
1942ea8396 | ||
|
|
280a27d9ca | ||
|
|
78c732db97 | ||
|
|
ef9453e862 | ||
|
|
307f44339c | ||
|
|
1a95a34441 | ||
|
|
4107758c8a | ||
|
|
2c6bbd8060 | ||
|
|
7053c62c41 | ||
|
|
75e6fd9c8e | ||
|
|
efe3c0d34a | ||
|
|
6011d26823 | ||
|
|
e39fb093e9 | ||
|
|
f4e6deeee0 | ||
|
|
1213eba630 | ||
|
|
5161cd1a3c | ||
|
|
2164069eda | ||
|
|
88d3fcb34b | ||
|
|
3d5b1986c9 | ||
|
|
c0a54e90c9 | ||
|
|
c95b58673a | ||
|
|
9f51f6f7ac | ||
|
|
13d4bd9c0a | ||
|
|
c10d03e74e | ||
|
|
35a300f894 | ||
|
|
b7dfa2347c | ||
|
|
a9906f6f7b | ||
|
|
3457f23db5 | ||
|
|
e5cd3e8f64 | ||
|
|
b28f60ccd2 | ||
|
|
36bdadfc36 | ||
|
|
58da62e244 | ||
|
|
3e2c6d69f9 | ||
|
|
08e1e8a120 | ||
|
|
94c15f712a | ||
|
|
0928fa6e1f | ||
|
|
36b1a0dc54 | ||
|
|
2578ef4786 | ||
|
|
089ea010d7 | ||
|
|
e33d303b48 | ||
|
|
e6c8a0b653 | ||
|
|
6b4bf12316 | ||
|
|
039925164d | ||
|
|
046e517c3f | ||
|
|
81d4149a17 | ||
|
|
b6b7e1589c | ||
|
|
c11da5bf67 | ||
|
|
663fb2cc06 | ||
|
|
8db3e4a9b4 | ||
|
|
6c0c8d6963 | ||
|
|
442dfc1833 | ||
|
|
b00e44725c | ||
|
|
9b19cde8ab | ||
|
|
2d3d21d074 | ||
|
|
d9844bd4d6 | ||
|
|
00ea023fdb | ||
|
|
1b4fef9c21 | ||
|
|
ea1f39683d | ||
|
|
045936b1fd | ||
|
|
cfc4a6a6b7 | ||
|
|
39762da5e0 | ||
|
|
a53da376d1 | ||
|
|
f60ca76eb2 | ||
|
|
1962aa3de4 | ||
|
|
71735c86c2 | ||
|
|
46185e3a02 | ||
|
|
b5ac0c94c6 | ||
|
|
7341b6156d | ||
|
|
a6177b3c92 | ||
|
|
7db1daba6e | ||
|
|
6c91f77776 | ||
|
|
30ae34352b | ||
|
|
4334a51cf3 | ||
|
|
ac1670c0af | ||
|
|
646e158813 | ||
|
|
81854279bd | ||
|
|
d385113e11 | ||
|
|
16ef11a3c3 | ||
|
|
fbd0c4edd0 | ||
|
|
a1a31bfd62 | ||
|
|
8f644af769 | ||
|
|
442f6875f5 | ||
|
|
0e1383ddd7 | ||
|
|
00cc78dfe6 | ||
|
|
a7382e06c2 | ||
|
|
653563fcbc | ||
|
|
1f6cdc7eda | ||
|
|
d2a5d19439 | ||
|
|
97c32970a0 | ||
|
|
1c2536321c | ||
|
|
3d9f8d50bc | ||
|
|
87c089e0a8 | ||
|
|
957757c271 | ||
|
|
d6919dd57b | ||
|
|
82a1b15d11 | ||
|
|
5a6ce293cc | ||
|
|
9b38028e25 | ||
|
|
9aae174942 | ||
|
|
f6aca58dbb | ||
|
|
eac44e89d9 | ||
|
|
6d949cbd39 | ||
|
|
a2b8eb924e | ||
|
|
f9fc79b16f | ||
|
|
f19232f800 | ||
|
|
5ffce86768 | ||
|
|
b365ff095a | ||
|
|
77fca277fe | ||
|
|
f377d25c23 | ||
|
|
4e954c29a2 | ||
|
|
b99b6b85ba | ||
|
|
5fff9fa8da | ||
|
|
a58aa17c7a | ||
|
|
1455e8bd4c | ||
|
|
dcc1429ed8 | ||
|
|
b750016bc1 | ||
|
|
2e338cc7b4 | ||
|
|
e40f0a7350 | ||
|
|
e7acf8c3a8 | ||
|
|
432c21d4fb | ||
|
|
ce9b018789 | ||
|
|
c20a17e7b7 | ||
|
|
51a05286fa | ||
|
|
23f0dd5542 | ||
|
|
b03f6efa60 | ||
|
|
142393b599 | ||
|
|
4239268efd | ||
|
|
6f3e2cdde3 | ||
|
|
c0baa5116f | ||
|
|
72356d1515 | ||
|
|
e04d30a676 | ||
|
|
6100425274 | ||
|
|
b4b2338144 | ||
|
|
6d7a75d1b9 | ||
|
|
8a490775d8 | ||
|
|
0eb6d1c76e | ||
|
|
acd16afddd | ||
|
|
cb1076c335 | ||
|
|
fe542565c3 | ||
|
|
01ff690d51 | ||
|
|
da66136ded | ||
|
|
d0e7354a1b | ||
|
|
9572b9d308 | ||
|
|
c0dec21546 | ||
|
|
7dac819730 | ||
|
|
6e8f600cb9 | ||
|
|
69aa099ed1 | ||
|
|
e828d8dace | ||
|
|
131b2b3e0c | ||
|
|
09346c76e7 | ||
|
|
fa729faa0a | ||
|
|
499b6f35e5 | ||
|
|
e2feed78a0 | ||
|
|
e927470961 | ||
|
|
560b876c01 | ||
|
|
fa23a45f9d | ||
|
|
cb6aed18f3 | ||
|
|
9da749ad77 | ||
|
|
0bce42410a | ||
|
|
859e1bfabc | ||
|
|
389294bded | ||
|
|
0391e063ca | ||
|
|
a1234d4235 | ||
|
|
2a1d5b7481 | ||
|
|
2b0fcab182 | ||
|
|
e9f0b535ea | ||
|
|
0ca3f3308b | ||
|
|
7da6da1c93 | ||
|
|
cebaca328e | ||
|
|
1cd32722be | ||
|
|
f4f5d43bcb | ||
|
|
28863f39b0 | ||
|
|
9d59f50340 | ||
|
|
e47e77c438 | ||
|
|
f33aff42ad | ||
|
|
75dad4764f | ||
|
|
f865fa3050 | ||
|
|
0ed724eb13 | ||
|
|
4f47461f60 | ||
|
|
f67d5e1dc6 | ||
|
|
1a511c2d52 | ||
|
|
ab334f6c1b | ||
|
|
cd22bb3505 | ||
|
|
03fbd387df | ||
|
|
45c39e6072 | ||
|
|
92db7b047c | ||
|
|
0673b19ce1 | ||
|
|
d4b5a4d4f4 | ||
|
|
7b33574b85 | ||
|
|
022a06659c | ||
|
|
79c90fa36a | ||
|
|
3e86c4c39e | ||
|
|
65fbcc570c | ||
|
|
eeaa361b12 | ||
|
|
07650af357 | ||
|
|
60f2e8a676 | ||
|
|
146c50049c | ||
|
|
f2f4e1f882 | ||
|
|
e9750af89f | ||
|
|
291f1a189d | ||
|
|
37a546253e | ||
|
|
5862cd2378 | ||
|
|
467231e469 | ||
|
|
073d170253 | ||
|
|
957c0d6387 | ||
|
|
e795e1c387 | ||
|
|
6e6e118d4b | ||
|
|
dc98dec5b6 | ||
|
|
3433437034 | ||
|
|
ab3f3d03c5 | ||
|
|
6bb9e6d122 | ||
|
|
58d8a2d77f | ||
|
|
2126ab0dde | ||
|
|
0d97c1c54a | ||
|
|
e62ec888c0 | ||
|
|
e1a5eba61b | ||
|
|
650ff8db87 | ||
|
|
0781cb78e8 | ||
|
|
5abf7769a7 | ||
|
|
2f9172046b | ||
|
|
ef1a5cb0fa | ||
|
|
34864e1077 | ||
|
|
6c989b9c6b | ||
|
|
693970f243 | ||
|
|
56e19411d0 | ||
|
|
05cf796c54 | ||
|
|
7ef3adcafd | ||
|
|
db88b7da88 | ||
|
|
b926a7ebba | ||
|
|
4d14311653 | ||
|
|
6208175aa9 | ||
|
|
0d33c32d8e | ||
|
|
4dbaed9ec2 | ||
|
|
b8717b3046 | ||
|
|
e14e0cdbb7 | ||
|
|
2300285204 | ||
|
|
23e2eb11dd | ||
|
|
fe4eef0bcb | ||
|
|
6ed4aaf94b | ||
|
|
33e991b037 | ||
|
|
af07efe14f | ||
|
|
f0a1742ad6 | ||
|
|
7c9d41d3b9 | ||
|
|
835b5e349b | ||
|
|
0f285ccce0 | ||
|
|
c0828a488f | ||
|
|
e2e9c810bf | ||
|
|
5a106fd5d6 | ||
|
|
3ebbb80a9e | ||
|
|
10bbf441dc | ||
|
|
ccc3094267 | ||
|
|
c7fb8de5f9 | ||
|
|
daf6ecd12f | ||
|
|
6f38769a9b | ||
|
|
024c5cfe2f | ||
|
|
0142309cab | ||
|
|
b301092e34 | ||
|
|
de0ec3e3f7 | ||
|
|
19622aec49 | ||
|
|
e64d581f7a | ||
|
|
d2a24dee7f | ||
|
|
516831aa41 | ||
|
|
c510d33fbf | ||
|
|
761db70d8d | ||
|
|
abe3a816ce | ||
|
|
7b3bdee5ea | ||
|
|
ea9f49efa1 | ||
|
|
97c688849d | ||
|
|
2d832db883 | ||
|
|
9807c0b0a6 | ||
|
|
b14db86ef9 | ||
|
|
050a563580 | ||
|
|
33eaeb9cf8 | ||
|
|
51c8331c8f | ||
|
|
3e9d9e72dc | ||
|
|
98e670f25c | ||
|
|
121d754be4 | ||
|
|
9c4d77a925 | ||
|
|
d3eb9c1325 | ||
|
|
5db569da89 | ||
|
|
e066e87890 | ||
|
|
877ee7047d | ||
|
|
86dbb507fd | ||
|
|
eb19052a7d | ||
|
|
981f67531c | ||
|
|
75c333273c | ||
|
|
d398c8c5a8 | ||
|
|
d80eff330b | ||
|
|
586c8803c5 | ||
|
|
e9bad321b6 | ||
|
|
7270b5079b | ||
|
|
fba37aa7c9 | ||
|
|
deb97a6ccc | ||
|
|
fc7f8409be | ||
|
|
3658710578 | ||
|
|
b69188fee9 | ||
|
|
e011480114 | ||
|
|
9ed8dec87f | ||
|
|
50f5c4d5f6 | ||
|
|
67cd25184a | ||
|
|
48048d6f38 | ||
|
|
00c704201c | ||
|
|
7ff6f09626 | ||
|
|
0c0720a962 | ||
|
|
2ac646770e | ||
|
|
1ad533a4f8 | ||
|
|
8702efda1e | ||
|
|
525ed65b0b | ||
|
|
f7923d93f1 | ||
|
|
0ae81eace3 | ||
|
|
5950865b55 | ||
|
|
72171972c3 | ||
|
|
84316c41a3 | ||
|
|
90052a3ca2 | ||
|
|
e2a0849a0e | ||
|
|
37455ec29e | ||
|
|
c5990311ca | ||
|
|
70bef64e2a | ||
|
|
f4a05c183b | ||
|
|
15daa51ee5 | ||
|
|
a23e77ca58 | ||
|
|
9a4de208ef | ||
|
|
d1a616a70a | ||
|
|
c38cbe859d | ||
|
|
131ae1aae9 | ||
|
|
1c425a5602 | ||
|
|
9b8d7df370 | ||
|
|
2f3e52646c | ||
|
|
5d69e14cc1 | ||
|
|
1988397f93 | ||
|
|
5049aafdd8 | ||
|
|
89aa86a1d6 | ||
|
|
56869553e8 | ||
|
|
ff5409fec7 | ||
|
|
0dafe2d757 | ||
|
|
a5f521cfa4 | ||
|
|
3007fdab5e | ||
|
|
096eeeb549 | ||
|
|
b953c4a1cf | ||
|
|
7bc8bf616f | ||
|
|
7bea18773c | ||
|
|
1ad51e754e | ||
|
|
0bd87f9f86 | ||
|
|
5124310f14 | ||
|
|
5f7e5b946d | ||
|
|
e30ac42e3e | ||
|
|
c8f5ada594 | ||
|
|
cb55b10edc | ||
|
|
9d643ae1ed | ||
|
|
116006d280 | ||
|
|
405a3a73d1 | ||
|
|
40219aad88 | ||
|
|
15da4ee009 | ||
|
|
6667d9e45c | ||
|
|
655f238017 | ||
|
|
199d1431d7 | ||
|
|
5946d5e806 | ||
|
|
0544205594 | ||
|
|
73d4b126cf | ||
|
|
b27a3a81bc | ||
|
|
21eb78ea5e | ||
|
|
fcb482b870 | ||
|
|
5c9a839ac7 | ||
|
|
c34c667e6b | ||
|
|
50e7892498 | ||
|
|
d7ea60e137 | ||
|
|
dbc6868bc1 | ||
|
|
9326fbd1dd | ||
|
|
4568cccd71 | ||
|
|
a9bc23fa3e | ||
|
|
7ba8a663bf | ||
|
|
c3c5fc0981 | ||
|
|
324eac7718 | ||
|
|
cf8dc64842 | ||
|
|
49c8daefca | ||
|
|
ab4e643bf8 | ||
|
|
ffd1456d67 | ||
|
|
a8ccc8d980 | ||
|
|
fc66b6ef9c | ||
|
|
99ac98bffc | ||
|
|
e97a4a1aea | ||
|
|
0604a85bb1 | ||
|
|
21ec83a197 | ||
|
|
b500d8baa1 | ||
|
|
2b741448f4 | ||
|
|
41487987b5 | ||
|
|
d111fa7e94 | ||
|
|
b5d08ade59 | ||
|
|
e73e312e10 | ||
|
|
621c05dc4b | ||
|
|
bc3e78f034 | ||
|
|
058236877e | ||
|
|
5ad984f22f | ||
|
|
da87d82d08 | ||
|
|
be629b27ed | ||
|
|
f5c4155d63 | ||
|
|
44b8ec642e | ||
|
|
8cc367c45e | ||
|
|
37b6b46dbf | ||
|
|
50603102d1 | ||
|
|
457604e37e | ||
|
|
938a7a788f | ||
|
|
abed936556 | ||
|
|
1bc222ec40 | ||
|
|
2e89a11949 | ||
|
|
18fe587e75 | ||
|
|
2b3cab355d | ||
|
|
ef8d95f87d | ||
|
|
5a5e921ee7 | ||
|
|
a8c64443e8 | ||
|
|
b547ae7c2f | ||
|
|
1d5eb4a960 | ||
|
|
caf2180bad | ||
|
|
3bc7cf6ac7 | ||
|
|
9ab2a28de0 | ||
|
|
df1e8e263b | ||
|
|
d98079d72c | ||
|
|
216911dad9 | ||
|
|
3d495bdd43 | ||
|
|
47a536c85d | ||
|
|
af854749d7 | ||
|
|
f437a6f729 | ||
|
|
558238a9be | ||
|
|
46f80dc5ca | ||
|
|
f272b0786a | ||
|
|
7f82aba7d4 | ||
|
|
2240e4bffb | ||
|
|
9a334d3300 | ||
|
|
e87b8ba3d7 | ||
|
|
a148c7cc87 | ||
|
|
1c64fb16f1 | ||
|
|
da3eb28767 | ||
|
|
a0c0da78e9 | ||
|
|
c4b782407b | ||
|
|
4d05b742d6 | ||
|
|
32da3c3730 | ||
|
|
f921076fca | ||
|
|
5488abc512 | ||
|
|
41f1315da9 | ||
|
|
e534afe634 | ||
|
|
12f2539d1d | ||
|
|
20b0969a97 | ||
|
|
2562f8a297 | ||
|
|
3bd4d34a47 | ||
|
|
74e5c15eaa | ||
|
|
b5518047fa | ||
|
|
4656130dab | ||
|
|
0bc75ea9b7 | ||
|
|
93e5b2260e | ||
|
|
fd1949092c | ||
|
|
ce9a14b692 | ||
|
|
4529d8b75a | ||
|
|
f6b6a988ca | ||
|
|
22ae430e65 | ||
|
|
bb4fe2002f | ||
|
|
3e7a7fe54e | ||
|
|
01a512b677 | ||
|
|
0895853a23 | ||
|
|
e8f4aee1cf | ||
|
|
00d5cb737c | ||
|
|
d2b8d836e9 | ||
|
|
40eab180cc | ||
|
|
08cba7dc5f | ||
|
|
6039af0087 | ||
|
|
7ed520ab54 | ||
|
|
a020189895 | ||
|
|
f08879a2df | ||
|
|
6fa2d2764d | ||
|
|
a98ae8941c | ||
|
|
2dff0ce5b4 | ||
|
|
8bf960bd44 | ||
|
|
021eedfdf1 | ||
|
|
84dacbfbfd | ||
|
|
82fd0e45aa | ||
|
|
a9d2f43538 | ||
|
|
8ed773b240 | ||
|
|
09c64e8fee | ||
|
|
1694915535 | ||
|
|
499bd970d3 | ||
|
|
c3a2ae2943 | ||
|
|
c089368557 | ||
|
|
90ac5b905b | ||
|
|
2a49219127 | ||
|
|
beacade499 | ||
|
|
15244e0ee1 | ||
|
|
2d88ac1846 | ||
|
|
e2740fef73 | ||
|
|
f5e17d7d39 | ||
|
|
2ba983bf4a | ||
|
|
d9800c7bb6 | ||
|
|
d0a912fb02 | ||
|
|
57a55eda75 | ||
|
|
82057513c5 | ||
|
|
c36ce785d8 | ||
|
|
aa6d7c088b | ||
|
|
9588e68115 | ||
|
|
3eb1bac9df | ||
|
|
44d785fabf | ||
|
|
c239a4399c | ||
|
|
97a4230d5d | ||
|
|
f3fc56294e | ||
|
|
8438fb2310 | ||
|
|
9d6bc76dc0 | ||
|
|
9b2b58a823 | ||
|
|
e0cc337c71 | ||
|
|
f40bcd0cdd | ||
|
|
bf5ba37348 | ||
|
|
e54341a170 | ||
|
|
c69a9ea032 | ||
|
|
778de6b5d2 | ||
|
|
536fd349bd | ||
|
|
8685242c16 | ||
|
|
24cdc962c2 | ||
|
|
a4a492627d | ||
|
|
409471c3b2 | ||
|
|
602eb43109 | ||
|
|
358737452e | ||
|
|
aa59741c38 | ||
|
|
532552a7ac | ||
|
|
2067d393e1 | ||
|
|
b2688bba7d | ||
|
|
f3c6564dc3 | ||
|
|
08f5774d13 | ||
|
|
fbbc2938c3 | ||
|
|
698b8d3c5c | ||
|
|
ac3c4fd5ef | ||
|
|
b8b38e4bbe | ||
|
|
5188095529 | ||
|
|
aedd073dad | ||
|
|
0a7eecf28c | ||
|
|
c9fc5a54c7 | ||
|
|
4fcb576099 | ||
|
|
1f39ec3188 | ||
|
|
cd4ec6c996 | ||
|
|
60c7c84018 | ||
|
|
9f2ee0d7c2 | ||
|
|
b1c6ee4396 | ||
|
|
13989dba91 | ||
|
|
099e11fb0c | ||
|
|
997eb1caf2 | ||
|
|
2caad67980 | ||
|
|
99f6e685c7 | ||
|
|
54afed6e1d | ||
|
|
46832d0b17 | ||
|
|
e75f604172 | ||
|
|
7f7930b3bb | ||
|
|
af904f5cfe | ||
|
|
97809e7646 | ||
|
|
e1f519fab7 | ||
|
|
e1763db36c | ||
|
|
9f9cf9f765 | ||
|
|
70ac0a5462 | ||
|
|
2cfa14b91f | ||
|
|
5cad8ec0a2 | ||
|
|
a176ba262b | ||
|
|
6ebd5ab3ed | ||
|
|
0d116a00fb | ||
|
|
3767ce5a99 | ||
|
|
1612ee3e9a | ||
|
|
55cfadb1f4 | ||
|
|
359a9e5fe8 | ||
|
|
374c157afe | ||
|
|
e27399c9ef | ||
|
|
27c12de178 | ||
|
|
2582b084f6 | ||
|
|
21937e6a27 | ||
|
|
c0407ae0be | ||
|
|
acb1310e99 | ||
|
|
26d4f9f0fd | ||
|
|
cd3b519081 | ||
|
|
db8b506106 | ||
|
|
88b78284ec | ||
|
|
13027a1094 | ||
|
|
2f2f507a5d | ||
|
|
0a0e34716e | ||
|
|
4a276c37ac | ||
|
|
4345369e9b | ||
|
|
d02a1c2840 | ||
|
|
5edc5e7c7b | ||
|
|
a272eb8447 | ||
|
|
9108982b07 | ||
|
|
9cb09d6e9a | ||
|
|
aa6bf67482 | ||
|
|
1fa6511482 | ||
|
|
f0ab3a3c84 | ||
|
|
8ab2f89d53 | ||
|
|
786c6e1c5e | ||
|
|
645028e219 | ||
|
|
4676ca5a4a | ||
|
|
c44507cc42 | ||
|
|
39b6d927d6 | ||
|
|
066a6ef7c4 | ||
|
|
b8f67d7e8a | ||
|
|
b62c86d89c | ||
|
|
dc89e0d2b0 | ||
|
|
af8612ecd2 | ||
|
|
6c0d47f122 | ||
|
|
4e7438ac5c | ||
|
|
d3b3af8ae6 | ||
|
|
36ff54b48b | ||
|
|
cc5a404149 | ||
|
|
226103b246 | ||
|
|
f054f73836 | ||
|
|
1de68457ae | ||
|
|
0156fcc381 | ||
|
|
3a6665b0ed | ||
|
|
5330ce12cc | ||
|
|
00e0e5a61a | ||
|
|
419bbbc9ac | ||
|
|
94780aabec | ||
|
|
1259f8d596 | ||
|
|
89e7b75ea1 | ||
|
|
d9187c62fe | ||
|
|
1cfb9bbf34 | ||
|
|
a2f4628522 | ||
|
|
ac389067fe | ||
|
|
f91b7a9342 | ||
|
|
742f080a55 | ||
|
|
d350c0d5c8 | ||
|
|
0859c4f926 | ||
|
|
69ea7d92cd | ||
|
|
d905b1e006 | ||
|
|
83aef6fc16 | ||
|
|
108cd7f078 | ||
|
|
d13170de98 | ||
|
|
52e84ba12b | ||
|
|
7c0c820684 | ||
|
|
6110243306 | ||
|
|
5270cf6c41 | ||
|
|
8a314dd2cf | ||
|
|
4f57852ba0 | ||
|
|
a7ee27ec22 | ||
|
|
6c3c4c302e | ||
|
|
412cf558f2 | ||
|
|
4075dacd52 | ||
|
|
79da723878 | ||
|
|
3d515b18df | ||
|
|
369cee9ed9 | ||
|
|
4c9c5d8f0c | ||
|
|
75c5d16406 | ||
|
|
ec650b80fd | ||
|
|
7c429fb924 | ||
|
|
61079e07c1 | ||
|
|
252d969efd | ||
|
|
e76dc4a1f9 | ||
|
|
41ad1ed8b4 | ||
|
|
ec9997781c | ||
|
|
883543fd77 | ||
|
|
2a63116fc2 | ||
|
|
922f4d5496 | ||
|
|
238cb26624 | ||
|
|
29543f5726 | ||
|
|
2dbbcc2413 | ||
|
|
afc46576f0 | ||
|
|
093c6905dd | ||
|
|
99d8ae720f | ||
|
|
bcc45658b3 | ||
|
|
1fac08ef6c | ||
|
|
dfa5e18988 | ||
|
|
c7084b6d8e | ||
|
|
81a25b23ba | ||
|
|
d4b635d674 | ||
|
|
169326ffe5 | ||
|
|
0b35be284e | ||
|
|
05cb429635 | ||
|
|
ef9376d39c | ||
|
|
70a9fe3974 | ||
|
|
eca2c21af5 | ||
|
|
bc4724b1fb | ||
|
|
8a0286ec34 | ||
|
|
9432fec612 | ||
|
|
3f36d3244b | ||
|
|
378313332b | ||
|
|
6b425f1395 | ||
|
|
6793bc6c6b | ||
|
|
a524735236 | ||
|
|
0db535bdd7 | ||
|
|
2c3117a981 | ||
|
|
aaea1ad2fa | ||
|
|
2947f176ef | ||
|
|
42cc6448cc | ||
|
|
eb5c600a6b | ||
|
|
2b0a8097e6 | ||
|
|
f1c82b650f | ||
|
|
919cb07c1e | ||
|
|
f3fab587a9 | ||
|
|
991d5cc54b | ||
|
|
64a7206f3e | ||
|
|
15269c9166 | ||
|
|
0f9ab8f53e | ||
|
|
7c9e1ad6ec | ||
|
|
362e8f7dd2 | ||
|
|
ee1ba71e5d | ||
|
|
10cd649ba7 | ||
|
|
69efddbaef | ||
|
|
1559b7da3c | ||
|
|
7a717555aa | ||
|
|
733e625080 | ||
|
|
f2cc2af276 | ||
|
|
76455d628e | ||
|
|
c9fadd98f4 | ||
|
|
02c41f3dcf | ||
|
|
d7d9ffc449 | ||
|
|
4d2ce6b2e0 | ||
|
|
a892e83c8e | ||
|
|
ff1ae7d9c6 | ||
|
|
0247278bad | ||
|
|
cea3477ac2 | ||
|
|
c255f8717d | ||
|
|
c4f72dd2f2 | ||
|
|
e8563e5dfd | ||
|
|
2ce1192ee6 | ||
|
|
f45b89a3cc | ||
|
|
047d486509 | ||
|
|
e45a31744f | ||
|
|
a3c58c66e9 | ||
|
|
bfbb77a796 | ||
|
|
8dbb0a51c0 | ||
|
|
01798f63f8 | ||
|
|
30615308b4 | ||
|
|
b807d005ec | ||
|
|
4ed90d5234 | ||
|
|
81372d0b63 | ||
|
|
922fc3aba7 | ||
|
|
c11ce4ce68 | ||
|
|
958ae24a61 | ||
|
|
e74eccdd97 | ||
|
|
38ecfd8233 | ||
|
|
df58902674 | ||
|
|
d5f4939719 | ||
|
|
23bf8470ce | ||
|
|
8c9ccab9c9 | ||
|
|
72d9d4736e | ||
|
|
2112d73a6a | ||
|
|
1a108fb1c9 | ||
|
|
7c235e3786 | ||
|
|
8c73fbeabe | ||
|
|
55eeb00309 | ||
|
|
b6c35dd88c | ||
|
|
c612a7a16b | ||
|
|
1d32f6efc3 | ||
|
|
bab4eeeb55 | ||
|
|
c42e65cbaf | ||
|
|
22fe055e53 | ||
|
|
0b09fdae43 | ||
|
|
e93b44670f | ||
|
|
edb822279b | ||
|
|
70ff401f21 | ||
|
|
ab3b87a3f2 | ||
|
|
2183d380db | ||
|
|
a8f887e3f9 | ||
|
|
2d8318dc02 | ||
|
|
065b69460d | ||
|
|
5e33f14ff1 | ||
|
|
d45d046fa7 | ||
|
|
d8bc818d5a | ||
|
|
dfbf259e2d | ||
|
|
9ab6eabd15 | ||
|
|
15047368e8 | ||
|
|
3f7c4dec25 | ||
|
|
d81dc274f6 | ||
|
|
05ed66ad8f | ||
|
|
5a2433244e | ||
|
|
b0882a9e5f | ||
|
|
026d94c457 | ||
|
|
2fb6cdc19b | ||
|
|
c65c65557d | ||
|
|
3685590a12 | ||
|
|
7adcd0d043 | ||
|
|
87c73879cb | ||
|
|
826d7c7dbe | ||
|
|
146591934a | ||
|
|
f6a6958c03 | ||
|
|
92c20be038 | ||
|
|
6c954eae3c | ||
|
|
dfbc248e78 | ||
|
|
0aed7d56c2 | ||
|
|
2592129d83 | ||
|
|
c8ca6057d3 | ||
|
|
4ac91ea1b2 | ||
|
|
dcca0278b8 | ||
|
|
ab5b267a39 | ||
|
|
2eb82fede7 | ||
|
|
b6146478dc | ||
|
|
1274aaaf9c | ||
|
|
476cf72710 | ||
|
|
348bc964be | ||
|
|
b269bd5010 | ||
|
|
9a27016663 | ||
|
|
f1905f21b2 | ||
|
|
4380495eed |
@@ -1 +1 @@
|
||||
6.1.2
|
||||
6.3.1
|
||||
|
||||
@@ -1,24 +1,4 @@
|
||||
{
|
||||
"DataFlow Java/C++/C#/Go/Python/Ruby/Swift": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlow.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll"
|
||||
],
|
||||
"DataFlowImpl Java/C++/C#/Go/Python/Ruby/Swift": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Go/Python/Ruby/Swift Legacy Configuration": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll",
|
||||
@@ -42,7 +22,6 @@
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||
@@ -53,16 +32,6 @@
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll"
|
||||
],
|
||||
"DataFlow Java/C++/C#/Go/Python/Ruby/Swift Common": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll",
|
||||
"swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll"
|
||||
],
|
||||
"TaintTracking Java/C++/C#/Go/Python/Ruby/Swift": [
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll",
|
||||
@@ -514,11 +483,6 @@
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
|
||||
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"CFG": [
|
||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||
"ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||
"swift/ql/lib/codeql/swift/controlflow/internal/ControlFlowGraphImplShared.qll"
|
||||
],
|
||||
"TypeTracker": [
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/TypeTracker.qll",
|
||||
"ruby/ql/lib/codeql/ruby/typetracking/TypeTracker.qll"
|
||||
|
||||
@@ -327,7 +327,7 @@ namespace Semmle.Autobuild.Cpp.Tests
|
||||
{
|
||||
Actions.RunProcess[@"cmd.exe /C nuget restore C:\Project\test.sln -DisableParallelProcessing"] = 1;
|
||||
Actions.RunProcess[@"cmd.exe /C C:\Project\.nuget\nuget.exe restore C:\Project\test.sln -DisableParallelProcessing"] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program Files ^(x86^)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
|
||||
Actions.RunProcess[@"cmd.exe /C CALL ^""C:\Program^ Files^ ^(x86^)\Microsoft^ Visual^ Studio^ 14.0\VC\vcvarsall.bat^"" && set Platform=&& type NUL && msbuild C:\Project\test.sln /t:rebuild /p:Platform=""x86"" /p:Configuration=""Release"""] = 0;
|
||||
Actions.RunProcessOut[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = "";
|
||||
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationPath"] = 1;
|
||||
Actions.RunProcess[@"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe -prerelease -legacy -property installationVersion"] = 0;
|
||||
|
||||
2212
cpp/downgrades/d77c09d8bdc172c9201dec293de1e14c931d3f05/old.dbscheme
Normal file
2212
cpp/downgrades/d77c09d8bdc172c9201dec293de1e14c931d3f05/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Remove _Float128 type
|
||||
compatibility: full
|
||||
@@ -1,3 +1,22 @@
|
||||
## 0.9.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.9.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `shouldPrintFunction` predicate from `PrintAstConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
|
||||
* The `shouldPrintFunction` predicate from `PrintIRConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The `PrintAST` library now also prints global and namespace variables and their initializers.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `_Float128x` type is no longer exposed as a builtin type. As this type could not occur any code base, this should only affect queries that explicitly looked at the builtin types.
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
14
cpp/ql/lib/change-notes/released/0.9.0.md
Normal file
14
cpp/ql/lib/change-notes/released/0.9.0.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## 0.9.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `shouldPrintFunction` predicate from `PrintAstConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
|
||||
* The `shouldPrintFunction` predicate from `PrintIRConfiguration` has been replaced by `shouldPrintDeclaration`. Users should now override `shouldPrintDeclaration` if they want to limit the declarations that should be printed.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* The `PrintAST` library now also prints global and namespace variables and their initializers.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `_Float128x` type is no longer exposed as a builtin type. As this type could not occur any code base, this should only affect queries that explicitly looked at the builtin types.
|
||||
3
cpp/ql/lib/change-notes/released/0.9.1.md
Normal file
3
cpp/ql/lib/change-notes/released/0.9.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.9.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.8.1
|
||||
lastReleaseVersion: 0.9.1
|
||||
|
||||
@@ -18,10 +18,10 @@ external string selectedSourceFile();
|
||||
|
||||
class Cfg extends PrintAstConfiguration {
|
||||
/**
|
||||
* Holds if the AST for `func` should be printed.
|
||||
* Print All functions from the selected file.
|
||||
* Holds if the AST for `decl` should be printed.
|
||||
* Print All declarations from the selected file.
|
||||
*/
|
||||
override predicate shouldPrintFunction(Function func) {
|
||||
func.getFile() = getFileBySourceArchiveName(selectedSourceFile())
|
||||
override predicate shouldPrintDeclaration(Declaration decl) {
|
||||
decl.getFile() = getFileBySourceArchiveName(selectedSourceFile())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.8.1
|
||||
version: 0.9.1
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
library: true
|
||||
upgrades: upgrades
|
||||
dependencies:
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
|
||||
@@ -6,11 +6,9 @@ private import PrintAST
|
||||
* that requests that function, or no `PrintASTConfiguration` exists.
|
||||
*/
|
||||
private predicate shouldPrintDeclaration(Declaration decl) {
|
||||
not decl instanceof Function
|
||||
not (decl instanceof Function or decl instanceof GlobalOrNamespaceVariable)
|
||||
or
|
||||
not exists(PrintAstConfiguration c)
|
||||
or
|
||||
exists(PrintAstConfiguration config | config.shouldPrintFunction(decl))
|
||||
exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,13 +9,13 @@ import cpp
|
||||
import PrintAST
|
||||
|
||||
/**
|
||||
* Temporarily tweak this class or make a copy to control which functions are
|
||||
* Temporarily tweak this class or make a copy to control which declarations are
|
||||
* printed.
|
||||
*/
|
||||
class Cfg extends PrintAstConfiguration {
|
||||
/**
|
||||
* TWEAK THIS PREDICATE AS NEEDED.
|
||||
* Holds if the AST for `func` should be printed.
|
||||
* Holds if the AST for `decl` should be printed.
|
||||
*/
|
||||
override predicate shouldPrintFunction(Function func) { any() }
|
||||
override predicate shouldPrintDeclaration(Declaration decl) { any() }
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* Provides queries to pretty-print a C++ AST as a graph.
|
||||
*
|
||||
* By default, this will print the AST for all functions in the database. To change this behavior,
|
||||
* extend `PrintASTConfiguration` and override `shouldPrintFunction` to hold for only the functions
|
||||
* you wish to view the AST for.
|
||||
* By default, this will print the AST for all functions and global and namespace variables in
|
||||
* the database. To change this behavior, extend `PrintASTConfiguration` and override
|
||||
* `shouldPrintDeclaration` to hold for only the declarations you wish to view the AST for.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
@@ -12,7 +12,7 @@ private import semmle.code.cpp.Print
|
||||
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
|
||||
|
||||
/**
|
||||
* The query can extend this class to control which functions are printed.
|
||||
* The query can extend this class to control which declarations are printed.
|
||||
*/
|
||||
class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
/**
|
||||
@@ -21,14 +21,16 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
string toString() { result = "PrintASTConfiguration" }
|
||||
|
||||
/**
|
||||
* Holds if the AST for `func` should be printed. By default, holds for all
|
||||
* functions.
|
||||
* Holds if the AST for `decl` should be printed. By default, holds for all
|
||||
* functions and global and namespace variables. Currently, does not support any
|
||||
* other declaration types.
|
||||
*/
|
||||
predicate shouldPrintFunction(Function func) { any() }
|
||||
predicate shouldPrintDeclaration(Declaration decl) { any() }
|
||||
}
|
||||
|
||||
private predicate shouldPrintFunction(Function func) {
|
||||
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
|
||||
private predicate shouldPrintDeclaration(Declaration decl) {
|
||||
exists(PrintAstConfiguration config | config.shouldPrintDeclaration(decl)) and
|
||||
(decl instanceof Function or decl instanceof GlobalOrNamespaceVariable)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
@@ -69,7 +71,7 @@ private predicate locationSortKeys(Locatable ast, string file, int line, int col
|
||||
)
|
||||
}
|
||||
|
||||
private Function getEnclosingFunction(Locatable ast) {
|
||||
private Declaration getAnEnclosingDeclaration(Locatable ast) {
|
||||
result = ast.(Expr).getEnclosingFunction()
|
||||
or
|
||||
result = ast.(Stmt).getEnclosingFunction()
|
||||
@@ -78,6 +80,10 @@ private Function getEnclosingFunction(Locatable ast) {
|
||||
or
|
||||
result = ast.(Parameter).getFunction()
|
||||
or
|
||||
result = ast.(Expr).getEnclosingDeclaration()
|
||||
or
|
||||
result = ast.(Initializer).getDeclaration()
|
||||
or
|
||||
result = ast
|
||||
}
|
||||
|
||||
@@ -86,21 +92,21 @@ private Function getEnclosingFunction(Locatable ast) {
|
||||
* nodes for things like parameter lists and constructor init lists.
|
||||
*/
|
||||
private newtype TPrintAstNode =
|
||||
TAstNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
|
||||
TAstNode(Locatable ast) { shouldPrintDeclaration(getAnEnclosingDeclaration(ast)) } or
|
||||
TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) {
|
||||
// We create a unique node for each pair of (stmt, entry), to avoid having one node with
|
||||
// multiple parents due to extractor bug CPP-413.
|
||||
stmt.getADeclarationEntry() = entry and
|
||||
shouldPrintFunction(stmt.getEnclosingFunction())
|
||||
shouldPrintDeclaration(stmt.getEnclosingFunction())
|
||||
} or
|
||||
TParametersNode(Function func) { shouldPrintFunction(func) } or
|
||||
TParametersNode(Function func) { shouldPrintDeclaration(func) } or
|
||||
TConstructorInitializersNode(Constructor ctor) {
|
||||
ctor.hasEntryPoint() and
|
||||
shouldPrintFunction(ctor)
|
||||
shouldPrintDeclaration(ctor)
|
||||
} or
|
||||
TDestructorDestructionsNode(Destructor dtor) {
|
||||
dtor.hasEntryPoint() and
|
||||
shouldPrintFunction(dtor)
|
||||
shouldPrintDeclaration(dtor)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,10 +164,10 @@ class PrintAstNode extends TPrintAstNode {
|
||||
|
||||
/**
|
||||
* Holds if this node should be printed in the output. By default, all nodes
|
||||
* within a function are printed, but the query can override
|
||||
* `PrintASTConfiguration.shouldPrintFunction` to filter the output.
|
||||
* within functions and global and namespace variables are printed, but the query
|
||||
* can override `PrintASTConfiguration.shouldPrintDeclaration` to filter the output.
|
||||
*/
|
||||
final predicate shouldPrint() { shouldPrintFunction(this.getEnclosingFunction()) }
|
||||
final predicate shouldPrint() { shouldPrintDeclaration(this.getEnclosingDeclaration()) }
|
||||
|
||||
/**
|
||||
* Gets the children of this node.
|
||||
@@ -229,10 +235,15 @@ class PrintAstNode extends TPrintAstNode {
|
||||
abstract string getChildAccessorPredicateInternal(int childIndex);
|
||||
|
||||
/**
|
||||
* Gets the `Function` that contains this node.
|
||||
* Gets the `Declaration` that contains this node.
|
||||
*/
|
||||
private Function getEnclosingFunction() {
|
||||
result = this.getParent*().(FunctionNode).getFunction()
|
||||
private Declaration getEnclosingDeclaration() { result = this.getParent*().getDeclaration() }
|
||||
|
||||
/**
|
||||
* Gets the `Declaration` this node represents.
|
||||
*/
|
||||
private Declaration getDeclaration() {
|
||||
result = this.(AstNode).getAst() and shouldPrintDeclaration(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,16 +582,53 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
|
||||
final Destructor getDestructor() { result = dtor }
|
||||
}
|
||||
|
||||
abstract private class FunctionOrGlobalOrNamespaceVariableNode extends AstNode {
|
||||
override string toString() { result = qlClass(ast) + getIdentityString(ast) }
|
||||
|
||||
private int getOrder() {
|
||||
this =
|
||||
rank[result](FunctionOrGlobalOrNamespaceVariableNode node, Declaration decl, string file,
|
||||
int line, int column |
|
||||
node.getAst() = decl and
|
||||
locationSortKeys(decl, file, line, column)
|
||||
|
|
||||
node order by file, line, column, getIdentityString(decl)
|
||||
)
|
||||
}
|
||||
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `GlobalOrNamespaceVariable`.
|
||||
*/
|
||||
class GlobalOrNamespaceVariableNode extends FunctionOrGlobalOrNamespaceVariableNode {
|
||||
GlobalOrNamespaceVariable var;
|
||||
|
||||
GlobalOrNamespaceVariableNode() { var = ast }
|
||||
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.(AstNode).getAst() = var.getInitializer()
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
childIndex = 0 and result = "getInitializer()"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `Function`.
|
||||
*/
|
||||
class FunctionNode extends AstNode {
|
||||
class FunctionNode extends FunctionOrGlobalOrNamespaceVariableNode {
|
||||
Function func;
|
||||
|
||||
FunctionNode() { func = ast }
|
||||
|
||||
override string toString() { result = qlClass(func) + getIdentityString(func) }
|
||||
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.(ParametersNode).getFunction() = func
|
||||
@@ -604,31 +652,10 @@ class FunctionNode extends AstNode {
|
||||
or
|
||||
childIndex = 3 and result = "<destructions>"
|
||||
}
|
||||
|
||||
private int getOrder() {
|
||||
this =
|
||||
rank[result](FunctionNode node, Function function, string file, int line, int column |
|
||||
node.getAst() = function and
|
||||
locationSortKeys(function, file, line, column)
|
||||
|
|
||||
node order by file, line, column, getIdentityString(function)
|
||||
)
|
||||
}
|
||||
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `Function` this node represents.
|
||||
*/
|
||||
final Function getFunction() { result = func }
|
||||
}
|
||||
|
||||
private string getChildAccessorWithoutConversions(Locatable parent, Element child) {
|
||||
shouldPrintFunction(getEnclosingFunction(parent)) and
|
||||
shouldPrintDeclaration(getAnEnclosingDeclaration(parent)) and
|
||||
(
|
||||
exists(Stmt s | s = parent |
|
||||
namedStmtChildPredicates(s, child, result)
|
||||
@@ -647,7 +674,7 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
|
||||
}
|
||||
|
||||
private predicate namedStmtChildPredicates(Locatable s, Element e, string pred) {
|
||||
shouldPrintFunction(getEnclosingFunction(s)) and
|
||||
shouldPrintDeclaration(getAnEnclosingDeclaration(s)) and
|
||||
(
|
||||
exists(int n | s.(BlockStmt).getStmt(n) = e and pred = "getStmt(" + n + ")")
|
||||
or
|
||||
@@ -735,7 +762,7 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
|
||||
}
|
||||
|
||||
private predicate namedExprChildPredicates(Expr expr, Element ele, string pred) {
|
||||
shouldPrintFunction(expr.getEnclosingFunction()) and
|
||||
shouldPrintDeclaration(expr.getEnclosingDeclaration()) and
|
||||
(
|
||||
expr.(Access).getTarget() = ele and pred = "getTarget()"
|
||||
or
|
||||
|
||||
@@ -814,9 +814,6 @@ private predicate floatingPointTypeMapping(
|
||||
// _Float128
|
||||
kind = 49 and base = 2 and domain = TRealDomain() and realKind = 49 and extended = false
|
||||
or
|
||||
// _Float128x
|
||||
kind = 50 and base = 2 and domain = TRealDomain() and realKind = 50 and extended = true
|
||||
or
|
||||
// _Float16
|
||||
kind = 52 and base = 2 and domain = TRealDomain() and realKind = 52 and extended = false
|
||||
or
|
||||
|
||||
@@ -26,6 +26,8 @@ import cpp
|
||||
* global (inter-procedural) data flow analyses.
|
||||
*/
|
||||
deprecated module DataFlow {
|
||||
import semmle.code.cpp.dataflow.internal.DataFlow
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<CppOldDataFlow>
|
||||
import semmle.code.cpp.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -1,433 +0,0 @@
|
||||
/**
|
||||
* Provides an implementation of global (interprocedural) data flow. This file
|
||||
* re-exports the local (intraprocedural) data flow analysis from
|
||||
* `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed
|
||||
* through the `Global` and `GlobalWithState` modules.
|
||||
*/
|
||||
|
||||
private import DataFlowImplCommon
|
||||
private import DataFlowImplSpecific::Private
|
||||
import DataFlowImplSpecific::Public
|
||||
import DataFlowImplCommonPublic
|
||||
private import DataFlowImpl
|
||||
|
||||
/** An input configuration for data flow. */
|
||||
signature module ConfigSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
predicate isSource(Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
predicate isSink(Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
*/
|
||||
default predicate isBarrier(Node node) { none() }
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
default predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
default predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
default predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `node` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
default predicate neverSkip(Node node) {
|
||||
isAdditionalFlowStep(node, _) or isAdditionalFlowStep(_, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
* This can be overridden to a smaller value to improve performance (a
|
||||
* value of 0 disables field flow), or a larger value to get more results.
|
||||
*/
|
||||
default int fieldFlowBranchLimit() { result = 2 }
|
||||
|
||||
/**
|
||||
* Gets a data flow configuration feature to add restrictions to the set of
|
||||
* valid flow paths.
|
||||
*
|
||||
* - `FeatureHasSourceCallContext`:
|
||||
* Assume that sources have some existing call context to disallow
|
||||
* conflicting return-flow directly following the source.
|
||||
* - `FeatureHasSinkCallContext`:
|
||||
* Assume that sinks have some existing call context to disallow
|
||||
* conflicting argument-to-parameter flow directly preceding the sink.
|
||||
* - `FeatureEqualSourceSinkCallContext`:
|
||||
* Implies both of the above and additionally ensures that the entire flow
|
||||
* path preserves the call context.
|
||||
*
|
||||
* These features are generally not relevant for typical end-to-end data flow
|
||||
* queries, but should only be used for constructing paths that need to
|
||||
* somehow be pluggable in another path context.
|
||||
*/
|
||||
default FlowFeature getAFeature() { none() }
|
||||
|
||||
/** Holds if sources should be grouped in the result of `flowPath`. */
|
||||
default predicate sourceGrouping(Node source, string sourceGroup) { none() }
|
||||
|
||||
/** Holds if sinks should be grouped in the result of `flowPath`. */
|
||||
default predicate sinkGrouping(Node sink, string sinkGroup) { none() }
|
||||
|
||||
/**
|
||||
* Holds if hidden nodes should be included in the data flow graph.
|
||||
*
|
||||
* This feature should only be used for debugging or when the data flow graph
|
||||
* is not visualized (as it is in a `path-problem` query).
|
||||
*/
|
||||
default predicate includeHiddenNodes() { none() }
|
||||
}
|
||||
|
||||
/** An input configuration for data flow using flow state. */
|
||||
signature module StateConfigSig {
|
||||
bindingset[this]
|
||||
class FlowState;
|
||||
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source with the given initial
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSource(Node source, FlowState state);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink accepting `state`.
|
||||
*/
|
||||
predicate isSink(Node sink, FlowState state);
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
*/
|
||||
default predicate isBarrier(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
default predicate isBarrier(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
default predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
default predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
* This step is only applicable in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
default predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `node` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
default predicate neverSkip(Node node) {
|
||||
isAdditionalFlowStep(node, _) or
|
||||
isAdditionalFlowStep(_, node) or
|
||||
isAdditionalFlowStep(node, _, _, _) or
|
||||
isAdditionalFlowStep(_, _, node, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
* This can be overridden to a smaller value to improve performance (a
|
||||
* value of 0 disables field flow), or a larger value to get more results.
|
||||
*/
|
||||
default int fieldFlowBranchLimit() { result = 2 }
|
||||
|
||||
/**
|
||||
* Gets a data flow configuration feature to add restrictions to the set of
|
||||
* valid flow paths.
|
||||
*
|
||||
* - `FeatureHasSourceCallContext`:
|
||||
* Assume that sources have some existing call context to disallow
|
||||
* conflicting return-flow directly following the source.
|
||||
* - `FeatureHasSinkCallContext`:
|
||||
* Assume that sinks have some existing call context to disallow
|
||||
* conflicting argument-to-parameter flow directly preceding the sink.
|
||||
* - `FeatureEqualSourceSinkCallContext`:
|
||||
* Implies both of the above and additionally ensures that the entire flow
|
||||
* path preserves the call context.
|
||||
*
|
||||
* These features are generally not relevant for typical end-to-end data flow
|
||||
* queries, but should only be used for constructing paths that need to
|
||||
* somehow be pluggable in another path context.
|
||||
*/
|
||||
default FlowFeature getAFeature() { none() }
|
||||
|
||||
/** Holds if sources should be grouped in the result of `flowPath`. */
|
||||
default predicate sourceGrouping(Node source, string sourceGroup) { none() }
|
||||
|
||||
/** Holds if sinks should be grouped in the result of `flowPath`. */
|
||||
default predicate sinkGrouping(Node sink, string sinkGroup) { none() }
|
||||
|
||||
/**
|
||||
* Holds if hidden nodes should be included in the data flow graph.
|
||||
*
|
||||
* This feature should only be used for debugging or when the data flow graph
|
||||
* is not visualized (as it is in a `path-problem` query).
|
||||
*/
|
||||
default predicate includeHiddenNodes() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exploration limit for `partialFlow` and `partialFlowRev`
|
||||
* measured in approximate number of interprocedural steps.
|
||||
*/
|
||||
signature int explorationLimitSig();
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
signature module GlobalFlowSig {
|
||||
/**
|
||||
* A `Node` augmented with a call context (except for sinks) and an access path.
|
||||
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
|
||||
*/
|
||||
class PathNode;
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `source` to `sink`.
|
||||
*
|
||||
* The corresponding paths are generated from the end-points and the graph
|
||||
* included in the module `PathGraph`.
|
||||
*/
|
||||
predicate flowPath(PathNode source, PathNode sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `source` to `sink`.
|
||||
*/
|
||||
predicate flow(Node source, Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from some source to `sink`.
|
||||
*/
|
||||
predicate flowTo(Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from some source to `sink`.
|
||||
*/
|
||||
predicate flowToExpr(DataFlowExpr sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a global data flow computation.
|
||||
*/
|
||||
module Global<ConfigSig Config> implements GlobalFlowSig {
|
||||
private module C implements FullStateConfigSig {
|
||||
import DefaultState<Config>
|
||||
import Config
|
||||
}
|
||||
|
||||
import Impl<C>
|
||||
}
|
||||
|
||||
/** DEPRECATED: Use `Global` instead. */
|
||||
deprecated module Make<ConfigSig Config> implements GlobalFlowSig {
|
||||
import Global<Config>
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a global data flow computation using flow state.
|
||||
*/
|
||||
module GlobalWithState<StateConfigSig Config> implements GlobalFlowSig {
|
||||
private module C implements FullStateConfigSig {
|
||||
import Config
|
||||
}
|
||||
|
||||
import Impl<C>
|
||||
}
|
||||
|
||||
/** DEPRECATED: Use `GlobalWithState` instead. */
|
||||
deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig {
|
||||
import GlobalWithState<Config>
|
||||
}
|
||||
|
||||
signature class PathNodeSig {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString();
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
);
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode();
|
||||
}
|
||||
|
||||
signature module PathGraphSig<PathNodeSig PathNode> {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
predicate edges(PathNode a, PathNode b);
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
predicate nodes(PathNode n, string key, string val);
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from two `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig<PathNode1> Graph1,
|
||||
PathGraphSig<PathNode2> Graph2>
|
||||
{
|
||||
private newtype TPathNode =
|
||||
TPathNode1(PathNode1 p) or
|
||||
TPathNode2(PathNode2 p)
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */
|
||||
class PathNode extends TPathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { this = TPathNode1(result) }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { this = TPathNode2(result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
result = this.asPathNode1().toString() or
|
||||
result = this.asPathNode2().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or
|
||||
this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() {
|
||||
result = this.asPathNode1().getNode() or
|
||||
result = this.asPathNode2().getNode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph implements PathGraphSig<PathNode> {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) {
|
||||
Graph1::edges(a.asPathNode1(), b.asPathNode1()) or
|
||||
Graph2::edges(a.asPathNode2(), b.asPathNode2())
|
||||
}
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
Graph1::nodes(n.asPathNode1(), key, val) or
|
||||
Graph2::nodes(n.asPathNode2(), key, val)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
|
||||
Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or
|
||||
Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
@@ -5,8 +5,8 @@ private import DataFlowUtil
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
*/
|
||||
Function viableCallable(Call call) {
|
||||
result = call.getTarget()
|
||||
Function viableCallable(DataFlowCall call) {
|
||||
result = call.(Call).getTarget()
|
||||
or
|
||||
// If the target of the call does not have a body in the snapshot, it might
|
||||
// be because the target is just a header declaration, and the real target
|
||||
@@ -58,13 +58,13 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(Call call, Function f) { none() }
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, Function f) { none() }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(Call call, Call ctx) { none() }
|
||||
Function viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Provides C++-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
private import codeql.dataflow.DataFlow
|
||||
|
||||
module Private {
|
||||
import DataFlowPrivate
|
||||
import DataFlowDispatch
|
||||
@@ -9,3 +12,10 @@ module Private {
|
||||
module Public {
|
||||
import DataFlowUtil
|
||||
}
|
||||
|
||||
module CppOldDataFlow implements InputSig {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
}
|
||||
|
||||
@@ -153,10 +153,11 @@ predicate jumpStep(Node n1, Node n2) { none() }
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*/
|
||||
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
predicate storeStep(Node node1, ContentSet f, Node node2) {
|
||||
exists(ClassAggregateLiteral aggr, Field field |
|
||||
// The following line requires `node2` to be both an `ExprNode` and a
|
||||
// The following lines requires `node2` to be both an `ExprNode` and a
|
||||
// `PostUpdateNode`, which means it must be an `ObjectInitializerNode`.
|
||||
node2 instanceof PostUpdateNode and
|
||||
node2.asExpr() = aggr and
|
||||
f.(FieldContent).getField() = field and
|
||||
aggr.getAFieldExpr(field) = node1.asExpr()
|
||||
@@ -167,12 +168,13 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
node1.asExpr() = a and
|
||||
a.getLValue() = fa
|
||||
) and
|
||||
node2.getPreUpdateNode().asExpr() = fa.getQualifier() and
|
||||
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = fa.getQualifier() and
|
||||
f.(FieldContent).getField() = fa.getTarget()
|
||||
)
|
||||
or
|
||||
exists(ConstructorFieldInit cfi |
|
||||
node2.getPreUpdateNode().(PreConstructorInitThis).getConstructorFieldInit() = cfi and
|
||||
node2.(PostUpdateNode).getPreUpdateNode().(PreConstructorInitThis).getConstructorFieldInit() =
|
||||
cfi and
|
||||
f.(FieldContent).getField() = cfi.getTarget() and
|
||||
node1.asExpr() = cfi.getExpr()
|
||||
)
|
||||
@@ -183,7 +185,7 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, Content f, Node node2) {
|
||||
predicate readStep(Node node1, ContentSet f, Node node2) {
|
||||
exists(FieldAccess fr |
|
||||
node1.asExpr() = fr.getQualifier() and
|
||||
fr.getTarget() = f.(FieldContent).getField() and
|
||||
@@ -195,7 +197,7 @@ predicate readStep(Node node1, Content f, Node node2) {
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
none() // stub implementation
|
||||
}
|
||||
|
||||
@@ -235,12 +237,6 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
predicate neverSkipInPathGraph(Node n) { none() }
|
||||
|
||||
class DataFlowCallable = Function;
|
||||
|
||||
class DataFlowExpr = Expr;
|
||||
@@ -265,8 +261,6 @@ class DataFlowCall extends Expr instanceof Call {
|
||||
|
||||
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
/**
|
||||
* Holds if access paths with `c` at their head always should be tracked at high
|
||||
* precision. This disables adaptive access path precision for such access paths.
|
||||
|
||||
@@ -24,6 +24,7 @@ private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> imp
|
||||
Config::allowImplicitRead(node, c)
|
||||
or
|
||||
(
|
||||
Config::isSink(node) or
|
||||
Config::isSink(node, _) or
|
||||
Config::isAdditionalFlowStep(node, _) or
|
||||
Config::isAdditionalFlowStep(node, _, _, _)
|
||||
|
||||
@@ -26,6 +26,8 @@ import cpp
|
||||
* global (inter-procedural) data flow analyses.
|
||||
*/
|
||||
module DataFlow {
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<CppDataFlow>
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -152,7 +152,19 @@ class Expr extends StmtParent, @expr {
|
||||
else result = this.getValue()
|
||||
}
|
||||
|
||||
/** Holds if this expression has a value that can be determined at compile time. */
|
||||
/**
|
||||
* Holds if this expression has a value that can be determined at compile time.
|
||||
*
|
||||
* An expression has a value that can be determined at compile time when:
|
||||
* - it is a compile-time constant, e.g., a literal value or the result of a constexpr
|
||||
* compile-time constant;
|
||||
* - it is an address of a (member) function, an address of a constexpr variable
|
||||
* initialized to a constant address, or an address of an lvalue, or any of the
|
||||
* previous with a constant value added to or subtracted from the address;
|
||||
* - it is a reference to a (member) function, a reference to a constexpr variable
|
||||
* initialized to a constant address, or a reference to an lvalue;
|
||||
* - it is a non-template parameter of a uninstantiated template.
|
||||
*/
|
||||
cached
|
||||
predicate isConstant() {
|
||||
valuebind(_, underlyingElement(this))
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
|
||||
* to dump.
|
||||
*/
|
||||
|
||||
import implementation.aliased_ssa.PrintIR
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
import cpp
|
||||
|
||||
module DataFlow {
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.dataflow.DataFlow
|
||||
import DataFlowMake<CppDataFlow>
|
||||
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1
|
||||
}
|
||||
|
||||
@@ -1,433 +0,0 @@
|
||||
/**
|
||||
* Provides an implementation of global (interprocedural) data flow. This file
|
||||
* re-exports the local (intraprocedural) data flow analysis from
|
||||
* `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed
|
||||
* through the `Global` and `GlobalWithState` modules.
|
||||
*/
|
||||
|
||||
private import DataFlowImplCommon
|
||||
private import DataFlowImplSpecific::Private
|
||||
import DataFlowImplSpecific::Public
|
||||
import DataFlowImplCommonPublic
|
||||
private import DataFlowImpl
|
||||
|
||||
/** An input configuration for data flow. */
|
||||
signature module ConfigSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
predicate isSource(Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
predicate isSink(Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
*/
|
||||
default predicate isBarrier(Node node) { none() }
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
default predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
default predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
default predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `node` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
default predicate neverSkip(Node node) {
|
||||
isAdditionalFlowStep(node, _) or isAdditionalFlowStep(_, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
* This can be overridden to a smaller value to improve performance (a
|
||||
* value of 0 disables field flow), or a larger value to get more results.
|
||||
*/
|
||||
default int fieldFlowBranchLimit() { result = 2 }
|
||||
|
||||
/**
|
||||
* Gets a data flow configuration feature to add restrictions to the set of
|
||||
* valid flow paths.
|
||||
*
|
||||
* - `FeatureHasSourceCallContext`:
|
||||
* Assume that sources have some existing call context to disallow
|
||||
* conflicting return-flow directly following the source.
|
||||
* - `FeatureHasSinkCallContext`:
|
||||
* Assume that sinks have some existing call context to disallow
|
||||
* conflicting argument-to-parameter flow directly preceding the sink.
|
||||
* - `FeatureEqualSourceSinkCallContext`:
|
||||
* Implies both of the above and additionally ensures that the entire flow
|
||||
* path preserves the call context.
|
||||
*
|
||||
* These features are generally not relevant for typical end-to-end data flow
|
||||
* queries, but should only be used for constructing paths that need to
|
||||
* somehow be pluggable in another path context.
|
||||
*/
|
||||
default FlowFeature getAFeature() { none() }
|
||||
|
||||
/** Holds if sources should be grouped in the result of `flowPath`. */
|
||||
default predicate sourceGrouping(Node source, string sourceGroup) { none() }
|
||||
|
||||
/** Holds if sinks should be grouped in the result of `flowPath`. */
|
||||
default predicate sinkGrouping(Node sink, string sinkGroup) { none() }
|
||||
|
||||
/**
|
||||
* Holds if hidden nodes should be included in the data flow graph.
|
||||
*
|
||||
* This feature should only be used for debugging or when the data flow graph
|
||||
* is not visualized (as it is in a `path-problem` query).
|
||||
*/
|
||||
default predicate includeHiddenNodes() { none() }
|
||||
}
|
||||
|
||||
/** An input configuration for data flow using flow state. */
|
||||
signature module StateConfigSig {
|
||||
bindingset[this]
|
||||
class FlowState;
|
||||
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source with the given initial
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSource(Node source, FlowState state);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink accepting `state`.
|
||||
*/
|
||||
predicate isSink(Node sink, FlowState state);
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited. This completely removes
|
||||
* `node` from the data flow graph.
|
||||
*/
|
||||
default predicate isBarrier(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
default predicate isBarrier(Node node, FlowState state) { none() }
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
default predicate isBarrierIn(Node node) { none() }
|
||||
|
||||
/** Holds if data flow out of `node` is prohibited. */
|
||||
default predicate isBarrierOut(Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
* This step is only applicable in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if an arbitrary number of implicit read steps of content `c` may be
|
||||
* taken at `node`.
|
||||
*/
|
||||
default predicate allowImplicitRead(Node node, ContentSet c) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `node` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
default predicate neverSkip(Node node) {
|
||||
isAdditionalFlowStep(node, _) or
|
||||
isAdditionalFlowStep(_, node) or
|
||||
isAdditionalFlowStep(node, _, _, _) or
|
||||
isAdditionalFlowStep(_, _, node, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the virtual dispatch branching limit when calculating field flow.
|
||||
* This can be overridden to a smaller value to improve performance (a
|
||||
* value of 0 disables field flow), or a larger value to get more results.
|
||||
*/
|
||||
default int fieldFlowBranchLimit() { result = 2 }
|
||||
|
||||
/**
|
||||
* Gets a data flow configuration feature to add restrictions to the set of
|
||||
* valid flow paths.
|
||||
*
|
||||
* - `FeatureHasSourceCallContext`:
|
||||
* Assume that sources have some existing call context to disallow
|
||||
* conflicting return-flow directly following the source.
|
||||
* - `FeatureHasSinkCallContext`:
|
||||
* Assume that sinks have some existing call context to disallow
|
||||
* conflicting argument-to-parameter flow directly preceding the sink.
|
||||
* - `FeatureEqualSourceSinkCallContext`:
|
||||
* Implies both of the above and additionally ensures that the entire flow
|
||||
* path preserves the call context.
|
||||
*
|
||||
* These features are generally not relevant for typical end-to-end data flow
|
||||
* queries, but should only be used for constructing paths that need to
|
||||
* somehow be pluggable in another path context.
|
||||
*/
|
||||
default FlowFeature getAFeature() { none() }
|
||||
|
||||
/** Holds if sources should be grouped in the result of `flowPath`. */
|
||||
default predicate sourceGrouping(Node source, string sourceGroup) { none() }
|
||||
|
||||
/** Holds if sinks should be grouped in the result of `flowPath`. */
|
||||
default predicate sinkGrouping(Node sink, string sinkGroup) { none() }
|
||||
|
||||
/**
|
||||
* Holds if hidden nodes should be included in the data flow graph.
|
||||
*
|
||||
* This feature should only be used for debugging or when the data flow graph
|
||||
* is not visualized (as it is in a `path-problem` query).
|
||||
*/
|
||||
default predicate includeHiddenNodes() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the exploration limit for `partialFlow` and `partialFlowRev`
|
||||
* measured in approximate number of interprocedural steps.
|
||||
*/
|
||||
signature int explorationLimitSig();
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
signature module GlobalFlowSig {
|
||||
/**
|
||||
* A `Node` augmented with a call context (except for sinks) and an access path.
|
||||
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
|
||||
*/
|
||||
class PathNode;
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `source` to `sink`.
|
||||
*
|
||||
* The corresponding paths are generated from the end-points and the graph
|
||||
* included in the module `PathGraph`.
|
||||
*/
|
||||
predicate flowPath(PathNode source, PathNode sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `source` to `sink`.
|
||||
*/
|
||||
predicate flow(Node source, Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from some source to `sink`.
|
||||
*/
|
||||
predicate flowTo(Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data can flow from some source to `sink`.
|
||||
*/
|
||||
predicate flowToExpr(DataFlowExpr sink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a global data flow computation.
|
||||
*/
|
||||
module Global<ConfigSig Config> implements GlobalFlowSig {
|
||||
private module C implements FullStateConfigSig {
|
||||
import DefaultState<Config>
|
||||
import Config
|
||||
}
|
||||
|
||||
import Impl<C>
|
||||
}
|
||||
|
||||
/** DEPRECATED: Use `Global` instead. */
|
||||
deprecated module Make<ConfigSig Config> implements GlobalFlowSig {
|
||||
import Global<Config>
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a global data flow computation using flow state.
|
||||
*/
|
||||
module GlobalWithState<StateConfigSig Config> implements GlobalFlowSig {
|
||||
private module C implements FullStateConfigSig {
|
||||
import Config
|
||||
}
|
||||
|
||||
import Impl<C>
|
||||
}
|
||||
|
||||
/** DEPRECATED: Use `GlobalWithState` instead. */
|
||||
deprecated module MakeWithState<StateConfigSig Config> implements GlobalFlowSig {
|
||||
import GlobalWithState<Config>
|
||||
}
|
||||
|
||||
signature class PathNodeSig {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString();
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
);
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode();
|
||||
}
|
||||
|
||||
signature module PathGraphSig<PathNodeSig PathNode> {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
predicate edges(PathNode a, PathNode b);
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
predicate nodes(PathNode n, string key, string val);
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from two `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig<PathNode1> Graph1,
|
||||
PathGraphSig<PathNode2> Graph2>
|
||||
{
|
||||
private newtype TPathNode =
|
||||
TPathNode1(PathNode1 p) or
|
||||
TPathNode2(PathNode2 p)
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */
|
||||
class PathNode extends TPathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { this = TPathNode1(result) }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { this = TPathNode2(result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
result = this.asPathNode1().toString() or
|
||||
result = this.asPathNode2().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or
|
||||
this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() {
|
||||
result = this.asPathNode1().getNode() or
|
||||
result = this.asPathNode2().getNode()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph implements PathGraphSig<PathNode> {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) {
|
||||
Graph1::edges(a.asPathNode1(), b.asPathNode1()) or
|
||||
Graph2::edges(a.asPathNode2(), b.asPathNode2())
|
||||
}
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
Graph1::nodes(n.asPathNode1(), key, val) or
|
||||
Graph2::nodes(n.asPathNode2(), key, val)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
|
||||
Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or
|
||||
Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
* Gets a function that might be called by `call`.
|
||||
*/
|
||||
cached
|
||||
Function viableCallable(CallInstruction call) {
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
result = call.getStaticCallTarget()
|
||||
or
|
||||
@@ -235,7 +235,7 @@ private predicate functionSignature(Function f, string qualifiedName, int nparam
|
||||
* Holds if the set of viable implementations that can be called by `call`
|
||||
* might be improved by knowing the call context.
|
||||
*/
|
||||
predicate mayBenefitFromCallContext(CallInstruction call, Function f) {
|
||||
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) {
|
||||
mayBenefitFromCallContext(call, f, _)
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ private predicate mayBenefitFromCallContext(
|
||||
* Gets a viable dispatch target of `call` in the context `ctx`. This is
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
|
||||
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableCallable(call) and
|
||||
exists(int i, Function f |
|
||||
mayBenefitFromCallContext(pragma[only_bind_into](call), f, i) and
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
@@ -276,6 +276,8 @@ private module Config implements FullStateConfigSig {
|
||||
getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty
|
||||
}
|
||||
|
||||
predicate isSink(Node sink) { none() }
|
||||
|
||||
predicate isSink(Node sink, FlowState state) {
|
||||
getConfig(state).isSink(sink, getState(state))
|
||||
or
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,9 @@
|
||||
/**
|
||||
* Provides IR-specific definitions for use in the data flow library.
|
||||
*/
|
||||
|
||||
private import codeql.dataflow.DataFlow
|
||||
|
||||
module Private {
|
||||
import DataFlowPrivate
|
||||
import DataFlowDispatch
|
||||
@@ -9,3 +12,10 @@ module Private {
|
||||
module Public {
|
||||
import DataFlowUtil
|
||||
}
|
||||
|
||||
module CppDataFlow implements InputSig {
|
||||
import Private
|
||||
import Public
|
||||
|
||||
Node exprNode(DataFlowExpr e) { result = Public::exprNode(e) }
|
||||
}
|
||||
|
||||
@@ -681,9 +681,7 @@ predicate storeStepImpl(Node node1, Content c, PostFieldUpdateNode node2, boolea
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*/
|
||||
predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) {
|
||||
storeStepImpl(node1, c, node2, _)
|
||||
}
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepImpl(node1, c, node2, _) }
|
||||
|
||||
/**
|
||||
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
|
||||
@@ -744,7 +742,7 @@ predicate nodeHasInstruction(Node node, Instruction instr, int indirectionIndex)
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, Content c, Node node2) {
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2 |
|
||||
nodeHasOperand(node2, operand, indirectionIndex2) and
|
||||
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
|
||||
@@ -767,7 +765,7 @@ predicate readStep(Node node1, Content c, Node node2) {
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
predicate clearsContent(Node n, Content c) {
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
n =
|
||||
any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun)
|
||||
.getPreUpdateNode() and
|
||||
@@ -792,7 +790,7 @@ predicate clearsContent(Node n, Content c) {
|
||||
storeStepImpl(_, d, pun, true) and
|
||||
pun.getPreUpdateNode() = n
|
||||
|
|
||||
c.getIndirectionIndex() = d.getIndirectionIndex()
|
||||
c.(Content).getIndirectionIndex() = d.getIndirectionIndex()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -833,12 +831,6 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` should never be skipped over in the `PathGraph` and in path
|
||||
* explanations.
|
||||
*/
|
||||
predicate neverSkipInPathGraph(Node n) { none() }
|
||||
|
||||
/**
|
||||
* A function that may contain code or a variable that may contain itself. When
|
||||
* flow crosses from one _enclosing callable_ to another, the interprocedural
|
||||
@@ -853,7 +845,7 @@ class DataFlowType = Type;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends CallInstruction {
|
||||
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
|
||||
}
|
||||
|
||||
module IsUnreachableInCall {
|
||||
@@ -924,8 +916,6 @@ module IsUnreachableInCall {
|
||||
|
||||
import IsUnreachableInCall
|
||||
|
||||
int accessPathLimit() { result = 5 }
|
||||
|
||||
/**
|
||||
* Holds if access paths with `c` at their head always should be tracked at high
|
||||
* precision. This disables adaptive access path precision for such access paths.
|
||||
@@ -1088,7 +1078,7 @@ private IRVariable getIRVariableForParameterNode(ParameterNode p) {
|
||||
|
||||
/** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */
|
||||
pragma[nomagic]
|
||||
private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceIRVariable v) {
|
||||
private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceVariable v) {
|
||||
v.getIRVariable() = getIRVariableForParameterNode(p) and
|
||||
exists(Position pos | p.isParameterOf(_, pos) |
|
||||
pos instanceof DirectPosition and
|
||||
|
||||
@@ -781,26 +781,12 @@ class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PartialDef
|
||||
override Expr getDefinedExpr() { result = operand.getDef().getUnconvertedResultExpression() }
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate indirectReturnOutNodeOperand0(CallInstruction call, Operand operand, int indirectionIndex) {
|
||||
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
|
||||
operandForFullyConvertedCall(operand, call)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate indirectReturnOutNodeInstruction0(
|
||||
CallInstruction call, Instruction instr, int indirectionIndex
|
||||
) {
|
||||
Ssa::hasRawIndirectInstruction(call, indirectionIndex) and
|
||||
instructionForFullyConvertedCall(instr, call)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and
|
||||
* `operand` represents a use of the fully converted value of `call`.
|
||||
*/
|
||||
private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) {
|
||||
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and
|
||||
operandForFullyConvertedCall(operand, call) and
|
||||
hasOperandAndIndex(node, operand, indirectionIndex)
|
||||
}
|
||||
|
||||
@@ -813,7 +799,7 @@ private predicate hasOperand(Node node, CallInstruction call, int indirectionInd
|
||||
private predicate hasInstruction(
|
||||
Node node, CallInstruction call, int indirectionIndex, Instruction instr
|
||||
) {
|
||||
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and
|
||||
instructionForFullyConvertedCall(instr, call) and
|
||||
hasInstructionAndIndex(node, instr, indirectionIndex)
|
||||
}
|
||||
|
||||
@@ -1534,6 +1520,25 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `operand.getDef() = instr`, but there exists a `StoreInstruction` that
|
||||
* writes to an address that is equivalent to the value computed by `instr` in
|
||||
* between `instr` and `operand`, and therefore there should not be flow from `*instr`
|
||||
* to `*operand`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate isStoredToBetween(Instruction instr, Operand operand) {
|
||||
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) and
|
||||
exists(StoreInstruction store, IRBlock block, int storeIndex, int instrIndex, int operandIndex |
|
||||
store.getDestinationAddress() = instr and
|
||||
block.getInstruction(storeIndex) = store and
|
||||
block.getInstruction(instrIndex) = instr and
|
||||
block.getInstruction(operandIndex) = operand.getUse() and
|
||||
instrIndex < storeIndex and
|
||||
storeIndex < operandIndex
|
||||
)
|
||||
}
|
||||
|
||||
private predicate indirectionInstructionFlow(
|
||||
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
|
||||
) {
|
||||
@@ -1543,7 +1548,8 @@ private module Cached {
|
||||
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand))
|
||||
|
|
||||
hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex))
|
||||
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex)) and
|
||||
not isStoredToBetween(instr, operand)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,32 +10,35 @@ private import ssa0.SsaInternals as SsaInternals0
|
||||
import SsaInternalsCommon
|
||||
|
||||
private module SourceVariables {
|
||||
int getMaxIndirectionForIRVariable(IRVariable var) {
|
||||
exists(Type type, boolean isGLValue |
|
||||
var.getLanguageType().hasType(type, isGLValue) and
|
||||
if isGLValue = true
|
||||
then result = 1 + getMaxIndirectionsForType(type)
|
||||
else result = getMaxIndirectionsForType(type)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private newtype TSourceVariable =
|
||||
TSourceIRVariable(BaseIRVariable baseVar, int ind) {
|
||||
ind = [0 .. getMaxIndirectionForIRVariable(baseVar.getIRVariable())]
|
||||
} or
|
||||
TCallVariable(AllocationInstruction call, int ind) {
|
||||
ind = [0 .. countIndirectionsForCppType(getResultLanguageType(call))]
|
||||
TMkSourceVariable(SsaInternals0::SourceVariable base, int ind) {
|
||||
ind = [0 .. countIndirectionsForCppType(base.getLanguageType()) + 1]
|
||||
}
|
||||
|
||||
abstract class SourceVariable extends TSourceVariable {
|
||||
class SourceVariable extends TSourceVariable {
|
||||
SsaInternals0::SourceVariable base;
|
||||
int ind;
|
||||
|
||||
bindingset[ind]
|
||||
SourceVariable() { any() }
|
||||
SourceVariable() { this = TMkSourceVariable(base, ind) }
|
||||
|
||||
/** Gets the IR variable associated with this `SourceVariable`, if any. */
|
||||
IRVariable getIRVariable() { result = base.(BaseIRVariable).getIRVariable() }
|
||||
|
||||
/**
|
||||
* Gets the base source variable (i.e., the variable without any
|
||||
* indirections) of this source variable.
|
||||
*/
|
||||
SsaInternals0::SourceVariable getBaseVariable() { result = base }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
string toString() {
|
||||
ind = 0 and
|
||||
result = this.getBaseVariable().toString()
|
||||
or
|
||||
ind > 0 and
|
||||
result = this.getBaseVariable().toString() + " indirection"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of loads performed on the base source variable
|
||||
@@ -43,65 +46,19 @@ private module SourceVariables {
|
||||
*/
|
||||
int getIndirection() { result = ind }
|
||||
|
||||
/**
|
||||
* Gets the base source variable (i.e., the variable without any
|
||||
* indirections) of this source variable.
|
||||
*/
|
||||
abstract BaseSourceVariable getBaseVariable();
|
||||
|
||||
/** Holds if this variable is a glvalue. */
|
||||
predicate isGLValue() { none() }
|
||||
predicate isGLValue() { ind = 0 }
|
||||
|
||||
/**
|
||||
* Gets the type of this source variable. If `isGLValue()` holds, then
|
||||
* the type of this source variable should be thought of as "pointer
|
||||
* to `getType()`".
|
||||
*/
|
||||
abstract DataFlowType getType();
|
||||
}
|
||||
|
||||
class SourceIRVariable extends SourceVariable, TSourceIRVariable {
|
||||
BaseIRVariable var;
|
||||
|
||||
SourceIRVariable() { this = TSourceIRVariable(var, ind) }
|
||||
|
||||
IRVariable getIRVariable() { result = var.getIRVariable() }
|
||||
|
||||
override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() }
|
||||
|
||||
override string toString() {
|
||||
ind = 0 and
|
||||
result = this.getIRVariable().toString()
|
||||
or
|
||||
ind > 0 and
|
||||
result = this.getIRVariable().toString() + " indirection"
|
||||
DataFlowType getType() {
|
||||
if this.isGLValue()
|
||||
then result = base.getType()
|
||||
else result = getTypeImpl(base.getType(), ind - 1)
|
||||
}
|
||||
|
||||
override predicate isGLValue() { ind = 0 }
|
||||
|
||||
override DataFlowType getType() {
|
||||
if ind = 0 then result = var.getType() else result = getTypeImpl(var.getType(), ind - 1)
|
||||
}
|
||||
}
|
||||
|
||||
class CallVariable extends SourceVariable, TCallVariable {
|
||||
AllocationInstruction call;
|
||||
|
||||
CallVariable() { this = TCallVariable(call, ind) }
|
||||
|
||||
AllocationInstruction getCall() { result = call }
|
||||
|
||||
override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call }
|
||||
|
||||
override string toString() {
|
||||
ind = 0 and
|
||||
result = "Call"
|
||||
or
|
||||
ind > 0 and
|
||||
result = "Call indirection"
|
||||
}
|
||||
|
||||
override DataFlowType getType() { result = getTypeImpl(call.getResultType(), ind) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +94,9 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
|
||||
|
||||
cached
|
||||
private newtype TDefOrUseImpl =
|
||||
TDefImpl(Operand address, int indirectionIndex) {
|
||||
exists(Instruction base | isDef(_, _, address, base, _, indirectionIndex) |
|
||||
TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
|
||||
isDef(_, _, address, base, _, indirectionIndex) and
|
||||
(
|
||||
// We only include the definition if the SSA pruning stage
|
||||
// concluded that the definition is live after the write.
|
||||
any(SsaInternals0::Def def).getAddressOperand() = address
|
||||
@@ -148,8 +106,8 @@ private newtype TDefOrUseImpl =
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
|
||||
)
|
||||
} or
|
||||
TUseImpl(Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, _, _, indirectionIndex) and
|
||||
TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, base, _, indirectionIndex) and
|
||||
not isDef(_, _, operand, _, _, _)
|
||||
} or
|
||||
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
@@ -236,7 +194,7 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
|
||||
|
||||
/**
|
||||
* Gets the instruction that computes the base of this definition or use.
|
||||
* This is always a `VariableAddressInstruction` or an `AllocationInstruction`.
|
||||
* This is always a `VariableAddressInstruction` or an `CallInstruction`.
|
||||
*/
|
||||
abstract BaseSourceVariableInstruction getBase();
|
||||
|
||||
@@ -308,15 +266,17 @@ abstract class DefImpl extends DefOrUseImpl {
|
||||
}
|
||||
|
||||
private class DirectDef extends DefImpl, TDefImpl {
|
||||
DirectDef() { this = TDefImpl(address, ind) }
|
||||
BaseSourceVariableInstruction base;
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
|
||||
DirectDef() { this = TDefImpl(base, address, ind) }
|
||||
|
||||
override int getIndirection() { isDef(_, _, address, _, result, ind) }
|
||||
override BaseSourceVariableInstruction getBase() { result = base }
|
||||
|
||||
override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
|
||||
override int getIndirection() { isDef(_, _, address, base, result, ind) }
|
||||
|
||||
override predicate isCertain() { isDef(true, _, address, _, _, ind) }
|
||||
override Node0Impl getValue() { isDef(_, result, address, base, _, _) }
|
||||
|
||||
override predicate isCertain() { isDef(true, _, address, base, _, ind) }
|
||||
}
|
||||
|
||||
private class IteratorDef extends DefImpl, TIteratorDef {
|
||||
@@ -359,6 +319,7 @@ abstract class UseImpl extends DefOrUseImpl {
|
||||
|
||||
abstract private class OperandBasedUse extends UseImpl {
|
||||
Operand operand;
|
||||
BaseSourceVariableInstruction base;
|
||||
|
||||
bindingset[ind]
|
||||
OperandBasedUse() { any() }
|
||||
@@ -366,50 +327,44 @@ abstract private class OperandBasedUse extends UseImpl {
|
||||
final override predicate hasIndexInBlock(IRBlock block, int index) {
|
||||
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
|
||||
// predicate's implementation.
|
||||
exists(BaseSourceVariableInstruction base | base = this.getBase() |
|
||||
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
|
||||
then
|
||||
exists(Operand op, int indirectionIndex, int indirection |
|
||||
indirectionIndex = this.getIndirectionIndex() and
|
||||
indirection = this.getIndirection() and
|
||||
op =
|
||||
min(Operand cand, int i |
|
||||
isUse(_, cand, base, indirection, indirectionIndex) and
|
||||
block.getInstruction(i) = cand.getUse()
|
||||
|
|
||||
cand order by i
|
||||
) and
|
||||
block.getInstruction(index) = op.getUse()
|
||||
)
|
||||
else operand.getUse() = block.getInstruction(index)
|
||||
)
|
||||
if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
|
||||
then
|
||||
exists(Operand op, int indirectionIndex, int indirection |
|
||||
indirectionIndex = this.getIndirectionIndex() and
|
||||
indirection = this.getIndirection() and
|
||||
op =
|
||||
min(Operand cand, int i |
|
||||
isUse(_, cand, base, indirection, indirectionIndex) and
|
||||
block.getInstruction(i) = cand.getUse()
|
||||
|
|
||||
cand order by i
|
||||
) and
|
||||
block.getInstruction(index) = op.getUse()
|
||||
)
|
||||
else operand.getUse() = block.getInstruction(index)
|
||||
}
|
||||
|
||||
final override BaseSourceVariableInstruction getBase() { result = base }
|
||||
|
||||
final Operand getOperand() { result = operand }
|
||||
|
||||
final override Cpp::Location getLocation() { result = operand.getLocation() }
|
||||
}
|
||||
|
||||
private class DirectUse extends OperandBasedUse, TUseImpl {
|
||||
DirectUse() { this = TUseImpl(operand, ind) }
|
||||
DirectUse() { this = TUseImpl(base, operand, ind) }
|
||||
|
||||
override int getIndirection() { isUse(_, operand, _, result, ind) }
|
||||
override int getIndirection() { isUse(_, operand, base, result, ind) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) }
|
||||
|
||||
override predicate isCertain() { isUse(true, operand, _, _, ind) }
|
||||
override predicate isCertain() { isUse(true, operand, base, _, ind) }
|
||||
|
||||
override Node getNode() { nodeHasOperand(result, operand, ind) }
|
||||
}
|
||||
|
||||
private class IteratorUse extends OperandBasedUse, TIteratorUse {
|
||||
BaseSourceVariableInstruction container;
|
||||
IteratorUse() { this = TIteratorUse(operand, base, ind) }
|
||||
|
||||
IteratorUse() { this = TIteratorUse(operand, container, ind) }
|
||||
|
||||
override int getIndirection() { isIteratorUse(container, operand, result, ind) }
|
||||
|
||||
override BaseSourceVariableInstruction getBase() { result = container }
|
||||
override int getIndirection() { isIteratorUse(base, operand, result, ind) }
|
||||
|
||||
override predicate isCertain() { none() }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import DataFlowUtil
|
||||
private import semmle.code.cpp.models.interfaces.PointerWrapper
|
||||
private import DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
/**
|
||||
* Holds if `operand` is an operand that is not used by the dataflow library.
|
||||
@@ -146,14 +147,6 @@ int countIndirectionsForCppType(LanguageType langType) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `CallInstruction` that calls an allocation function such
|
||||
* as `malloc` or `operator new`.
|
||||
*/
|
||||
class AllocationInstruction extends CallInstruction {
|
||||
AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction }
|
||||
}
|
||||
|
||||
private predicate isIndirectionType(Type t) { t instanceof Indirection }
|
||||
|
||||
private predicate hasUnspecifiedBaseType(Indirection t, Type base) {
|
||||
@@ -368,17 +361,22 @@ newtype TBaseSourceVariable =
|
||||
// Each IR variable gets its own source variable
|
||||
TBaseIRVariable(IRVariable var) or
|
||||
// Each allocation gets its own source variable
|
||||
TBaseCallVariable(AllocationInstruction call)
|
||||
TBaseCallVariable(CallInstruction call) { not call.getResultIRType() instanceof IRVoidType }
|
||||
|
||||
abstract class BaseSourceVariable extends TBaseSourceVariable {
|
||||
abstract private class AbstractBaseSourceVariable extends TBaseSourceVariable {
|
||||
/** Gets a textual representation of this element. */
|
||||
abstract string toString();
|
||||
|
||||
/** Gets the type of this base source variable. */
|
||||
abstract DataFlowType getType();
|
||||
final DataFlowType getType() { this.getLanguageType().hasUnspecifiedType(result, _) }
|
||||
|
||||
/** Gets the `CppType` of this base source variable. */
|
||||
abstract CppType getLanguageType();
|
||||
}
|
||||
|
||||
class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable {
|
||||
final class BaseSourceVariable = AbstractBaseSourceVariable;
|
||||
|
||||
class BaseIRVariable extends AbstractBaseSourceVariable, TBaseIRVariable {
|
||||
IRVariable var;
|
||||
|
||||
IRVariable getIRVariable() { result = var }
|
||||
@@ -387,19 +385,19 @@ class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable {
|
||||
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
override DataFlowType getType() { result = var.getType() }
|
||||
override CppType getLanguageType() { result = var.getLanguageType() }
|
||||
}
|
||||
|
||||
class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable {
|
||||
AllocationInstruction call;
|
||||
class BaseCallVariable extends AbstractBaseSourceVariable, TBaseCallVariable {
|
||||
CallInstruction call;
|
||||
|
||||
BaseCallVariable() { this = TBaseCallVariable(call) }
|
||||
|
||||
AllocationInstruction getCallInstruction() { result = call }
|
||||
CallInstruction getCallInstruction() { result = call }
|
||||
|
||||
override string toString() { result = call.toString() }
|
||||
|
||||
override DataFlowType getType() { result = call.getResultType() }
|
||||
override CppType getLanguageType() { result = getResultLanguageType(call) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -499,8 +497,7 @@ private class BaseIRVariableInstruction extends BaseSourceVariableInstruction,
|
||||
override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() }
|
||||
}
|
||||
|
||||
private class BaseAllocationInstruction extends BaseSourceVariableInstruction, AllocationInstruction
|
||||
{
|
||||
private class BaseCallInstruction extends BaseSourceVariableInstruction, CallInstruction {
|
||||
override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this }
|
||||
}
|
||||
|
||||
@@ -868,7 +865,7 @@ private module Cached {
|
||||
* to a specific address.
|
||||
*/
|
||||
private predicate isCertainAddress(Operand operand) {
|
||||
operand.getDef() instanceof VariableAddressInstruction
|
||||
valueNumberOfOperand(operand).getAnInstruction() instanceof VariableAddressInstruction
|
||||
or
|
||||
operand.getType() instanceof Cpp::ReferenceType
|
||||
}
|
||||
|
||||
@@ -15,15 +15,12 @@ private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon
|
||||
|
||||
private module SourceVariables {
|
||||
class SourceVariable instanceof BaseSourceVariable {
|
||||
string toString() { result = BaseSourceVariable.super.toString() }
|
||||
|
||||
class SourceVariable extends BaseSourceVariable {
|
||||
/**
|
||||
* Gets the base source variable of this `SourceVariable`.
|
||||
*/
|
||||
BaseSourceVariable getBaseVariable() { result = this }
|
||||
}
|
||||
|
||||
class SourceIRVariable = BaseIRVariable;
|
||||
|
||||
class CallVariable = BaseCallVariable;
|
||||
}
|
||||
|
||||
import SourceVariables
|
||||
|
||||
@@ -24,6 +24,7 @@ private module AddTaintDefaults<DataFlowInternal::FullStateConfigSig Config> imp
|
||||
Config::allowImplicitRead(node, c)
|
||||
or
|
||||
(
|
||||
Config::isSink(node) or
|
||||
Config::isSink(node, _) or
|
||||
Config::isAdditionalFlowStep(node, _) or
|
||||
Config::isAdditionalFlowStep(node, _, _, _)
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
|
||||
* to dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
@@ -16,7 +16,7 @@ import Imports::IRConfiguration
|
||||
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
|
||||
/**
|
||||
* The query can extend this class to control which functions are printed.
|
||||
* The query can extend this class to control which declarations are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
@@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
|
||||
/**
|
||||
* Holds if the IR for `func` should be printed. By default, holds for all
|
||||
* functions.
|
||||
* functions, global and namespace variables, and static local variables.
|
||||
*/
|
||||
predicate shouldPrintFunction(Language::Declaration decl) { any() }
|
||||
predicate shouldPrintDeclaration(Language::Declaration decl) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
*/
|
||||
private class FilteredIRConfiguration extends IRConfiguration {
|
||||
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
|
||||
shouldPrintFunction(func)
|
||||
shouldPrintDeclaration(func)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
private predicate shouldPrintDeclaration(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
@@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) {
|
||||
}
|
||||
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
|
||||
* to dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
@@ -16,7 +16,7 @@ import Imports::IRConfiguration
|
||||
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
|
||||
/**
|
||||
* The query can extend this class to control which functions are printed.
|
||||
* The query can extend this class to control which declarations are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
@@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
|
||||
/**
|
||||
* Holds if the IR for `func` should be printed. By default, holds for all
|
||||
* functions.
|
||||
* functions, global and namespace variables, and static local variables.
|
||||
*/
|
||||
predicate shouldPrintFunction(Language::Declaration decl) { any() }
|
||||
predicate shouldPrintDeclaration(Language::Declaration decl) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
*/
|
||||
private class FilteredIRConfiguration extends IRConfiguration {
|
||||
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
|
||||
shouldPrintFunction(func)
|
||||
shouldPrintDeclaration(func)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
private predicate shouldPrintDeclaration(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
@@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) {
|
||||
}
|
||||
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* This file contains the actual implementation of `PrintIR.ql`. For test cases and very small
|
||||
* databases, `PrintIR.ql` can be run directly to dump the IR for the entire database. For most
|
||||
* uses, however, it is better to write a query that imports `PrintIR.qll`, extends
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintFunction()` to select a subset of functions to
|
||||
* dump.
|
||||
* `PrintIRConfiguration`, and overrides `shouldPrintDeclaration()` to select a subset of declarations
|
||||
* to dump.
|
||||
*/
|
||||
|
||||
private import internal.IRInternal
|
||||
@@ -16,7 +16,7 @@ import Imports::IRConfiguration
|
||||
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
|
||||
|
||||
/**
|
||||
* The query can extend this class to control which functions are printed.
|
||||
* The query can extend this class to control which declarations are printed.
|
||||
*/
|
||||
class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
/** Gets a textual representation of this configuration. */
|
||||
@@ -24,9 +24,9 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
|
||||
/**
|
||||
* Holds if the IR for `func` should be printed. By default, holds for all
|
||||
* functions.
|
||||
* functions, global and namespace variables, and static local variables.
|
||||
*/
|
||||
predicate shouldPrintFunction(Language::Declaration decl) { any() }
|
||||
predicate shouldPrintDeclaration(Language::Declaration decl) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,12 +34,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
|
||||
*/
|
||||
private class FilteredIRConfiguration extends IRConfiguration {
|
||||
override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) {
|
||||
shouldPrintFunction(func)
|
||||
shouldPrintDeclaration(func)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
private predicate shouldPrintDeclaration(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintDeclaration(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
@@ -90,10 +90,10 @@ private string getOperandPropertyString(Operand operand) {
|
||||
}
|
||||
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintDeclaration(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintDeclaration(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
shouldPrintInstruction(instr) and shouldPrintDeclaration(instr.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -574,16 +574,6 @@ module RangeStage<
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `e >= 1` as determined by sign analysis. */
|
||||
private predicate strictlyPositiveIntegralExpr(SemExpr e) {
|
||||
semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType
|
||||
}
|
||||
|
||||
/** Holds if `e <= -1` as determined by sign analysis. */
|
||||
private predicate strictlyNegativeIntegralExpr(SemExpr e) {
|
||||
semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e1 + delta` is a valid bound for `e2`.
|
||||
* - `upper = true` : `e2 <= e1 + delta`
|
||||
@@ -597,27 +587,6 @@ module RangeStage<
|
||||
delta = D::fromInt(0) and
|
||||
(upper = true or upper = false)
|
||||
or
|
||||
exists(SemExpr x, SemSubExpr sub |
|
||||
e2 = sub and
|
||||
sub.getLeftOperand() = e1 and
|
||||
sub.getRightOperand() = x
|
||||
|
|
||||
// `x instanceof ConstantIntegerExpr` is covered by valueFlowStep
|
||||
not x instanceof SemConstantIntegerExpr and
|
||||
if strictlyPositiveIntegralExpr(x)
|
||||
then upper = true and delta = D::fromInt(-1)
|
||||
else
|
||||
if semPositive(x)
|
||||
then upper = true and delta = D::fromInt(0)
|
||||
else
|
||||
if strictlyNegativeIntegralExpr(x)
|
||||
then upper = false and delta = D::fromInt(1)
|
||||
else
|
||||
if semNegative(x)
|
||||
then upper = false and delta = D::fromInt(0)
|
||||
else none()
|
||||
)
|
||||
or
|
||||
e2.(SemRemExpr).getRightOperand() = e1 and
|
||||
semPositive(e1) and
|
||||
delta = D::fromInt(-1) and
|
||||
@@ -1137,6 +1106,23 @@ module RangeStage<
|
||||
b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound
|
||||
)
|
||||
or
|
||||
exists(D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight |
|
||||
boundedSubOperandLeft(e, upper, b, dLeft, fbeLeft, origdelta, reason) and
|
||||
boundedSubOperandRight(e, upper, dRight, fbeRight) and
|
||||
// when `upper` is `true` we have:
|
||||
// left <= b + dLeft
|
||||
// right >= 0 + dRight
|
||||
// left - right <= b + dLeft - (0 + dRight)
|
||||
// = b + (dLeft - dRight)
|
||||
// and when `upper` is `false` we have:
|
||||
// left >= b + dLeft
|
||||
// right <= 0 + dRight
|
||||
// left - right >= b + dLeft - (0 + dRight)
|
||||
// = b + (dLeft - dRight)
|
||||
delta = D::fromFloat(D::toFloat(dLeft) - D::toFloat(dRight)) and
|
||||
fromBackEdge = fbeLeft.booleanOr(fbeRight)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2,
|
||||
D::Delta od1, D::Delta od2, SemReason r1, SemReason r2
|
||||
@@ -1201,6 +1187,37 @@ module RangeStage<
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sub = left - right` and `left <= b + delta` if `upper` is `true`
|
||||
* and `left >= b + delta` is `upper` is `false`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate boundedSubOperandLeft(
|
||||
SemSubExpr sub, boolean upper, SemBound b, D::Delta delta, boolean fromBackEdge,
|
||||
D::Delta origdelta, SemReason reason
|
||||
) {
|
||||
// `semValueFlowStep` already handles the case where one of the operands is a constant.
|
||||
not semValueFlowStep(sub, _, _) and
|
||||
bounded(sub.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sub = left - right` and `right <= 0 + delta` if `upper` is `false`
|
||||
* and `right >= 0 + delta` is `upper` is `true`.
|
||||
*
|
||||
* Note that the boolean value of `upper` is flipped compared to many other predicates in
|
||||
* this file. This ensures a clean join at the call-site.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate boundedSubOperandRight(
|
||||
SemSubExpr sub, boolean upper, D::Delta delta, boolean fromBackEdge
|
||||
) {
|
||||
// `semValueFlowStep` already handles the case where one of the operands is a constant.
|
||||
not semValueFlowStep(sub, _, _) and
|
||||
bounded(sub.getRightOperand(), any(SemZeroBound zb), delta, upper.booleanNot(), fromBackEdge, _,
|
||||
_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate boundedRemExpr(
|
||||
SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta,
|
||||
|
||||
@@ -1,6 +1,54 @@
|
||||
/**
|
||||
* This file provides the first phase of the `cpp/invalid-pointer-deref` query that identifies flow
|
||||
* from an allocation to a pointer-arithmetic instruction that constructs a pointer that is out of bounds.
|
||||
*
|
||||
* Consider the following snippet:
|
||||
* ```cpp
|
||||
* 1. char* base = (char*)malloc(size);
|
||||
* 2. char* end = base + size;
|
||||
* 3. for(int *p = base; p <= end; p++) {
|
||||
* 4. use(*p); // BUG: Should have been bounded by `p < end`.
|
||||
* 5. }
|
||||
* ```
|
||||
* this file identifies the flow from `new int[size]` to `base + size`.
|
||||
*
|
||||
* This is done using the product-flow library. The configuration tracks flow from the pair
|
||||
* `(allocation, size of allocation)` to a pair `(a, b)` where there exists a pointer-arithmetic instruction
|
||||
* `pai = a + r` such that `b` is a dataflow node where `b <= r`. Because there will be a dataflow-path from
|
||||
* `allocation` to `a` this means that the `pai` will compute a pointer that is some number of elements beyond
|
||||
* the end position of the allocation. See `pointerAddInstructionHasBounds` for the implementation of this.
|
||||
*
|
||||
* In the above example, the pair `(a, b)` is `(base, size)` with `base` and `size` coming from the expression
|
||||
* `base + size` on line 2, which is also the pointer-arithmetic instruction. In general, the pair does not necessarily
|
||||
* correspond directly to the operands of the pointer-arithmetic instruction.
|
||||
* In the following example, the pair is again `(base, size)`, but with `base` coming from line 3 and `size` from line 2,
|
||||
* and the pointer-arithmetic instruction being `base + n` on line 3:
|
||||
* ```cpp
|
||||
* 1. int* base = new int[size];
|
||||
* 2. if(n <= size) {
|
||||
* 3. int* end = base + n;
|
||||
* 4. for(int* p = base; p <= end; ++p) {
|
||||
* 5. *p = 0; // BUG: Should have been bounded by `p < end`.
|
||||
* 6. }
|
||||
* 7. }
|
||||
* ```
|
||||
*
|
||||
* Handling false positives:
|
||||
*
|
||||
* Consider a snippet such as:
|
||||
* ```cpp
|
||||
* 1. int* base = new int[size];
|
||||
* 2. int n = condition() ? size : 0;
|
||||
* 3. if(n >= size) return;
|
||||
* 4. int* end = base + n;
|
||||
* 5. for(int* p = base; p <= end; ++p) {
|
||||
* 6. *p = 0; // This is fine since `end < base + size`
|
||||
* 7. }
|
||||
* ```
|
||||
* In order to remove this false positive we define a barrier (see `SizeBarrier::SizeBarrierConfig`) that finds the
|
||||
* possible guards that compares a value to the size of the allocation. In the above example, this is the `(n >= size)`
|
||||
* guard on line 3. `SizeBarrier::getABarrierNode` then defines any node that is guarded by such a guard as a barrier
|
||||
* in the dataflow configuration.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
@@ -42,51 +90,74 @@ predicate hasSize(HeuristicAllocationExpr alloc, DataFlow::Node n, int state) {
|
||||
* ```
|
||||
* In this case, the sink pair identified by the product flow library (without any additional barriers)
|
||||
* would be `(p, n)` (where `n` is the `n` in `p[n]`), because there exists a pointer-arithmetic
|
||||
* instruction `pai` such that:
|
||||
* 1. The left-hand of `pai` flows from the allocation, and
|
||||
* 2. The right-hand of `pai` is non-strictly upper bounded by `n` (where `n` is the `n` in `p[n]`)
|
||||
* instruction `pai = a + b` such that:
|
||||
* 1. the allocation flows to `a`, and
|
||||
* 2. `b <= n` where `n` is the `n` in `p[n]`
|
||||
* but because there's a strict comparison that compares `n` against the size of the allocation this
|
||||
* snippet is fine.
|
||||
*/
|
||||
module Barrier2 {
|
||||
private class FlowState2 = int;
|
||||
|
||||
private module BarrierConfig2 implements DataFlow::ConfigSig {
|
||||
private module SizeBarrier {
|
||||
private module SizeBarrierConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// The sources is the same as in the sources for the second
|
||||
// projection in the `AllocToInvalidPointerConfig` module.
|
||||
hasSize(_, source, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `small <= large + k` holds if `g` evaluates to `testIsTrue`.
|
||||
*/
|
||||
additional predicate isSink(
|
||||
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, FlowState2 state,
|
||||
boolean testIsTrue
|
||||
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
|
||||
) {
|
||||
// The sink is any "large" side of a relational comparison.
|
||||
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
|
||||
// The sink is any "large" side of a relational comparison. i.e., the `large` expression
|
||||
// in a guard such as `small <= large + k`.
|
||||
g.comparesLt(small.asOperand(), large.asOperand(), k + 1, true, testIsTrue)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
|
||||
}
|
||||
|
||||
private import DataFlow::Global<BarrierConfig2>
|
||||
module SizeBarrierFlow = DataFlow::Global<SizeBarrierConfig>;
|
||||
|
||||
private FlowState2 getAFlowStateForNode(DataFlow::Node node) {
|
||||
private int getASizeAddend(DataFlow::Node node) {
|
||||
exists(DataFlow::Node source |
|
||||
flow(source, node) and
|
||||
SizeBarrierFlow::flow(source, node) and
|
||||
hasSize(_, source, result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `small <= large + k` holds if `g` evaluates to `edge`.
|
||||
*/
|
||||
private predicate operandGuardChecks(
|
||||
IRGuardCondition g, Operand left, Operand right, FlowState2 state, boolean edge
|
||||
IRGuardCondition g, Operand small, DataFlow::Node large, int k, boolean edge
|
||||
) {
|
||||
exists(DataFlow::Node nLeft, DataFlow::Node nRight, FlowState2 state0 |
|
||||
nRight.asOperand() = right and
|
||||
nLeft.asOperand() = left and
|
||||
BarrierConfig2::isSink(nLeft, nRight, g, state0, edge) and
|
||||
state = getAFlowStateForNode(nRight) and
|
||||
state0 <= state
|
||||
SizeBarrierFlow::flowTo(large) and
|
||||
SizeBarrierConfig::isSink(DataFlow::operandNode(small), large, g, k, edge)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction `instr` that is guarded by a check such as `instr <= small + delta` where
|
||||
* `small <= _ + k` and `small` is the "small side" of of a relational comparison that checks
|
||||
* whether `small <= size` where `size` is the size of an allocation.
|
||||
*/
|
||||
Instruction getABarrierInstruction0(int delta, int k) {
|
||||
exists(
|
||||
IRGuardCondition g, ValueNumber value, Operand small, boolean edge, DataFlow::Node large
|
||||
|
|
||||
// We know:
|
||||
// 1. result <= value + delta (by `bounded`)
|
||||
// 2. value <= large + k (by `operandGuardChecks`).
|
||||
// So:
|
||||
// result <= value + delta (by 1.)
|
||||
// <= large + k + delta (by 2.)
|
||||
small = value.getAUse() and
|
||||
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](small), large,
|
||||
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
|
||||
bounded(result, value.getAnInstruction(), delta) and
|
||||
g.controls(result.getBlock(), edge) and
|
||||
k < getASizeAddend(large)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -94,13 +165,14 @@ module Barrier2 {
|
||||
* Gets an instruction that is guarded by a guard condition which ensures that
|
||||
* the value of the instruction is upper-bounded by size of some allocation.
|
||||
*/
|
||||
Instruction getABarrierInstruction(FlowState2 state) {
|
||||
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
|
||||
use = value.getAUse() and
|
||||
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _,
|
||||
pragma[only_bind_into](state), pragma[only_bind_into](edge)) and
|
||||
result = value.getAnInstruction() and
|
||||
g.controls(result.getBlock(), edge)
|
||||
bindingset[state]
|
||||
pragma[inline_late]
|
||||
Instruction getABarrierInstruction(int state) {
|
||||
exists(int delta, int k |
|
||||
state > k + delta and
|
||||
// result <= "size of allocation" + delta + k
|
||||
// < "size of allocation" + state
|
||||
result = getABarrierInstruction0(delta, k)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,16 +180,16 @@ module Barrier2 {
|
||||
* Gets a `DataFlow::Node` that is guarded by a guard condition which ensures that
|
||||
* the value of the node is upper-bounded by size of some allocation.
|
||||
*/
|
||||
DataFlow::Node getABarrierNode(FlowState2 state) {
|
||||
result.asOperand() = getABarrierInstruction(state).getAUse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the block of a node that is guarded (see `getABarrierInstruction` or
|
||||
* `getABarrierNode` for the definition of what it means to be guarded).
|
||||
*/
|
||||
IRBlock getABarrierBlock(FlowState2 state) {
|
||||
result.getAnInstruction() = getABarrierInstruction(state)
|
||||
DataFlow::Node getABarrierNode(int state) {
|
||||
exists(DataFlow::Node source, int delta, int k |
|
||||
SizeBarrierFlow::flow(source, result) and
|
||||
hasSize(_, source, state) and
|
||||
result.asInstruction() = SizeBarrier::getABarrierInstruction0(delta, k) and
|
||||
state > k + delta
|
||||
// so now we have:
|
||||
// result <= "size of allocation" + delta + k
|
||||
// < "size of allocation" + state
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,24 +223,8 @@ private module InterestingPointerAddInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* A product-flow configuration for flow from an (allocation, size) pair to a
|
||||
* pointer-arithmetic operation that is non-strictly upper-bounded by `allocation + size`.
|
||||
*
|
||||
* The goal of this query is to find patterns such as:
|
||||
* ```cpp
|
||||
* 1. char* begin = (char*)malloc(size);
|
||||
* 2. char* end = begin + size;
|
||||
* 3. for(int *p = begin; p <= end; p++) {
|
||||
* 4. use(*p);
|
||||
* 5. }
|
||||
* ```
|
||||
*
|
||||
* We do this by splitting the task up into two configurations:
|
||||
* 1. `AllocToInvalidPointerConfig` find flow from `malloc(size)` to `begin + size`, and
|
||||
* 2. `InvalidPointerToDerefConfig` finds flow from `begin + size` to an `end` (on line 3).
|
||||
*
|
||||
* Finally, the range-analysis library will find a load from (or store to) an address that
|
||||
* is non-strictly upper-bounded by `end` (which in this case is `*p`).
|
||||
* A product-flow configuration for flow from an `(allocation, size)` pair to a
|
||||
* pointer-arithmetic operation `pai` such that `pai <= allocation + size`.
|
||||
*/
|
||||
private module Config implements ProductFlow::StateConfigSig {
|
||||
class FlowState1 = Unit;
|
||||
@@ -176,7 +232,7 @@ private module Config implements ProductFlow::StateConfigSig {
|
||||
class FlowState2 = int;
|
||||
|
||||
predicate isSourcePair(
|
||||
DataFlow::Node source1, FlowState1 state1, DataFlow::Node source2, FlowState2 state2
|
||||
DataFlow::Node allocSource, FlowState1 unit, DataFlow::Node sizeSource, FlowState2 sizeAddend
|
||||
) {
|
||||
// In the case of an allocation like
|
||||
// ```cpp
|
||||
@@ -184,21 +240,21 @@ private module Config implements ProductFlow::StateConfigSig {
|
||||
// ```
|
||||
// we use `state2` to remember that there was an offset (in this case an offset of `1`) added
|
||||
// to the size of the allocation. This state is then checked in `isSinkPair`.
|
||||
exists(state1) and
|
||||
hasSize(source1.asConvertedExpr(), source2, state2)
|
||||
exists(unit) and
|
||||
hasSize(allocSource.asConvertedExpr(), sizeSource, sizeAddend)
|
||||
}
|
||||
|
||||
predicate isSinkPair(
|
||||
DataFlow::Node sink1, FlowState1 state1, DataFlow::Node sink2, FlowState2 state2
|
||||
DataFlow::Node allocSink, FlowState1 unit, DataFlow::Node sizeSink, FlowState2 sizeAddend
|
||||
) {
|
||||
exists(state1) and
|
||||
exists(unit) and
|
||||
// We check that the delta computed by the range analysis matches the
|
||||
// state value that we set in `isSourcePair`.
|
||||
pointerAddInstructionHasBounds0(_, sink1, sink2, state2)
|
||||
pointerAddInstructionHasBounds0(_, allocSink, sizeSink, sizeAddend)
|
||||
}
|
||||
|
||||
predicate isBarrier2(DataFlow::Node node, FlowState2 state) {
|
||||
node = Barrier2::getABarrierNode(state)
|
||||
node = SizeBarrier::getABarrierNode(state)
|
||||
}
|
||||
|
||||
predicate isBarrierIn1(DataFlow::Node node) { isSourcePair(node, _, _, _) }
|
||||
@@ -211,7 +267,7 @@ private module Config implements ProductFlow::StateConfigSig {
|
||||
private module AllocToInvalidPointerFlow = ProductFlow::GlobalWithState<Config>;
|
||||
|
||||
/**
|
||||
* Holds if `pai` is non-strictly upper bounded by `sink2 + delta` and `sink1` is the
|
||||
* Holds if `pai` is non-strictly upper bounded by `sizeSink + delta` and `allocSink` is the
|
||||
* left operand of the pointer-arithmetic operation.
|
||||
*
|
||||
* For example in,
|
||||
@@ -220,37 +276,37 @@ private module AllocToInvalidPointerFlow = ProductFlow::GlobalWithState<Config>;
|
||||
* ```
|
||||
* We will have:
|
||||
* - `pai` is `p + (size + 1)`,
|
||||
* - `sink1` is `p`
|
||||
* - `sink2` is `size`
|
||||
* - `allocSink` is `p`
|
||||
* - `sizeSink` is `size`
|
||||
* - `delta` is `1`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate pointerAddInstructionHasBounds0(
|
||||
PointerAddInstruction pai, DataFlow::Node sink1, DataFlow::Node sink2, int delta
|
||||
PointerAddInstruction pai, DataFlow::Node allocSink, DataFlow::Node sizeSink, int delta
|
||||
) {
|
||||
InterestingPointerAddInstruction::isInteresting(pragma[only_bind_into](pai)) and
|
||||
exists(Instruction right, Instruction instr2 |
|
||||
exists(Instruction right, Instruction sizeInstr |
|
||||
pai.getRight() = right and
|
||||
pai.getLeft() = sink1.asInstruction() and
|
||||
instr2 = sink2.asInstruction() and
|
||||
// pai.getRight() <= sink2 + delta
|
||||
bounded1(right, instr2, delta) and
|
||||
not right = Barrier2::getABarrierInstruction(delta) and
|
||||
not instr2 = Barrier2::getABarrierInstruction(delta)
|
||||
pai.getLeft() = allocSink.asInstruction() and
|
||||
sizeInstr = sizeSink.asInstruction() and
|
||||
// pai.getRight() <= sizeSink + delta
|
||||
bounded1(right, sizeInstr, delta) and
|
||||
not right = SizeBarrier::getABarrierInstruction(delta) and
|
||||
not sizeInstr = SizeBarrier::getABarrierInstruction(delta)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `allocation` flows to `sink1` and `sink1` represents the left-hand
|
||||
* side of the pointer-arithmetic instruction `pai`, and the right-hand side of `pai`
|
||||
* is non-strictly upper bounded by the size of `alllocation` + `delta`.
|
||||
* Holds if `allocation` flows to `allocSink` and `allocSink` represents the left operand
|
||||
* of the pointer-arithmetic instruction `pai = a + b` (i.e., `allocSink = a`), and
|
||||
* `b <= allocation + delta`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate pointerAddInstructionHasBounds(
|
||||
DataFlow::Node allocation, PointerAddInstruction pai, DataFlow::Node sink1, int delta
|
||||
DataFlow::Node allocation, PointerAddInstruction pai, DataFlow::Node allocSink, int delta
|
||||
) {
|
||||
exists(DataFlow::Node sink2 |
|
||||
AllocToInvalidPointerFlow::flow(allocation, _, sink1, sink2) and
|
||||
pointerAddInstructionHasBounds0(pai, sink1, sink2, delta)
|
||||
exists(DataFlow::Node sizeSink |
|
||||
AllocToInvalidPointerFlow::flow(allocation, _, allocSink, sizeSink) and
|
||||
pointerAddInstructionHasBounds0(pai, allocSink, sizeSink, delta)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,78 @@
|
||||
* This file provides the second phase of the `cpp/invalid-pointer-deref` query that identifies flow
|
||||
* from the out-of-bounds pointer identified by the `AllocationToInvalidPointer.qll` library to
|
||||
* a dereference of the out-of-bounds pointer.
|
||||
*
|
||||
* Consider the following snippet:
|
||||
* ```cpp
|
||||
* 1. char* base = (char*)malloc(size);
|
||||
* 2. char* end = base + size;
|
||||
* 3. for(char *p = base; p <= end; p++) {
|
||||
* 4. use(*p); // BUG: Should have been bounded by `p < end`.
|
||||
* 5. }
|
||||
* ```
|
||||
* this file identifies the flow from `base + size` to `end`. We call `base + size` the "dereference source" and `end`
|
||||
* the "dereference sink" (even though `end` is not actually dereferenced we will use this term because we will perform
|
||||
* dataflow to find a use of a pointer `x` such that `x <= end` which is dereferenced. In the above example, `x` is `p`
|
||||
* on line 4).
|
||||
*
|
||||
* Merely _constructing_ a pointer that's out-of-bounds is fine if the pointer is never dereferenced (in reality, the
|
||||
* standard only guarantees that it is safe to move the pointer one element past the last element, but we ignore that
|
||||
* here). So this step is about identifying which of the out-of-bounds pointers found by `pointerAddInstructionHasBounds`
|
||||
* in `AllocationToInvalidPointer.qll` are actually being dereferenced. We do this using a regular dataflow
|
||||
* configuration (see `InvalidPointerToDerefConfig`).
|
||||
*
|
||||
* The dataflow traversal defines the set of sources as any dataflow node `n` such that there exists a pointer-arithmetic
|
||||
* instruction `pai` found by `AllocationToInvalidPointer.qll` and a `n.asInstruction() >= pai + deltaDerefSourceAndPai`.
|
||||
* Here, `deltaDerefSourceAndPai` is the constant difference between the source we track for finding a dereference and the
|
||||
* pointer-arithmetic instruction.
|
||||
*
|
||||
* The set of sinks is defined as any dataflow node `n` such that `addr <= n.asInstruction() + deltaDerefSinkAndDerefAddress`
|
||||
* for some address operand `addr` and constant difference `deltaDerefSinkAndDerefAddress`. Since an address operand is
|
||||
* always consumed by an instruction that performs a dereference this lets us identify a "bad dereference". We call the
|
||||
* instruction that consumes the address operand the "operation".
|
||||
*
|
||||
* For example, consider the flow from `base + size` to `end` above. The sink is `end` on line 3 because
|
||||
* `p <= end.asInstruction() + deltaDerefSinkAndDerefAddress`, where `p` is the address operand in `use(*p)` and
|
||||
* `deltaDerefSinkAndDerefAddress >= 0`. The load attached to `*p` is the "operation". To ensure that the path makes
|
||||
* intuitive sense, we only pick operations that are control-flow reachable from the dereference sink.
|
||||
*
|
||||
* To compute how many elements the dereference is beyond the end position of the allocation, we sum the two deltas
|
||||
* `deltaDerefSourceAndPai` and `deltaDerefSinkAndDerefAddress`. This is done in the `operationIsOffBy` predicate
|
||||
* (which is the only predicate exposed by this file).
|
||||
*
|
||||
* Handling false positives:
|
||||
*
|
||||
* Consider the following snippet:
|
||||
* ```cpp
|
||||
* 1. char *p = new char[size];
|
||||
* 2. char *end = p + size;
|
||||
* 3. if (p < end) {
|
||||
* 4. p += 1;
|
||||
* 5. }
|
||||
* 6. if (p < end) {
|
||||
* 7. int val = *p; // GOOD
|
||||
* 8. }
|
||||
* ```
|
||||
* this is safe because `p` is guarded to be strictly less than `end` on line 6 before the dereference on line 7. However, if we
|
||||
* run the query on the above without further modifications we would see an alert on line 7. This is because range analysis infers
|
||||
* that `p <= end` after the increment on line 4, and thus the result of `p += 1` is seen as a valid dereference source. This
|
||||
* node then flows to `p` on line 6 (which is a valid dereference sink since it non-strictly upper bounds an address operand), and
|
||||
* range analysis then infers that the address operand of `*p` (i.e., `p`) is non-strictly upper bounded by `p`, and thus reports
|
||||
* an alert on line 7.
|
||||
*
|
||||
* In order to handle the above false positive, we define a barrier that identifies guards such as `p < end` that ensures that a value
|
||||
* is less than the pointer-arithmetic instruction that computed the invalid pointer. This is done in the `InvalidPointerToDerefBarrier`
|
||||
* module. Since the node we are tracking is not necessarily _equal_ to the pointer-arithmetic instruction, but rather satisfies
|
||||
* `node.asInstruction() <= pai + deltaDerefSourceAndPai`, we need to account for the delta when checking if a guard is sufficiently
|
||||
* strong to infer that a future dereference is safe. To do this, we check that the guard guarantees that a node `n` satisfies
|
||||
* `n < node + k` where `node` is a node such that `node <= pai`. Thus, we know that any node `m` such that `m <= n + delta` where
|
||||
* `delta + k <= 0` will be safe because:
|
||||
* ```
|
||||
* m <= n + delta
|
||||
* < node + k + delta
|
||||
* <= pai + k + delta
|
||||
* <= pai
|
||||
* ```
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
@@ -13,16 +85,19 @@ private import RangeAnalysisUtil
|
||||
|
||||
private module InvalidPointerToDerefBarrier {
|
||||
private module BarrierConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
// The sources is the same as in the sources for `InvalidPointerToDerefConfig`.
|
||||
invalidPointerToDerefSource(_, _, source, _)
|
||||
additional predicate isSource(DataFlow::Node source, PointerArithmeticInstruction pai) {
|
||||
invalidPointerToDerefSource(_, pai, _, _) and
|
||||
// source <= pai
|
||||
bounded2(source.asInstruction(), pai, any(int d | d <= 0))
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node source) { isSource(source, _) }
|
||||
|
||||
additional predicate isSink(
|
||||
DataFlow::Node left, DataFlow::Node right, IRGuardCondition g, int state, boolean testIsTrue
|
||||
DataFlow::Node small, DataFlow::Node large, IRGuardCondition g, int k, boolean testIsTrue
|
||||
) {
|
||||
// The sink is any "large" side of a relational comparison.
|
||||
g.comparesLt(left.asOperand(), right.asOperand(), state, true, testIsTrue)
|
||||
g.comparesLt(small.asOperand(), large.asOperand(), k, true, testIsTrue)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isSink(_, sink, _, _, _) }
|
||||
@@ -30,102 +105,120 @@ private module InvalidPointerToDerefBarrier {
|
||||
|
||||
private module BarrierFlow = DataFlow::Global<BarrierConfig>;
|
||||
|
||||
private int getInvalidPointerToDerefSourceDelta(DataFlow::Node node) {
|
||||
exists(DataFlow::Node source |
|
||||
BarrierFlow::flow(source, node) and
|
||||
invalidPointerToDerefSource(_, _, source, result)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `g` ensures that `small < large + k` if `g` evaluates to `edge`.
|
||||
*
|
||||
* Additionally, it also holds that `large <= pai`. Thus, when `g` evaluates to `edge`
|
||||
* it holds that `small < pai + k`.
|
||||
*/
|
||||
private predicate operandGuardChecks(
|
||||
IRGuardCondition g, Operand left, Operand right, int state, boolean edge
|
||||
PointerArithmeticInstruction pai, IRGuardCondition g, Operand small, int k, boolean edge
|
||||
) {
|
||||
exists(DataFlow::Node nLeft, DataFlow::Node nRight, int state0 |
|
||||
nRight.asOperand() = right and
|
||||
nLeft.asOperand() = left and
|
||||
BarrierConfig::isSink(nLeft, nRight, g, state0, edge) and
|
||||
state = getInvalidPointerToDerefSourceDelta(nRight) and
|
||||
state0 <= state
|
||||
exists(DataFlow::Node source, DataFlow::Node nSmall, DataFlow::Node nLarge |
|
||||
nSmall.asOperand() = small and
|
||||
BarrierConfig::isSource(source, pai) and
|
||||
BarrierFlow::flow(source, nLarge) and
|
||||
BarrierConfig::isSink(nSmall, nLarge, g, k, edge)
|
||||
)
|
||||
}
|
||||
|
||||
Instruction getABarrierInstruction(int state) {
|
||||
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge |
|
||||
/**
|
||||
* Gets an instruction `instr` such that `instr < pai`.
|
||||
*/
|
||||
Instruction getABarrierInstruction(PointerArithmeticInstruction pai) {
|
||||
exists(IRGuardCondition g, ValueNumber value, Operand use, boolean edge, int delta, int k |
|
||||
use = value.getAUse() and
|
||||
operandGuardChecks(pragma[only_bind_into](g), pragma[only_bind_into](use), _, state,
|
||||
pragma[only_bind_into](edge)) and
|
||||
result = value.getAnInstruction() and
|
||||
g.controls(result.getBlock(), edge)
|
||||
// value < pai + k
|
||||
operandGuardChecks(pai, pragma[only_bind_into](g), pragma[only_bind_into](use),
|
||||
pragma[only_bind_into](k), pragma[only_bind_into](edge)) and
|
||||
// result <= value + delta
|
||||
bounded(result, value.getAnInstruction(), delta) and
|
||||
g.controls(result.getBlock(), edge) and
|
||||
delta + k <= 0
|
||||
// combining the above we have: result < pai + k + delta <= pai
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::Node getABarrierNode() { result.asOperand() = getABarrierInstruction(_).getAUse() }
|
||||
DataFlow::Node getABarrierNode(PointerArithmeticInstruction pai) {
|
||||
result.asOperand() = getABarrierInstruction(pai).getAUse()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
IRBlock getABarrierBlock(int state) { result.getAnInstruction() = getABarrierInstruction(state) }
|
||||
/**
|
||||
* Gets an address operand whose definition `instr` satisfies `instr < pai`.
|
||||
*/
|
||||
AddressOperand getABarrierAddressOperand(PointerArithmeticInstruction pai) {
|
||||
result.getDef() = getABarrierInstruction(pai)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to track flow from a pointer-arithmetic operation found
|
||||
* by `AllocToInvalidPointerConfig` to a dereference of the pointer.
|
||||
*/
|
||||
private module InvalidPointerToDerefConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { invalidPointerToDerefSource(_, _, source, _) }
|
||||
private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState extends PointerArithmeticInstruction {
|
||||
FlowState() { invalidPointerToDerefSource(_, this, _, _) }
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState pai) {
|
||||
invalidPointerToDerefSource(_, pai, source, _)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _) }
|
||||
predicate isSink(DataFlow::Node sink) { isInvalidPointerDerefSink(sink, _, _, _, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState pai) { none() }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node = any(DataFlow::SsaPhiNode phi | not phi.isPhiRead()).getAnInput(true)
|
||||
or
|
||||
node = InvalidPointerToDerefBarrier::getABarrierNode()
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node, FlowState pai) {
|
||||
// `node = getABarrierNode(pai)` ensures that node < pai, so this node is safe to dereference.
|
||||
// Note that this is the only place where the `FlowState` is used in this configuration.
|
||||
node = InvalidPointerToDerefBarrier::getABarrierNode(pai)
|
||||
}
|
||||
}
|
||||
|
||||
private import DataFlow::Global<InvalidPointerToDerefConfig>
|
||||
private import DataFlow::GlobalWithState<InvalidPointerToDerefConfig>
|
||||
|
||||
/**
|
||||
* Holds if `source1` is dataflow node that represents an allocation that flows to the
|
||||
* left-hand side of the pointer-arithmetic `pai`, and `derefSource` is a dataflow node with
|
||||
* a pointer-value that is non-strictly upper bounded by `pai + delta`.
|
||||
* Holds if `allocSource` is dataflow node that represents an allocation that flows to the
|
||||
* left-hand side of the pointer-arithmetic `pai`, and `derefSource <= pai + derefSourcePaiDelta`.
|
||||
*
|
||||
* For example, if `pai` is a pointer-arithmetic operation `p + size` in an expression such
|
||||
* as `(p + size) + 1` and `derefSource` is the node representing `(p + size) + 1`. In this
|
||||
* case `delta` is 1.
|
||||
* case `derefSourcePaiDelta` is 1.
|
||||
*/
|
||||
private predicate invalidPointerToDerefSource(
|
||||
DataFlow::Node source1, PointerArithmeticInstruction pai, DataFlow::Node derefSource, int delta
|
||||
DataFlow::Node allocSource, PointerArithmeticInstruction pai, DataFlow::Node derefSource,
|
||||
int deltaDerefSourceAndPai
|
||||
) {
|
||||
exists(int delta0 |
|
||||
// Note that `delta` is not necessarily equal to `delta0`:
|
||||
// `delta0` is the constant offset added to the size of the allocation, and
|
||||
// delta is the constant difference between the pointer-arithmetic instruction
|
||||
// and the instruction computing the address for which we will search for a dereference.
|
||||
AllocToInvalidPointer::pointerAddInstructionHasBounds(source1, pai, _, delta0) and
|
||||
bounded2(derefSource.asInstruction(), pai, delta) and
|
||||
delta >= 0 and
|
||||
// TODO: This condition will go away once #13725 is merged, and then we can make `Barrier2`
|
||||
// private to `AllocationToInvalidPointer.qll`.
|
||||
not derefSource.getBasicBlock() = AllocToInvalidPointer::Barrier2::getABarrierBlock(delta0)
|
||||
)
|
||||
// Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`:
|
||||
// `rhsSizeDelta` is the constant offset added to the size of the allocation, and
|
||||
// `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
|
||||
// and the instruction computing the address for which we will search for a dereference.
|
||||
AllocToInvalidPointer::pointerAddInstructionHasBounds(allocSource, pai, _, _) and
|
||||
// derefSource <= pai + deltaDerefSourceAndPai
|
||||
bounded2(derefSource.asInstruction(), pai, deltaDerefSourceAndPai) and
|
||||
deltaDerefSourceAndPai >= 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a sink for `InvalidPointerToDerefConfig` and `i` is a `StoreInstruction` that
|
||||
* writes to an address that non-strictly upper-bounds `sink`, or `i` is a `LoadInstruction` that
|
||||
* reads from an address that non-strictly upper-bounds `sink`.
|
||||
* writes to an address `addr` such that `addr <= sink`, or `i` is a `LoadInstruction` that
|
||||
* reads from an address `addr` such that `addr <= sink`.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate isInvalidPointerDerefSink(
|
||||
DataFlow::Node sink, Instruction i, string operation, int delta
|
||||
DataFlow::Node sink, AddressOperand addr, Instruction i, string operation,
|
||||
int deltaDerefSinkAndDerefAddress
|
||||
) {
|
||||
exists(AddressOperand addr, Instruction s, IRBlock b |
|
||||
exists(Instruction s |
|
||||
s = sink.asInstruction() and
|
||||
bounded(addr.getDef(), s, delta) and
|
||||
delta >= 0 and
|
||||
i.getAnOperand() = addr and
|
||||
b = i.getBlock() and
|
||||
not b = InvalidPointerToDerefBarrier::getABarrierBlock(delta)
|
||||
bounded(addr.getDef(), s, deltaDerefSinkAndDerefAddress) and
|
||||
deltaDerefSinkAndDerefAddress >= 0 and
|
||||
i.getAnOperand() = addr
|
||||
|
|
||||
i instanceof StoreInstruction and
|
||||
operation = "write"
|
||||
@@ -151,9 +244,11 @@ private Instruction getASuccessor(Instruction instr) {
|
||||
instr.getBlock().getASuccessor+() = result.getBlock()
|
||||
}
|
||||
|
||||
private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFlow::Node derefSink) {
|
||||
private predicate paiForDereferenceSink(
|
||||
PointerArithmeticInstruction pai, DataFlow::Node derefSink, int deltaDerefSourceAndPai
|
||||
) {
|
||||
exists(DataFlow::Node derefSource |
|
||||
invalidPointerToDerefSource(_, pai, derefSource, _) and
|
||||
invalidPointerToDerefSource(_, pai, derefSource, deltaDerefSourceAndPai) and
|
||||
flow(derefSource, derefSink)
|
||||
)
|
||||
}
|
||||
@@ -165,13 +260,15 @@ private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFl
|
||||
*/
|
||||
private predicate derefSinkToOperation(
|
||||
DataFlow::Node derefSink, PointerArithmeticInstruction pai, DataFlow::Node operation,
|
||||
string description, int delta
|
||||
string description, int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress
|
||||
) {
|
||||
exists(Instruction i |
|
||||
paiForDereferenceSink(pai, pragma[only_bind_into](derefSink)) and
|
||||
isInvalidPointerDerefSink(derefSink, i, description, delta) and
|
||||
i = getASuccessor(derefSink.asInstruction()) and
|
||||
operation.asInstruction() = i
|
||||
exists(Instruction operationInstr, AddressOperand addr |
|
||||
paiForDereferenceSink(pai, pragma[only_bind_into](derefSink), deltaDerefSourceAndPai) and
|
||||
isInvalidPointerDerefSink(derefSink, addr, operationInstr, description,
|
||||
deltaDerefSinkAndDerefAddress) and
|
||||
operationInstr = getASuccessor(derefSink.asInstruction()) and
|
||||
operation.asInstruction() = operationInstr and
|
||||
not addr = InvalidPointerToDerefBarrier::getABarrierAddressOperand(pai)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,7 +287,8 @@ predicate operationIsOffBy(
|
||||
exists(int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress |
|
||||
invalidPointerToDerefSource(allocation, pai, derefSource, deltaDerefSourceAndPai) and
|
||||
flow(derefSource, derefSink) and
|
||||
derefSinkToOperation(derefSink, pai, operation, description, deltaDerefSinkAndDerefAddress) and
|
||||
derefSinkToOperation(derefSink, pai, operation, description, deltaDerefSourceAndPai,
|
||||
deltaDerefSinkAndDerefAddress) and
|
||||
delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ private Instruction getABoundIn(SemBound b, IRFunction func) {
|
||||
* Holds if `i <= b + delta`.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate boundedImpl(Instruction i, Instruction b, int delta) {
|
||||
private predicate boundedImplCand(Instruction i, Instruction b, int delta) {
|
||||
exists(SemBound bound, IRFunction func |
|
||||
semBounded(getSemanticExpr(i), bound, delta, true, _) and
|
||||
b = getABoundIn(bound, func) and
|
||||
@@ -26,6 +26,15 @@ private predicate boundedImpl(Instruction i, Instruction b, int delta) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `i <= b + delta` and `delta` is the smallest integer that satisfies
|
||||
* this condition.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate boundedImpl(Instruction i, Instruction b, int delta) {
|
||||
delta = min(int cand | boundedImplCand(i, b, cand))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `i <= b + delta`.
|
||||
*
|
||||
|
||||
@@ -608,7 +608,7 @@ case @builtintype.kind of
|
||||
| 47 = @std_float64 // _Float64
|
||||
| 48 = @float64x // _Float64x
|
||||
| 49 = @std_float128 // _Float128
|
||||
| 50 = @float128x // _Float128x
|
||||
// ... 50 _Float128x
|
||||
| 51 = @char8_t
|
||||
| 52 = @float16 // _Float16
|
||||
| 53 = @complex_float16 // _Complex _Float16
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
class BuiltinType extends @builtintype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isFloat128xBuiltinType(BuiltinType type) {
|
||||
exists(int kind | builtintypes(type, _, kind, _, _, _) | kind = 50)
|
||||
}
|
||||
|
||||
from BuiltinType type, string name, int kind, int kind_new, int size, int sign, int alignment
|
||||
where
|
||||
builtintypes(type, name, kind, size, sign, alignment) and
|
||||
if isFloat128xBuiltinType(type) then kind_new = 1 else kind_new = kind
|
||||
select type, name, kind_new, size, sign, alignment
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Remove _Float128 type
|
||||
compatibility: partial
|
||||
builtintypes.rel: run builtintypes.qlo
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.7.3
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
int f() {
|
||||
void f() {
|
||||
char* buf = new char[SIZE];
|
||||
....
|
||||
...
|
||||
if (error) {
|
||||
free(buf); //error handling has freed the buffer
|
||||
delete buf; //error handling has freed the buffer
|
||||
}
|
||||
...
|
||||
log_contents(buf); //but it is still used here for logging
|
||||
...
|
||||
}
|
||||
|
||||
3
cpp/ql/src/change-notes/released/0.7.2.md
Normal file
3
cpp/ql/src/change-notes/released/0.7.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.7.2
|
||||
|
||||
No user-facing changes.
|
||||
3
cpp/ql/src/change-notes/released/0.7.3.md
Normal file
3
cpp/ql/src/change-notes/released/0.7.3.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.7.3
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.1
|
||||
lastReleaseVersion: 0.7.3
|
||||
|
||||
@@ -15,6 +15,51 @@
|
||||
* external/cwe/cwe-787
|
||||
*/
|
||||
|
||||
/*
|
||||
* High-level description of the query:
|
||||
*
|
||||
* The goal of this query is to identify issues such as:
|
||||
* ```cpp
|
||||
* 1. int* base = new int[size];
|
||||
* 2. int* end = base + size;
|
||||
* 3. for(int* p = base; p <= end; ++p) {
|
||||
* 4. *p = 0; // BUG: Should have been bounded by `p < end`.
|
||||
* 5. }
|
||||
* ```
|
||||
* In order to do this, we split the problem into three subtasks:
|
||||
* 1. First, we find flow from `new int[size]` to `base + size`.
|
||||
* 2. Then, we find flow from `base + size` to `end` (on line 3).
|
||||
* 3. Finally, we use range-analysis to find a write to (or read from) a pointer that may be greater than or equal to `end`.
|
||||
*
|
||||
* Step 1 is implemented in `AllocationToInvalidPointer.qll`, and step 2 is implemented by
|
||||
* `InvalidPointerToDereference.qll`. See those files for the description of these.
|
||||
*
|
||||
* This file imports both libraries and defines a final dataflow configuration that constructs the full path from
|
||||
* the allocation to the dereference of the out-of-bounds pointer. This is done for several reasons:
|
||||
* 1. It means the user is able to inspect the entire path from the allocation to the dereference, which can be useful
|
||||
* to understand the problem highlighted.
|
||||
* 2. It ensures that the call-contexts line up correctly when we transition from step 1 to step 2. See the
|
||||
* `test_missing_call_context_1` and `test_missing_call_context_2` tests for how this may flag false positives
|
||||
* without this final configuration.
|
||||
*
|
||||
* The source of the final path is an allocation that is:
|
||||
* 1. identified as flowing to an invalid pointer (by `AllocationToInvalidPointer`), and
|
||||
* 2. for which the invalid pointer flows to a dereference (as identified by `InvalidPointerToDereference`).
|
||||
*
|
||||
* The path can be described in 3 "chunks":
|
||||
* 1. One path from the allocation to the construction of the invalid pointer
|
||||
* 2. Another path from the construction of the invalid pointer to the final pointer that is about to be dereferenced.
|
||||
* 3. Finally, a single step from the dataflow node that represents the final pointer to the dereference.
|
||||
*
|
||||
* Step 1 happens when the flow state is `TInitial`, and step 2 and 3 happen when the flow state is `TPointerArith(pai)`
|
||||
* where the pointer-arithmetic instruction `pai` tracks the instruction that generated the out-of-bounds pointer. This
|
||||
* instruction is used in the construction of the alert message.
|
||||
*
|
||||
* The set of pointer-arithmetic instructions that define the `TPointerArith` flow state is restricted to be the pointer-
|
||||
* arithmetic instructions that both receive flow from the allocation (as identified by `AllocationToInvalidPointer.qll`),
|
||||
* and further flow to a dereference (as identified by `InvalidPointerToDereference.qll`).
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.7.1
|
||||
version: 0.7.3
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1308,6 +1308,11 @@ union_etc.cpp:
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = prvalue(load)
|
||||
# 6| getStmt(1): [ReturnStmt] return ...
|
||||
# 7| [GlobalVariable] S s
|
||||
# 7| getInitializer(): [Initializer] initializer for s
|
||||
# 7| getExpr(): [ConstructorCall] call to S
|
||||
# 7| Type = [VoidType] void
|
||||
# 7| ValueCategory = prvalue
|
||||
# 9| [CopyAssignmentOperator] C& C::operator=(C const&)
|
||||
# 9| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -1332,6 +1337,7 @@ union_etc.cpp:
|
||||
# 12| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] U &&
|
||||
# 14| [GlobalVariable] C c
|
||||
# 16| [CopyAssignmentOperator] U& U::operator=(U const&)
|
||||
# 16| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -1356,6 +1362,7 @@ union_etc.cpp:
|
||||
# 18| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] C &&
|
||||
# 20| [GlobalVariable] U u
|
||||
# 22| [TopLevelFunction] int foo()
|
||||
# 22| <params>:
|
||||
# 22| getEntryPoint(): [BlockStmt] { ... }
|
||||
|
||||
@@ -69,12 +69,6 @@ edges
|
||||
| test.cpp:322:19:322:27 | ... + ... | test.cpp:325:24:325:26 | end |
|
||||
| test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... |
|
||||
| test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 |
|
||||
| test.cpp:351:9:351:11 | arr | test.cpp:351:9:351:14 | access to array |
|
||||
| test.cpp:351:9:351:11 | arr | test.cpp:351:18:351:25 | access to array |
|
||||
| test.cpp:351:18:351:20 | arr | test.cpp:351:9:351:14 | access to array |
|
||||
| test.cpp:351:18:351:20 | arr | test.cpp:351:18:351:25 | access to array |
|
||||
| test.cpp:351:29:351:31 | arr | test.cpp:351:9:351:14 | access to array |
|
||||
| test.cpp:351:29:351:31 | arr | test.cpp:351:18:351:25 | access to array |
|
||||
nodes
|
||||
| test.cpp:34:5:34:24 | access to array | semmle.label | access to array |
|
||||
| test.cpp:34:10:34:12 | buf | semmle.label | buf |
|
||||
@@ -167,11 +161,6 @@ nodes
|
||||
| test.cpp:325:15:325:19 | temp2 | semmle.label | temp2 |
|
||||
| test.cpp:325:24:325:26 | end | semmle.label | end |
|
||||
| test.cpp:325:24:325:26 | end | semmle.label | end |
|
||||
| test.cpp:351:9:351:11 | arr | semmle.label | arr |
|
||||
| test.cpp:351:9:351:14 | access to array | semmle.label | access to array |
|
||||
| test.cpp:351:18:351:20 | arr | semmle.label | arr |
|
||||
| test.cpp:351:18:351:25 | access to array | semmle.label | access to array |
|
||||
| test.cpp:351:29:351:31 | arr | semmle.label | arr |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:35:5:35:22 | PointerAdd: access to array | test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:35:5:35:26 | Store: ... = ... | write |
|
||||
@@ -194,6 +183,3 @@ subpaths
|
||||
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:330:13:330:24 | Store: ... = ... | write |
|
||||
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:331:13:331:24 | Store: ... = ... | write |
|
||||
| test.cpp:322:19:322:27 | PointerAdd: ... + ... | test.cpp:322:19:322:22 | temp | test.cpp:325:24:325:26 | end | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:314:10:314:13 | temp | temp | test.cpp:333:13:333:24 | Store: ... = ... | write |
|
||||
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:9:351:11 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |
|
||||
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:18:351:20 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |
|
||||
| test.cpp:351:18:351:25 | PointerAdd: access to array | test.cpp:351:29:351:31 | arr | test.cpp:351:18:351:25 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:348:9:348:11 | arr | arr | test.cpp:351:18:351:25 | Load: access to array | read |
|
||||
|
||||
@@ -348,7 +348,7 @@ int positiveRange(int x) {
|
||||
int arr[128];
|
||||
|
||||
for(int i=127-offset; i>= 0; i--) {
|
||||
arr[i] = arr[i+1] + arr[i+offset]; // GOOD [FALSE POSITIVE]
|
||||
arr[i] = arr[i+1] + arr[i+offset]; // GOOD
|
||||
}
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
@@ -129,7 +129,6 @@ edges
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | ... = ... |
|
||||
| test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | ... = ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:356:15:356:23 | ... + ... |
|
||||
| test.cpp:355:14:355:27 | new[] | test.cpp:357:24:357:30 | ... + ... |
|
||||
@@ -214,13 +213,26 @@ edges
|
||||
| test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... |
|
||||
| test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... |
|
||||
| test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:656:3:656:6 | ... ++ |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:656:3:656:6 | ... ++ | test.cpp:662:3:662:11 | ... = ... |
|
||||
| test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... |
|
||||
| test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... |
|
||||
| test.cpp:695:13:695:26 | new[] | test.cpp:698:5:698:10 | ... += ... |
|
||||
| test.cpp:698:5:698:10 | ... += ... | test.cpp:698:5:698:10 | ... += ... |
|
||||
| test.cpp:698:5:698:10 | ... += ... | test.cpp:701:15:701:16 | * ... |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:705:18:705:18 | q |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
|
||||
| test.cpp:705:18:705:18 | q | test.cpp:706:12:706:13 | * ... |
|
||||
| test.cpp:711:13:711:26 | new[] | test.cpp:714:11:714:11 | q |
|
||||
| test.cpp:714:11:714:11 | q | test.cpp:705:18:705:18 | q |
|
||||
| test.cpp:730:12:730:28 | new[] | test.cpp:732:16:732:26 | ... + ... |
|
||||
| test.cpp:730:12:730:28 | new[] | test.cpp:732:16:732:26 | ... + ... |
|
||||
| test.cpp:730:12:730:28 | new[] | test.cpp:733:5:733:12 | ... = ... |
|
||||
| test.cpp:732:16:732:26 | ... + ... | test.cpp:732:16:732:26 | ... + ... |
|
||||
| test.cpp:732:16:732:26 | ... + ... | test.cpp:733:5:733:12 | ... = ... |
|
||||
| test.cpp:732:16:732:26 | ... + ... | test.cpp:733:5:733:12 | ... = ... |
|
||||
| test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array |
|
||||
| test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array |
|
||||
| test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array |
|
||||
| test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array |
|
||||
| test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array |
|
||||
nodes
|
||||
| test.cpp:4:15:4:20 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:5:15:5:22 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -313,8 +325,6 @@ nodes
|
||||
| test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:274:5:274:10 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:304:15:304:26 | new[] | semmle.label | new[] |
|
||||
| test.cpp:308:5:308:29 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:355:14:355:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:356:15:356:23 | ... + ... | semmle.label | ... + ... |
|
||||
@@ -364,12 +374,26 @@ nodes
|
||||
| test.cpp:559:5:559:19 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:642:14:642:31 | new[] | semmle.label | new[] |
|
||||
| test.cpp:647:5:647:19 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:652:14:652:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:656:3:656:6 | ... ++ | semmle.label | ... ++ |
|
||||
| test.cpp:662:3:662:11 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:667:14:667:31 | new[] | semmle.label | new[] |
|
||||
| test.cpp:675:7:675:23 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:695:13:695:26 | new[] | semmle.label | new[] |
|
||||
| test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... |
|
||||
| test.cpp:698:5:698:10 | ... += ... | semmle.label | ... += ... |
|
||||
| test.cpp:701:15:701:16 | * ... | semmle.label | * ... |
|
||||
| test.cpp:705:18:705:18 | q | semmle.label | q |
|
||||
| test.cpp:705:18:705:18 | q | semmle.label | q |
|
||||
| test.cpp:706:12:706:13 | * ... | semmle.label | * ... |
|
||||
| test.cpp:711:13:711:26 | new[] | semmle.label | new[] |
|
||||
| test.cpp:714:11:714:11 | q | semmle.label | q |
|
||||
| test.cpp:730:12:730:28 | new[] | semmle.label | new[] |
|
||||
| test.cpp:732:16:732:26 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:732:16:732:26 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:733:5:733:12 | ... = ... | semmle.label | ... = ... |
|
||||
| test.cpp:754:18:754:31 | new[] | semmle.label | new[] |
|
||||
| test.cpp:767:16:767:29 | access to array | semmle.label | access to array |
|
||||
| test.cpp:767:16:767:29 | access to array | semmle.label | access to array |
|
||||
| test.cpp:772:16:772:29 | access to array | semmle.label | access to array |
|
||||
| test.cpp:772:16:772:29 | access to array | semmle.label | access to array |
|
||||
| test.cpp:781:14:781:27 | new[] | semmle.label | new[] |
|
||||
| test.cpp:786:18:786:27 | access to array | semmle.label | access to array |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:6:14:6:15 | * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
|
||||
@@ -391,7 +415,6 @@ subpaths
|
||||
| test.cpp:254:9:254:16 | ... = ... | test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:16 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:24:248:30 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
|
||||
| test.cpp:264:13:264:14 | * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
|
||||
| test.cpp:274:5:274:10 | ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
|
||||
| test.cpp:308:5:308:29 | ... = ... | test.cpp:304:15:304:26 | new[] | test.cpp:308:5:308:29 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:304:15:304:26 | new[] | new[] | test.cpp:308:8:308:10 | ... + ... | ... + ... |
|
||||
| test.cpp:358:14:358:26 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:358:14:358:26 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
|
||||
| test.cpp:359:14:359:32 | * ... | test.cpp:355:14:355:27 | new[] | test.cpp:359:14:359:32 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 2. | test.cpp:355:14:355:27 | new[] | new[] | test.cpp:356:20:356:23 | size | size |
|
||||
| test.cpp:384:13:384:16 | * ... | test.cpp:377:14:377:27 | new[] | test.cpp:384:13:384:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:377:14:377:27 | new[] | new[] | test.cpp:378:20:378:23 | size | size |
|
||||
@@ -403,5 +426,11 @@ subpaths
|
||||
| test.cpp:548:5:548:19 | ... = ... | test.cpp:543:14:543:27 | new[] | test.cpp:548:5:548:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:543:14:543:27 | new[] | new[] | test.cpp:548:8:548:14 | src_pos | src_pos |
|
||||
| test.cpp:559:5:559:19 | ... = ... | test.cpp:554:14:554:27 | new[] | test.cpp:559:5:559:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:554:14:554:27 | new[] | new[] | test.cpp:559:8:559:14 | src_pos | src_pos |
|
||||
| test.cpp:647:5:647:19 | ... = ... | test.cpp:642:14:642:31 | new[] | test.cpp:647:5:647:19 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:642:14:642:31 | new[] | new[] | test.cpp:647:8:647:14 | src_pos | src_pos |
|
||||
| test.cpp:662:3:662:11 | ... = ... | test.cpp:652:14:652:27 | new[] | test.cpp:662:3:662:11 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:652:14:652:27 | new[] | new[] | test.cpp:653:19:653:22 | size | size |
|
||||
| test.cpp:675:7:675:23 | ... = ... | test.cpp:667:14:667:31 | new[] | test.cpp:675:7:675:23 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:667:14:667:31 | new[] | new[] | test.cpp:675:10:675:18 | ... ++ | ... ++ |
|
||||
| test.cpp:701:15:701:16 | * ... | test.cpp:695:13:695:26 | new[] | test.cpp:701:15:701:16 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:695:13:695:26 | new[] | new[] | test.cpp:696:19:696:22 | size | size |
|
||||
| test.cpp:706:12:706:13 | * ... | test.cpp:711:13:711:26 | new[] | test.cpp:706:12:706:13 | * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:711:13:711:26 | new[] | new[] | test.cpp:712:19:712:22 | size | size |
|
||||
| test.cpp:733:5:733:12 | ... = ... | test.cpp:730:12:730:28 | new[] | test.cpp:733:5:733:12 | ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:730:12:730:28 | new[] | new[] | test.cpp:732:21:732:25 | ... + ... | ... + ... |
|
||||
| test.cpp:767:16:767:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:767:22:767:28 | ... + ... | ... + ... |
|
||||
| test.cpp:767:16:767:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:767:16:767:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:772:22:772:28 | ... + ... | ... + ... |
|
||||
| test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:767:22:767:28 | ... + ... | ... + ... |
|
||||
| test.cpp:772:16:772:29 | access to array | test.cpp:754:18:754:31 | new[] | test.cpp:772:16:772:29 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:754:18:754:31 | new[] | new[] | test.cpp:772:22:772:28 | ... + ... | ... + ... |
|
||||
| test.cpp:786:18:786:27 | access to array | test.cpp:781:14:781:27 | new[] | test.cpp:786:18:786:27 | access to array | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:781:14:781:27 | new[] | new[] | test.cpp:786:20:786:26 | ... + ... | ... + ... |
|
||||
|
||||
@@ -305,7 +305,7 @@ void test21() {
|
||||
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
xs[i] = test21_get(i); // GOOD
|
||||
xs[i+1] = test21_get(i+1); // $ alloc=L304 alloc=L304-1 deref=L308 // GOOD [FALSE POSITIVE]
|
||||
xs[i+1] = test21_get(i+1); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -659,7 +659,7 @@ void test32(unsigned size) {
|
||||
xs++;
|
||||
if (xs >= end)
|
||||
return;
|
||||
xs[0] = 0; // $ deref=L656->L662+1 deref=L657->L662+1 GOOD [FALSE POSITIVE]
|
||||
xs[0] = 0; // GOOD
|
||||
}
|
||||
|
||||
void test33(unsigned size, unsigned src_pos)
|
||||
@@ -672,7 +672,7 @@ void test33(unsigned size, unsigned src_pos)
|
||||
while (dst_pos < size - 1) {
|
||||
dst_pos++;
|
||||
if (true)
|
||||
xs[dst_pos++] = 0; // $ alloc=L667+1 deref=L675 // GOOD [FALSE POSITIVE]
|
||||
xs[dst_pos++] = 0; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,4 +689,102 @@ void test_missing_call_context_2(unsigned size) {
|
||||
int* p = new int[size];
|
||||
int* end_minus_one = pointer_arithmetic(p, size - 1);
|
||||
*end_minus_one = '0'; // $ deref=L680->L690->L691 // GOOD
|
||||
}
|
||||
|
||||
void test34(unsigned size) {
|
||||
char *p = new char[size];
|
||||
char *end = p + size + 1; // $ alloc=L695
|
||||
if (p + 1 < end) {
|
||||
p += 1;
|
||||
}
|
||||
if (p + 1 < end) {
|
||||
int val = *p; // $ deref=L698->L700->L701 // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void deref(char* q) {
|
||||
char x = *q; // $ deref=L714->L705->L706 // BAD
|
||||
}
|
||||
|
||||
void test35(unsigned long size, char* q)
|
||||
{
|
||||
char* p = new char[size];
|
||||
char* end = p + size; // $ alloc=L711
|
||||
if(q <= end) {
|
||||
deref(q);
|
||||
}
|
||||
}
|
||||
|
||||
void test21_simple(bool b) {
|
||||
int n = 0;
|
||||
if (b) n = 2;
|
||||
|
||||
int* xs = new int[n];
|
||||
|
||||
for (int i = 0; i < n; i += 2) {
|
||||
xs[i+1] = 0; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void test36(unsigned size, unsigned n) {
|
||||
int* p = new int[size + 2];
|
||||
if(n < size + 1) {
|
||||
int* end = p + (n + 2); // $ alloc=L730+2
|
||||
*end = 0; // $ deref=L733 // BAD
|
||||
}
|
||||
}
|
||||
|
||||
void test37(unsigned long n)
|
||||
{
|
||||
int *p = new int[n];
|
||||
for (unsigned long i = n; i != 0u; i--)
|
||||
{
|
||||
p[n - i] = 0; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get(char);
|
||||
void exit(int);
|
||||
|
||||
void error(const char * msg) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void test38(unsigned size) {
|
||||
char * alloc = new char[size];
|
||||
|
||||
unsigned pos = 0;
|
||||
while (pos < size) {
|
||||
char kind = alloc[pos];
|
||||
unsigned n = get(alloc[pos]);
|
||||
if (pos + n >= size) {
|
||||
error("");
|
||||
}
|
||||
switch (kind) {
|
||||
case '0':
|
||||
if (n != 1)
|
||||
error("");
|
||||
char x = alloc[pos + 1]; // $ alloc=L754 deref=L767 // GOOD [FALSE POSITIVE]
|
||||
break;
|
||||
case '1':
|
||||
if (n != 2)
|
||||
error("");
|
||||
char a = alloc[pos + 1]; // $ alloc=L754 deref=L772 // GOOD [FALSE POSITIVE]
|
||||
char b = alloc[pos + 2];
|
||||
break;
|
||||
}
|
||||
pos += 1 + n;
|
||||
}
|
||||
}
|
||||
|
||||
void test38_simple(unsigned size, unsigned pos, unsigned numParams) {
|
||||
char * p = new char[size];
|
||||
|
||||
if (pos < size) {
|
||||
if (pos + numParams < size) {
|
||||
if (numParams == 1) {
|
||||
char x = p[pos + 1]; // $ alloc=L781 deref=L786 // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,3 +16,5 @@ class AddressOfGetter {
|
||||
&field;
|
||||
}
|
||||
};
|
||||
|
||||
__declspec("SAL_volatile") char* pBuf;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
| ms_var_attributes.cpp:8:15:8:20 | myInt4 | ms_var_attributes.cpp:8:1:8:9 | dllexport |
|
||||
| ms_var_attributes.cpp:9:5:9:10 | myInt5 | ms_var_attributes.h:7:1:7:9 | dllexport |
|
||||
| ms_var_attributes.cpp:12:42:12:46 | field | ms_var_attributes.cpp:12:14:12:21 | property |
|
||||
| ms_var_attributes.cpp:20:34:20:37 | pBuf | ms_var_attributes.cpp:20:12:20:12 | SAL_volatile |
|
||||
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
|
||||
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
|
||||
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |
|
||||
|
||||
@@ -732,7 +732,7 @@ void test_does_not_write_source_to_dereference()
|
||||
{
|
||||
int x;
|
||||
does_not_write_source_to_dereference(&x);
|
||||
sink(x); // $ ast,ir=733:7 SPURIOUS: ast,ir=726:11
|
||||
sink(x); // $ ast=733:7 ir SPURIOUS: ast=726:11
|
||||
}
|
||||
|
||||
void sometimes_calls_sink_eq(int x, int n) {
|
||||
|
||||
@@ -134,7 +134,7 @@ void pointer_test() {
|
||||
sink(*p3); // $ ast,ir
|
||||
|
||||
*p3 = 0;
|
||||
sink(*p3); // $ SPURIOUS: ast,ir
|
||||
sink(*p3); // $ SPURIOUS: ast
|
||||
}
|
||||
|
||||
// --- return values ---
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
| file://:0:0:0:0 | There was an error during this compilation |
|
||||
| float128.cpp:1:39:1:39 | 128-bit floating-point types are not supported in this configuration |
|
||||
| float128.cpp:2:30:2:30 | 128-bit floating-point types are not supported in this configuration |
|
||||
@@ -1,4 +0,0 @@
|
||||
import cpp
|
||||
|
||||
from Diagnostic d
|
||||
select d
|
||||
@@ -1,5 +1,5 @@
|
||||
typedef _Complex float __attribute__((mode(TC))) _Complex128; // [COMPILER ERROR AND ERROR-TYPE DUE TO __float128 BEING DISABLED]
|
||||
typedef float __attribute__((mode(TF))) _Float128; // [COMPILER ERROR AND ERROR-TYPE DUE TO __float128 BEING DISABLED]
|
||||
typedef _Complex float __attribute__((mode(TC))) _Complex128;
|
||||
typedef float __attribute__((mode(TF))) _Float128;
|
||||
|
||||
int main() {
|
||||
__float128 f = 1.0f;
|
||||
@@ -25,4 +25,3 @@ __float128 id(__float128 q)
|
||||
{
|
||||
return q;
|
||||
}
|
||||
// semmle-extractor-options: --expect_errors
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | <error-type> |
|
||||
| float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | <error-type> |
|
||||
| float128.cpp:1:50:1:60 | _Complex128 | file://:0:0:0:0 | float __complex__ |
|
||||
| float128.cpp:2:41:2:49 | _Float128 | file://:0:0:0:0 | __float128 |
|
||||
| float128.cpp:13:29:13:54 | __is_floating_point_helper<T> | float128.cpp:10:8:10:17 | false_type |
|
||||
| float128.cpp:14:19:14:51 | __is_floating_point_helper<float> | float128.cpp:11:8:11:16 | true_type |
|
||||
| float128.cpp:15:19:15:52 | __is_floating_point_helper<double> | float128.cpp:11:8:11:16 | true_type |
|
||||
|
||||
@@ -1728,6 +1728,76 @@ complex.c:
|
||||
# 144| Type = [LongDoubleType] long double
|
||||
# 144| ValueCategory = prvalue
|
||||
# 145| getStmt(72): [ReturnStmt] return ...
|
||||
ir.c:
|
||||
# 5| [TopLevelFunction] int getX(MyCoords*)
|
||||
# 5| <params>:
|
||||
# 5| getParameter(0): [Parameter] coords
|
||||
# 5| Type = [PointerType] MyCoords *
|
||||
# 7| [TopLevelFunction] void MyCoordsTest(int)
|
||||
# 7| <params>:
|
||||
# 7| getParameter(0): [Parameter] pos
|
||||
# 7| Type = [IntType] int
|
||||
# 7| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 8| getStmt(0): [DeclStmt] declaration
|
||||
# 8| getDeclarationEntry(0): [VariableDeclarationEntry] definition of coords
|
||||
# 8| Type = [CTypedefType] MyCoords
|
||||
# 8| getVariable().getInitializer(): [Initializer] initializer for coords
|
||||
# 8| getExpr(): [ClassAggregateLiteral] {...}
|
||||
# 8| Type = [Struct] (unnamed class/struct/union)
|
||||
# 8| ValueCategory = prvalue
|
||||
# 8| getAFieldExpr(x): [Literal] 0
|
||||
# 8| Type = [IntType] int
|
||||
# 8| Value = [Literal] 0
|
||||
# 8| ValueCategory = prvalue
|
||||
# 9| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 9| getExpr(): [AssignExpr] ... = ...
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = prvalue
|
||||
# 9| getLValue(): [ValueFieldAccess] x
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = lvalue
|
||||
# 9| getQualifier(): [VariableAccess] coords
|
||||
# 9| Type = [CTypedefType] MyCoords
|
||||
# 9| ValueCategory = lvalue
|
||||
# 9| getRValue(): [AssignExpr] ... = ...
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = prvalue
|
||||
# 9| getLValue(): [ValueFieldAccess] y
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = lvalue
|
||||
# 9| getQualifier(): [VariableAccess] coords
|
||||
# 9| Type = [CTypedefType] MyCoords
|
||||
# 9| ValueCategory = lvalue
|
||||
# 9| getRValue(): [AddExpr] ... + ...
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = prvalue
|
||||
# 9| getLeftOperand(): [VariableAccess] pos
|
||||
# 9| Type = [IntType] int
|
||||
# 9| ValueCategory = prvalue(load)
|
||||
# 9| getRightOperand(): [Literal] 1
|
||||
# 9| Type = [IntType] int
|
||||
# 9| Value = [Literal] 1
|
||||
# 9| ValueCategory = prvalue
|
||||
# 10| getStmt(2): [ExprStmt] ExprStmt
|
||||
# 10| getExpr(): [AssignExpr] ... = ...
|
||||
# 10| Type = [IntType] int
|
||||
# 10| ValueCategory = prvalue
|
||||
# 10| getLValue(): [ValueFieldAccess] x
|
||||
# 10| Type = [IntType] int
|
||||
# 10| ValueCategory = lvalue
|
||||
# 10| getQualifier(): [VariableAccess] coords
|
||||
# 10| Type = [CTypedefType] MyCoords
|
||||
# 10| ValueCategory = lvalue
|
||||
# 10| getRValue(): [FunctionCall] call to getX
|
||||
# 10| Type = [IntType] int
|
||||
# 10| ValueCategory = prvalue
|
||||
# 10| getArgument(0): [AddressOfExpr] & ...
|
||||
# 10| Type = [PointerType] MyCoords *
|
||||
# 10| ValueCategory = prvalue
|
||||
# 10| getOperand(): [VariableAccess] coords
|
||||
# 10| Type = [CTypedefType] MyCoords
|
||||
# 10| ValueCategory = lvalue
|
||||
# 11| getStmt(3): [ReturnStmt] return ...
|
||||
ir.cpp:
|
||||
# 1| [TopLevelFunction] void Constants()
|
||||
# 1| <params>:
|
||||
@@ -8529,6 +8599,11 @@ ir.cpp:
|
||||
# 1035| Type = [Struct] EmptyStruct
|
||||
# 1035| ValueCategory = prvalue
|
||||
# 1036| getStmt(1): [ReturnStmt] return ...
|
||||
# 1038| [GlobalVariable] (lambda [] type at line 1038, col. 12) lam
|
||||
# 1038| getInitializer(): [Initializer] initializer for lam
|
||||
# 1038| getExpr(): [LambdaExpression] [...](...){...}
|
||||
# 1038| Type = [Closure] decltype([...](...){...})
|
||||
# 1038| ValueCategory = prvalue
|
||||
# 1038| [CopyAssignmentOperator] (lambda [] type at line 1038, col. 12)& (lambda [] type at line 1038, col. 12)::operator=((lambda [] type at line 1038, col. 12) const&)
|
||||
# 1038| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -13976,6 +14051,54 @@ ir.cpp:
|
||||
# 1815| Type = [IntType] int
|
||||
# 1815| ValueCategory = prvalue(load)
|
||||
# 1817| getStmt(8): [ReturnStmt] return ...
|
||||
# 1821| [GlobalVariable] int global_2
|
||||
# 1821| getInitializer(): [Initializer] initializer for global_2
|
||||
# 1821| getExpr(): [Literal] 1
|
||||
# 1821| Type = [IntType] int
|
||||
# 1821| Value = [Literal] 1
|
||||
# 1821| ValueCategory = prvalue
|
||||
# 1823| [GlobalVariable] int const global_3
|
||||
# 1823| getInitializer(): [Initializer] initializer for global_3
|
||||
# 1823| getExpr(): [Literal] 2
|
||||
# 1823| Type = [IntType] int
|
||||
# 1823| Value = [Literal] 2
|
||||
# 1823| ValueCategory = prvalue
|
||||
# 1825| [GlobalVariable] constructor_only global_4
|
||||
# 1825| getInitializer(): [Initializer] initializer for global_4
|
||||
# 1825| getExpr(): [ConstructorCall] call to constructor_only
|
||||
# 1825| Type = [VoidType] void
|
||||
# 1825| ValueCategory = prvalue
|
||||
# 1825| getArgument(0): [Literal] 1
|
||||
# 1825| Type = [IntType] int
|
||||
# 1825| Value = [Literal] 1
|
||||
# 1825| ValueCategory = prvalue
|
||||
# 1827| [GlobalVariable] constructor_only global_5
|
||||
# 1827| getInitializer(): [Initializer] initializer for global_5
|
||||
# 1827| getExpr(): [ConstructorCall] call to constructor_only
|
||||
# 1827| Type = [VoidType] void
|
||||
# 1827| ValueCategory = prvalue
|
||||
# 1827| getArgument(0): [Literal] 2
|
||||
# 1827| Type = [IntType] int
|
||||
# 1827| Value = [Literal] 2
|
||||
# 1827| ValueCategory = prvalue
|
||||
# 1829| [GlobalVariable] char* global_string
|
||||
# 1829| getInitializer(): [Initializer] initializer for global_string
|
||||
# 1829| getExpr(): global string
|
||||
# 1829| Type = [ArrayType] const char[14]
|
||||
# 1829| Value = [StringLiteral] "global string"
|
||||
# 1829| ValueCategory = lvalue
|
||||
# 1829| getExpr().getFullyConverted(): [CStyleCast] (char *)...
|
||||
# 1829| Conversion = [PointerConversion] pointer conversion
|
||||
# 1829| Type = [CharPointerType] char *
|
||||
# 1829| ValueCategory = prvalue
|
||||
# 1829| getExpr(): [ArrayToPointerConversion] array to pointer conversion
|
||||
# 1829| Type = [PointerType] const char *
|
||||
# 1829| ValueCategory = prvalue
|
||||
# 1831| [GlobalVariable] int global_6
|
||||
# 1831| getInitializer(): [Initializer] initializer for global_6
|
||||
# 1831| getExpr(): [VariableAccess] global_2
|
||||
# 1831| Type = [IntType] int
|
||||
# 1831| ValueCategory = prvalue(load)
|
||||
# 1834| [CopyAssignmentOperator] block_assignment::A& block_assignment::A::operator=(block_assignment::A const&)
|
||||
# 1834| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
@@ -14377,6 +14500,23 @@ ir.cpp:
|
||||
# 1885| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
|
||||
# 1885| ValueCategory = lvalue
|
||||
# 1886| getStmt(2): [ReturnStmt] return ...
|
||||
# 1889| [GlobalVariable] char global_template<char>
|
||||
# 1889| getInitializer(): [Initializer] initializer for global_template
|
||||
# 1889| getExpr(): [Literal] 42
|
||||
# 1889| Type = [IntType] int
|
||||
# 1889| Value = [Literal] 42
|
||||
# 1889| ValueCategory = prvalue
|
||||
# 1889| getExpr().getFullyConverted(): [CStyleCast] (char)...
|
||||
# 1889| Conversion = [IntegralConversion] integral conversion
|
||||
# 1889| Type = [PlainCharType] char
|
||||
# 1889| Value = [CStyleCast] 42
|
||||
# 1889| ValueCategory = prvalue
|
||||
# 1889| [GlobalVariable] int global_template<int>
|
||||
# 1889| getInitializer(): [Initializer] initializer for global_template
|
||||
# 1889| getExpr(): [Literal] 42
|
||||
# 1889| Type = [IntType] int
|
||||
# 1889| Value = [Literal] 42
|
||||
# 1889| ValueCategory = prvalue
|
||||
# 1891| [TopLevelFunction] int test_global_template_int()
|
||||
# 1891| <params>:
|
||||
# 1891| getEntryPoint(): [BlockStmt] { ... }
|
||||
@@ -14888,6 +15028,514 @@ ir.cpp:
|
||||
# 1993| Type = [Class] C
|
||||
# 1993| ValueCategory = lvalue
|
||||
# 1994| getStmt(3): [ReturnStmt] return ...
|
||||
# 1996| [TopLevelFunction] void TernaryTestInt(bool, int, int, int)
|
||||
# 1996| <params>:
|
||||
# 1996| getParameter(0): [Parameter] a
|
||||
# 1996| Type = [BoolType] bool
|
||||
# 1996| getParameter(1): [Parameter] x
|
||||
# 1996| Type = [IntType] int
|
||||
# 1996| getParameter(2): [Parameter] y
|
||||
# 1996| Type = [IntType] int
|
||||
# 1996| getParameter(3): [Parameter] z
|
||||
# 1996| Type = [IntType] int
|
||||
# 1996| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1997| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 1997| getExpr(): [AssignExpr] ... = ...
|
||||
# 1997| Type = [IntType] int
|
||||
# 1997| ValueCategory = lvalue
|
||||
# 1997| getLValue(): [VariableAccess] z
|
||||
# 1997| Type = [IntType] int
|
||||
# 1997| ValueCategory = lvalue
|
||||
# 1997| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 1997| Type = [IntType] int
|
||||
# 1997| ValueCategory = prvalue
|
||||
# 1997| getCondition(): [VariableAccess] a
|
||||
# 1997| Type = [BoolType] bool
|
||||
# 1997| ValueCategory = prvalue(load)
|
||||
# 1997| getThen(): [VariableAccess] x
|
||||
# 1997| Type = [IntType] int
|
||||
# 1997| ValueCategory = prvalue(load)
|
||||
# 1997| getElse(): [VariableAccess] y
|
||||
# 1997| Type = [IntType] int
|
||||
# 1997| ValueCategory = prvalue(load)
|
||||
# 1998| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 1998| getExpr(): [AssignExpr] ... = ...
|
||||
# 1998| Type = [IntType] int
|
||||
# 1998| ValueCategory = lvalue
|
||||
# 1998| getLValue(): [VariableAccess] z
|
||||
# 1998| Type = [IntType] int
|
||||
# 1998| ValueCategory = lvalue
|
||||
# 1998| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 1998| Type = [IntType] int
|
||||
# 1998| ValueCategory = prvalue
|
||||
# 1998| getCondition(): [VariableAccess] a
|
||||
# 1998| Type = [BoolType] bool
|
||||
# 1998| ValueCategory = prvalue(load)
|
||||
# 1998| getThen(): [VariableAccess] x
|
||||
# 1998| Type = [IntType] int
|
||||
# 1998| ValueCategory = prvalue(load)
|
||||
# 1998| getElse(): [Literal] 5
|
||||
# 1998| Type = [IntType] int
|
||||
# 1998| Value = [Literal] 5
|
||||
# 1998| ValueCategory = prvalue
|
||||
# 1999| getStmt(2): [ExprStmt] ExprStmt
|
||||
# 1999| getExpr(): [AssignExpr] ... = ...
|
||||
# 1999| Type = [IntType] int
|
||||
# 1999| ValueCategory = lvalue
|
||||
# 1999| getLValue(): [VariableAccess] z
|
||||
# 1999| Type = [IntType] int
|
||||
# 1999| ValueCategory = lvalue
|
||||
# 1999| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 1999| Type = [IntType] int
|
||||
# 1999| ValueCategory = prvalue
|
||||
# 1999| getCondition(): [VariableAccess] a
|
||||
# 1999| Type = [BoolType] bool
|
||||
# 1999| ValueCategory = prvalue(load)
|
||||
# 1999| getThen(): [Literal] 3
|
||||
# 1999| Type = [IntType] int
|
||||
# 1999| Value = [Literal] 3
|
||||
# 1999| ValueCategory = prvalue
|
||||
# 1999| getElse(): [Literal] 5
|
||||
# 1999| Type = [IntType] int
|
||||
# 1999| Value = [Literal] 5
|
||||
# 1999| ValueCategory = prvalue
|
||||
# 2000| getStmt(3): [ExprStmt] ExprStmt
|
||||
# 2000| getExpr(): [AssignExpr] ... = ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getLValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getCondition(): [VariableAccess] a
|
||||
# 2000| Type = [BoolType] bool
|
||||
# 2000| ValueCategory = prvalue(load)
|
||||
# 2000| getThen(): [VariableAccess] x
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getElse(): [VariableAccess] y
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2000| getRValue(): [Literal] 7
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| Value = [Literal] 7
|
||||
# 2000| ValueCategory = prvalue
|
||||
# 2000| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2000| Type = [IntType] int
|
||||
# 2000| ValueCategory = lvalue
|
||||
# 2001| getStmt(4): [ReturnStmt] return ...
|
||||
# 2003| [CopyAssignmentOperator] TernaryPodObj& TernaryPodObj::operator=(TernaryPodObj const&)
|
||||
# 2003| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const TernaryPodObj &
|
||||
# 2003| [MoveAssignmentOperator] TernaryPodObj& TernaryPodObj::operator=(TernaryPodObj&&)
|
||||
# 2003| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] TernaryPodObj &&
|
||||
# 2006| [TopLevelFunction] void TernaryTestPodObj(bool, TernaryPodObj, TernaryPodObj, TernaryPodObj)
|
||||
# 2006| <params>:
|
||||
# 2006| getParameter(0): [Parameter] a
|
||||
# 2006| Type = [BoolType] bool
|
||||
# 2006| getParameter(1): [Parameter] x
|
||||
# 2006| Type = [Struct] TernaryPodObj
|
||||
# 2006| getParameter(2): [Parameter] y
|
||||
# 2006| Type = [Struct] TernaryPodObj
|
||||
# 2006| getParameter(3): [Parameter] z
|
||||
# 2006| Type = [Struct] TernaryPodObj
|
||||
# 2006| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2007| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 2007| getExpr(): [AssignExpr] ... = ...
|
||||
# 2007| Type = [Struct] TernaryPodObj
|
||||
# 2007| ValueCategory = lvalue
|
||||
# 2007| getLValue(): [VariableAccess] z
|
||||
# 2007| Type = [Struct] TernaryPodObj
|
||||
# 2007| ValueCategory = lvalue
|
||||
# 2007| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2007| Type = [Struct] TernaryPodObj
|
||||
# 2007| ValueCategory = prvalue
|
||||
# 2007| getCondition(): [VariableAccess] a
|
||||
# 2007| Type = [BoolType] bool
|
||||
# 2007| ValueCategory = prvalue(load)
|
||||
# 2007| getThen(): [VariableAccess] x
|
||||
# 2007| Type = [Struct] TernaryPodObj
|
||||
# 2007| ValueCategory = prvalue(load)
|
||||
# 2007| getElse(): [VariableAccess] y
|
||||
# 2007| Type = [Struct] TernaryPodObj
|
||||
# 2007| ValueCategory = prvalue(load)
|
||||
# 2008| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 2008| getExpr(): [AssignExpr] ... = ...
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = lvalue
|
||||
# 2008| getLValue(): [VariableAccess] z
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = lvalue
|
||||
# 2008| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = prvalue
|
||||
# 2008| getCondition(): [VariableAccess] a
|
||||
# 2008| Type = [BoolType] bool
|
||||
# 2008| ValueCategory = prvalue(load)
|
||||
# 2008| getThen(): [VariableAccess] x
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = prvalue(load)
|
||||
# 2008| getElse(): [Literal] 0
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| Value = [Literal] 0
|
||||
# 2008| ValueCategory = prvalue
|
||||
# 2008| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = prvalue(load)
|
||||
# 2008| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = prvalue(load)
|
||||
# 2008| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2008| Type = [Struct] TernaryPodObj
|
||||
# 2008| ValueCategory = prvalue(load)
|
||||
# 2009| getStmt(2): [ExprStmt] ExprStmt
|
||||
# 2009| getExpr(): [AssignExpr] ... = ...
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = lvalue
|
||||
# 2009| getLValue(): [VariableAccess] z
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = lvalue
|
||||
# 2009| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = prvalue
|
||||
# 2009| getCondition(): [VariableAccess] a
|
||||
# 2009| Type = [BoolType] bool
|
||||
# 2009| ValueCategory = prvalue(load)
|
||||
# 2009| getThen(): [Literal] 0
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| Value = [Literal] 0
|
||||
# 2009| ValueCategory = prvalue
|
||||
# 2009| getElse(): [Literal] 0
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| Value = [Literal] 0
|
||||
# 2009| ValueCategory = prvalue
|
||||
# 2009| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = prvalue(load)
|
||||
# 2009| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = prvalue(load)
|
||||
# 2009| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2009| Type = [Struct] TernaryPodObj
|
||||
# 2009| ValueCategory = prvalue(load)
|
||||
# 2010| getStmt(3): [ExprStmt] ExprStmt
|
||||
# 2010| getExpr(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getLValue(): [AssignExpr] ... = ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getLValue(): [VariableAccess] z
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getCondition(): [VariableAccess] a
|
||||
# 2010| Type = [BoolType] bool
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getThen(): [VariableAccess] x
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getElse(): [VariableAccess] y
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2010| getRValue(): [Literal] 0
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| Value = [Literal] 0
|
||||
# 2010| ValueCategory = prvalue
|
||||
# 2010| getLValue().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = lvalue
|
||||
# 2010| getRValue().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2010| Type = [Struct] TernaryPodObj
|
||||
# 2010| ValueCategory = prvalue(load)
|
||||
# 2011| getStmt(4): [ReturnStmt] return ...
|
||||
# 2013| [CopyAssignmentOperator] TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
# 2013| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
#-----| getEntryPoint(): [BlockStmt] { ... }
|
||||
#-----| getStmt(0): [ReturnStmt] return ...
|
||||
#-----| getExpr(): [PointerDereferenceExpr] * ...
|
||||
#-----| Type = [Struct] TernaryNonPodObj
|
||||
#-----| ValueCategory = lvalue
|
||||
#-----| getOperand(): [ThisExpr] this
|
||||
#-----| Type = [PointerType] TernaryNonPodObj *
|
||||
#-----| ValueCategory = prvalue(load)
|
||||
#-----| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
#-----| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
#-----| ValueCategory = prvalue
|
||||
# 2013| [Constructor] void TernaryNonPodObj::TernaryNonPodObj()
|
||||
# 2013| <params>:
|
||||
# 2013| <initializations>:
|
||||
# 2013| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2013| getStmt(0): [ReturnStmt] return ...
|
||||
# 2013| [CopyConstructor] void TernaryNonPodObj::TernaryNonPodObj(TernaryNonPodObj const&)
|
||||
# 2013| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2013| <initializations>:
|
||||
# 2013| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2013| getStmt(0): [ReturnStmt] return ...
|
||||
# 2014| [Destructor,VirtualFunction] void TernaryNonPodObj::~TernaryNonPodObj()
|
||||
# 2014| <params>:
|
||||
# 2014| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2014| getStmt(0): [ReturnStmt] return ...
|
||||
# 2014| <destructions>:
|
||||
# 2017| [TopLevelFunction] void TernaryTestNonPodObj(bool, TernaryNonPodObj, TernaryNonPodObj, TernaryNonPodObj)
|
||||
# 2017| <params>:
|
||||
# 2017| getParameter(0): [Parameter] a
|
||||
# 2017| Type = [BoolType] bool
|
||||
# 2017| getParameter(1): [Parameter] x
|
||||
# 2017| Type = [Struct] TernaryNonPodObj
|
||||
# 2017| getParameter(2): [Parameter] y
|
||||
# 2017| Type = [Struct] TernaryNonPodObj
|
||||
# 2017| getParameter(3): [Parameter] z
|
||||
# 2017| Type = [Struct] TernaryNonPodObj
|
||||
# 2017| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2018| getStmt(0): [ExprStmt] ExprStmt
|
||||
# 2018| getExpr(): [FunctionCall] call to operator=
|
||||
# 2018| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2018| ValueCategory = prvalue
|
||||
# 2018| getQualifier(): [VariableAccess] z
|
||||
# 2018| Type = [Struct] TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2018| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2018| Type = [Struct] TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2018| getCondition(): [VariableAccess] a
|
||||
# 2018| Type = [BoolType] bool
|
||||
# 2018| ValueCategory = prvalue(load)
|
||||
# 2018| getThen(): [VariableAccess] x
|
||||
# 2018| Type = [Struct] TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2018| getElse(): [VariableAccess] y
|
||||
# 2018| Type = [Struct] TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2018| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2018| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2018| ValueCategory = prvalue
|
||||
# 2018| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2018| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2018| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2018| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2018| Type = [Struct] TernaryNonPodObj
|
||||
# 2018| ValueCategory = lvalue
|
||||
# 2019| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 2019| getExpr(): [FunctionCall] call to operator=
|
||||
# 2019| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getQualifier(): [VariableAccess] z
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2019| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getCondition(): [VariableAccess] a
|
||||
# 2019| Type = [BoolType] bool
|
||||
# 2019| ValueCategory = prvalue(load)
|
||||
# 2019| getThen(): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2019| Type = [VoidType] void
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getArgument(0): [VariableAccess] x
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2019| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2019| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2019| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2019| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2019| getElse(): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2019| Type = [VoidType] void
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = prvalue(load)
|
||||
# 2019| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = prvalue(load)
|
||||
# 2019| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2019| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2019| ValueCategory = prvalue
|
||||
# 2019| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2019| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2019| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2019| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2019| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2019| Type = [Struct] TernaryNonPodObj
|
||||
# 2019| ValueCategory = lvalue
|
||||
# 2020| getStmt(2): [ExprStmt] ExprStmt
|
||||
# 2020| getExpr(): [FunctionCall] call to operator=
|
||||
# 2020| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2020| ValueCategory = prvalue
|
||||
# 2020| getQualifier(): [VariableAccess] z
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = lvalue
|
||||
# 2020| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = prvalue
|
||||
# 2020| getCondition(): [VariableAccess] a
|
||||
# 2020| Type = [BoolType] bool
|
||||
# 2020| ValueCategory = prvalue(load)
|
||||
# 2020| getThen(): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2020| Type = [VoidType] void
|
||||
# 2020| ValueCategory = prvalue
|
||||
# 2020| getElse(): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2020| Type = [VoidType] void
|
||||
# 2020| ValueCategory = prvalue
|
||||
# 2020| getThen().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = prvalue(load)
|
||||
# 2020| getElse().getFullyConverted(): [TemporaryObjectExpr] temporary object
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = prvalue(load)
|
||||
# 2020| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2020| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2020| ValueCategory = prvalue
|
||||
# 2020| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2020| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2020| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2020| ValueCategory = lvalue
|
||||
# 2020| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = lvalue
|
||||
# 2020| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2020| Type = [Struct] TernaryNonPodObj
|
||||
# 2020| ValueCategory = lvalue
|
||||
# 2021| getStmt(3): [ExprStmt] ExprStmt
|
||||
# 2021| getExpr(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [FunctionCall] call to operator=
|
||||
# 2021| Type = [LValueReferenceType] TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier(): [VariableAccess] z
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConditionalExpr] ... ? ... : ...
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getCondition(): [VariableAccess] a
|
||||
# 2021| Type = [BoolType] bool
|
||||
# 2021| ValueCategory = prvalue(load)
|
||||
# 2021| getThen(): [VariableAccess] x
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getElse(): [VariableAccess] y
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0): [ConstructorCall] call to TernaryNonPodObj
|
||||
# 2021| Type = [VoidType] void
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getQualifier().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
|
||||
# 2021| Type = [LValueReferenceType] const TernaryNonPodObj &
|
||||
# 2021| ValueCategory = prvalue
|
||||
# 2021| getExpr(): [CStyleCast] (const TernaryNonPodObj)...
|
||||
# 2021| Conversion = [GlvalueConversion] glvalue conversion
|
||||
# 2021| Type = [SpecifiedType] const TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr(): [TemporaryObjectExpr] temporary object
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2021| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
|
||||
# 2021| Type = [Struct] TernaryNonPodObj
|
||||
# 2021| ValueCategory = lvalue
|
||||
# 2022| getStmt(4): [ReturnStmt] return ...
|
||||
# 2024| [TopLevelFunction] void CommaTestHelper(unsigned int)
|
||||
# 2024| <params>:
|
||||
# 2024| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
# 2024| Type = [IntType] unsigned int
|
||||
# 2026| [TopLevelFunction] unsigned int CommaTest(unsigned int)
|
||||
# 2026| <params>:
|
||||
# 2026| getParameter(0): [Parameter] x
|
||||
# 2026| Type = [IntType] unsigned int
|
||||
# 2026| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 2027| getStmt(0): [DeclStmt] declaration
|
||||
# 2027| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
|
||||
# 2027| Type = [IntType] unsigned int
|
||||
# 2028| getStmt(1): [ExprStmt] ExprStmt
|
||||
# 2028| getExpr(): [AssignExpr] ... = ...
|
||||
# 2028| Type = [IntType] unsigned int
|
||||
# 2028| ValueCategory = lvalue
|
||||
# 2028| getLValue(): [VariableAccess] y
|
||||
# 2028| Type = [IntType] unsigned int
|
||||
# 2028| ValueCategory = lvalue
|
||||
# 2028| getRValue(): [ConditionalExpr] ... ? ... : ...
|
||||
# 2028| Type = [IntType] unsigned int
|
||||
# 2028| ValueCategory = prvalue
|
||||
# 2028| getCondition(): [LTExpr] ... < ...
|
||||
# 2028| Type = [BoolType] bool
|
||||
# 2028| ValueCategory = prvalue
|
||||
# 2028| getLesserOperand(): [VariableAccess] x
|
||||
# 2028| Type = [IntType] unsigned int
|
||||
# 2028| ValueCategory = prvalue(load)
|
||||
# 2028| getGreaterOperand(): [Literal] 100
|
||||
# 2028| Type = [IntType] int
|
||||
# 2028| Value = [Literal] 100
|
||||
# 2028| ValueCategory = prvalue
|
||||
# 2028| getGreaterOperand().getFullyConverted(): [CStyleCast] (unsigned int)...
|
||||
# 2028| Conversion = [IntegralConversion] integral conversion
|
||||
# 2028| Type = [IntType] unsigned int
|
||||
# 2028| Value = [CStyleCast] 100
|
||||
# 2028| ValueCategory = prvalue
|
||||
# 2029| getThen(): [CommaExpr] ... , ...
|
||||
# 2029| Type = [IntType] unsigned int
|
||||
# 2029| ValueCategory = prvalue
|
||||
# 2029| getLeftOperand(): [FunctionCall] call to CommaTestHelper
|
||||
# 2029| Type = [VoidType] void
|
||||
# 2029| ValueCategory = prvalue
|
||||
# 2029| getArgument(0): [VariableAccess] x
|
||||
# 2029| Type = [IntType] unsigned int
|
||||
# 2029| ValueCategory = prvalue(load)
|
||||
# 2029| getRightOperand(): [VariableAccess] x
|
||||
# 2029| Type = [IntType] unsigned int
|
||||
# 2029| ValueCategory = prvalue(load)
|
||||
# 2030| getElse(): [CommaExpr] ... , ...
|
||||
# 2030| Type = [IntType] int
|
||||
# 2030| ValueCategory = prvalue
|
||||
# 2030| getLeftOperand(): [FunctionCall] call to CommaTestHelper
|
||||
# 2030| Type = [VoidType] void
|
||||
# 2030| ValueCategory = prvalue
|
||||
# 2030| getArgument(0): [VariableAccess] x
|
||||
# 2030| Type = [IntType] unsigned int
|
||||
# 2030| ValueCategory = prvalue(load)
|
||||
# 2030| getRightOperand(): [Literal] 10
|
||||
# 2030| Type = [IntType] int
|
||||
# 2030| Value = [Literal] 10
|
||||
# 2030| ValueCategory = prvalue
|
||||
# 2029| getThen().getFullyConverted(): [ParenthesisExpr] (...)
|
||||
# 2029| Type = [IntType] unsigned int
|
||||
# 2029| ValueCategory = prvalue
|
||||
# 2030| getElse().getFullyConverted(): [CStyleCast] (unsigned int)...
|
||||
# 2030| Conversion = [IntegralConversion] integral conversion
|
||||
# 2030| Type = [IntType] unsigned int
|
||||
# 2030| ValueCategory = prvalue
|
||||
# 2030| getExpr(): [ParenthesisExpr] (...)
|
||||
# 2030| Type = [IntType] int
|
||||
# 2030| ValueCategory = prvalue
|
||||
# 2031| getStmt(2): [ReturnStmt] return ...
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
@@ -15170,6 +15818,40 @@ struct_init.cpp:
|
||||
# 4| <params>:
|
||||
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
|
||||
#-----| Type = [RValueReferenceType] Info &&
|
||||
# 9| [GlobalVariable] Info infos_in_file[]
|
||||
# 9| getInitializer(): [Initializer] initializer for infos_in_file
|
||||
# 9| getExpr(): [ArrayAggregateLiteral] {...}
|
||||
# 9| Type = [ArrayType] Info[2]
|
||||
# 9| ValueCategory = prvalue
|
||||
# 10| getAnElementExpr(0): [ClassAggregateLiteral] {...}
|
||||
# 10| Type = [Struct] Info
|
||||
# 10| ValueCategory = prvalue
|
||||
# 10| getAFieldExpr(name): 1
|
||||
# 10| Type = [ArrayType] const char[2]
|
||||
# 10| Value = [StringLiteral] "1"
|
||||
# 10| ValueCategory = lvalue
|
||||
# 10| getAFieldExpr(handler): [FunctionAccess] handler1
|
||||
# 10| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 10| ValueCategory = prvalue(load)
|
||||
# 10| getAFieldExpr(name).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
|
||||
# 10| Type = [PointerType] const char *
|
||||
# 10| ValueCategory = prvalue
|
||||
# 11| getAnElementExpr(1): [ClassAggregateLiteral] {...}
|
||||
# 11| Type = [Struct] Info
|
||||
# 11| ValueCategory = prvalue
|
||||
# 11| getAFieldExpr(name): 3
|
||||
# 11| Type = [ArrayType] const char[2]
|
||||
# 11| Value = [StringLiteral] "3"
|
||||
# 11| ValueCategory = lvalue
|
||||
# 11| getAFieldExpr(handler): [AddressOfExpr] & ...
|
||||
# 11| Type = [FunctionPointerType] ..(*)(..)
|
||||
# 11| ValueCategory = prvalue
|
||||
# 11| getOperand(): [FunctionAccess] handler2
|
||||
# 11| Type = [RoutineType] ..()(..)
|
||||
# 11| ValueCategory = lvalue
|
||||
# 11| getAFieldExpr(name).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
|
||||
# 11| Type = [PointerType] const char *
|
||||
# 11| ValueCategory = prvalue
|
||||
# 16| [TopLevelFunction] void let_info_escape(Info*)
|
||||
# 16| <params>:
|
||||
# 16| getParameter(0): [Parameter] info
|
||||
|
||||
@@ -7,5 +7,5 @@ private import semmle.code.cpp.PrintAST
|
||||
private import PrintConfig
|
||||
|
||||
private class PrintConfig extends PrintAstConfiguration {
|
||||
override predicate shouldPrintFunction(Function func) { shouldDumpFunction(func) }
|
||||
override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) }
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ predicate locationIsInStandardHeaders(Location loc) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the AST or IR for the specified function should be printed in the test output.
|
||||
* Holds if the AST or IR for the specified declaration should be printed in the test output.
|
||||
*
|
||||
* This predicate excludes functions defined in standard headers.
|
||||
* This predicate excludes declarations defined in standard headers.
|
||||
*/
|
||||
predicate shouldDumpFunction(Declaration decl) {
|
||||
predicate shouldDumpDeclaration(Declaration decl) {
|
||||
not locationIsInStandardHeaders(decl.getLocation()) and
|
||||
(
|
||||
decl instanceof Function
|
||||
|
||||
11
cpp/ql/test/library-tests/ir/ir/ir.c
Normal file
11
cpp/ql/test/library-tests/ir/ir/ir.c
Normal file
@@ -0,0 +1,11 @@
|
||||
typedef struct {
|
||||
int x, y;
|
||||
} MyCoords;
|
||||
|
||||
int getX(MyCoords *coords);
|
||||
|
||||
void MyCoordsTest(int pos) {
|
||||
MyCoords coords = {0};
|
||||
coords.x = coords.y = pos + 1;
|
||||
coords.x = getX(&coords);
|
||||
}
|
||||
@@ -1993,4 +1993,41 @@ void SetStaticFuncPtr() {
|
||||
pfn = c.StaticMemberFunction;
|
||||
}
|
||||
|
||||
void TernaryTestInt(bool a, int x, int y, int z) {
|
||||
z = a ? x : y;
|
||||
z = a ? x : 5;
|
||||
z = a ? 3 : 5;
|
||||
(a ? x : y) = 7;
|
||||
}
|
||||
|
||||
struct TernaryPodObj {
|
||||
};
|
||||
|
||||
void TernaryTestPodObj(bool a, TernaryPodObj x, TernaryPodObj y, TernaryPodObj z) {
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryPodObj();
|
||||
z = a ? TernaryPodObj() : TernaryPodObj();
|
||||
(z = a ? x : y) = TernaryPodObj();
|
||||
}
|
||||
|
||||
struct TernaryNonPodObj {
|
||||
virtual ~TernaryNonPodObj() {}
|
||||
};
|
||||
|
||||
void TernaryTestNonPodObj(bool a, TernaryNonPodObj x, TernaryNonPodObj y, TernaryNonPodObj z) {
|
||||
z = a ? x : y;
|
||||
z = a ? x : TernaryNonPodObj();
|
||||
z = a ? TernaryNonPodObj() : TernaryNonPodObj();
|
||||
(z = a ? x : y) = TernaryNonPodObj();
|
||||
}
|
||||
|
||||
void CommaTestHelper(unsigned int);
|
||||
|
||||
unsigned int CommaTest(unsigned int x) {
|
||||
unsigned int y;
|
||||
y = x < 100 ?
|
||||
(CommaTestHelper(x), x) :
|
||||
(CommaTestHelper(x), 10);
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -680,6 +680,10 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_1 |
|
||||
| file://:0:0:0:0 | Address | &:r0_2 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
@@ -704,6 +708,10 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_3 |
|
||||
| file://:0:0:0:0 | Address | &:r0_4 |
|
||||
| file://:0:0:0:0 | Address | &:r0_4 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
@@ -715,6 +723,8 @@
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_5 |
|
||||
| file://:0:0:0:0 | Address | &:r0_6 |
|
||||
| file://:0:0:0:0 | Address | &:r0_6 |
|
||||
| file://:0:0:0:0 | Address | &:r0_7 |
|
||||
| file://:0:0:0:0 | Address | &:r0_7 |
|
||||
@@ -799,6 +809,8 @@
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_2 |
|
||||
| file://:0:0:0:0 | Load | m0_5 |
|
||||
| file://:0:0:0:0 | Load | m0_8 |
|
||||
| file://:0:0:0:0 | Load | m0_11 |
|
||||
@@ -814,6 +826,7 @@
|
||||
| file://:0:0:0:0 | Load | m1834_6 |
|
||||
| file://:0:0:0:0 | Load | m1834_6 |
|
||||
| file://:0:0:0:0 | Load | m1839_6 |
|
||||
| file://:0:0:0:0 | Load | m2013_6 |
|
||||
| file://:0:0:0:0 | Load | ~m0_4 |
|
||||
| file://:0:0:0:0 | Load | ~m1444_6 |
|
||||
| file://:0:0:0:0 | Load | ~m1712_10 |
|
||||
@@ -832,6 +845,8 @@
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_4 |
|
||||
| file://:0:0:0:0 | SideEffect | m0_14 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
| file://:0:0:0:0 | SideEffect | m1078_23 |
|
||||
@@ -869,6 +884,7 @@
|
||||
| file://:0:0:0:0 | StoreValue | r0_7 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_9 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_9 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_9 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_12 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_12 |
|
||||
| file://:0:0:0:0 | StoreValue | r0_13 |
|
||||
@@ -895,6 +911,8 @@
|
||||
| file://:0:0:0:0 | Unary | r0_7 |
|
||||
| file://:0:0:0:0 | Unary | r0_7 |
|
||||
| file://:0:0:0:0 | Unary | r0_7 |
|
||||
| file://:0:0:0:0 | Unary | r0_7 |
|
||||
| file://:0:0:0:0 | Unary | r0_8 |
|
||||
| file://:0:0:0:0 | Unary | r0_8 |
|
||||
| file://:0:0:0:0 | Unary | r0_9 |
|
||||
| file://:0:0:0:0 | Unary | r0_9 |
|
||||
@@ -914,6 +932,52 @@
|
||||
| file://:0:0:0:0 | Unary | r0_20 |
|
||||
| file://:0:0:0:0 | Unary | r0_21 |
|
||||
| file://:0:0:0:0 | Unary | r0_21 |
|
||||
| ir.c:7:6:7:17 | ChiPartial | partial:m7_3 |
|
||||
| ir.c:7:6:7:17 | ChiTotal | total:m7_2 |
|
||||
| ir.c:7:6:7:17 | SideEffect | ~m10_6 |
|
||||
| ir.c:7:23:7:25 | Address | &:r7_5 |
|
||||
| ir.c:8:12:8:17 | Address | &:r8_1 |
|
||||
| ir.c:8:12:8:17 | Unary | r8_1 |
|
||||
| ir.c:8:12:8:17 | Unary | r8_1 |
|
||||
| ir.c:8:20:8:23 | Address | &:r8_3 |
|
||||
| ir.c:8:20:8:23 | Address | &:r8_7 |
|
||||
| ir.c:8:20:8:23 | ChiPartial | partial:m8_9 |
|
||||
| ir.c:8:20:8:23 | ChiTotal | total:m8_6 |
|
||||
| ir.c:8:20:8:23 | StoreValue | r8_8 |
|
||||
| ir.c:8:22:8:22 | ChiPartial | partial:m8_5 |
|
||||
| ir.c:8:22:8:22 | ChiTotal | total:m8_2 |
|
||||
| ir.c:8:22:8:22 | StoreValue | r8_4 |
|
||||
| ir.c:9:3:9:8 | Unary | r9_10 |
|
||||
| ir.c:9:3:9:31 | ChiPartial | partial:m9_12 |
|
||||
| ir.c:9:3:9:31 | ChiTotal | total:m9_8 |
|
||||
| ir.c:9:10:9:10 | Address | &:r9_11 |
|
||||
| ir.c:9:14:9:19 | Unary | r9_5 |
|
||||
| ir.c:9:14:9:31 | ChiPartial | partial:m9_7 |
|
||||
| ir.c:9:14:9:31 | ChiTotal | total:m8_10 |
|
||||
| ir.c:9:14:9:31 | StoreValue | r9_9 |
|
||||
| ir.c:9:21:9:21 | Address | &:r9_6 |
|
||||
| ir.c:9:25:9:27 | Address | &:r9_1 |
|
||||
| ir.c:9:25:9:27 | Left | r9_2 |
|
||||
| ir.c:9:25:9:27 | Load | m7_6 |
|
||||
| ir.c:9:25:9:31 | StoreValue | r9_4 |
|
||||
| ir.c:9:25:9:31 | Unary | r9_4 |
|
||||
| ir.c:9:31:9:31 | Right | r9_3 |
|
||||
| ir.c:10:3:10:8 | Unary | r10_10 |
|
||||
| ir.c:10:3:10:26 | ChiPartial | partial:m10_12 |
|
||||
| ir.c:10:3:10:26 | ChiTotal | total:m10_9 |
|
||||
| ir.c:10:10:10:10 | Address | &:r10_11 |
|
||||
| ir.c:10:14:10:17 | CallTarget | func:r10_1 |
|
||||
| ir.c:10:14:10:17 | ChiPartial | partial:m10_5 |
|
||||
| ir.c:10:14:10:17 | ChiTotal | total:m7_4 |
|
||||
| ir.c:10:14:10:17 | SideEffect | ~m7_4 |
|
||||
| ir.c:10:14:10:17 | StoreValue | r10_4 |
|
||||
| ir.c:10:19:10:25 | Address | &:r10_3 |
|
||||
| ir.c:10:19:10:25 | Address | &:r10_3 |
|
||||
| ir.c:10:19:10:25 | Arg(0) | 0:r10_3 |
|
||||
| ir.c:10:19:10:25 | ChiPartial | partial:m10_8 |
|
||||
| ir.c:10:19:10:25 | ChiTotal | total:m9_13 |
|
||||
| ir.c:10:19:10:25 | SideEffect | ~m9_13 |
|
||||
| ir.c:10:20:10:25 | Unary | r10_2 |
|
||||
| ir.cpp:1:6:1:14 | ChiPartial | partial:m1_3 |
|
||||
| ir.cpp:1:6:1:14 | ChiTotal | total:m1_2 |
|
||||
| ir.cpp:1:6:1:14 | SideEffect | m1_3 |
|
||||
@@ -9058,6 +9122,446 @@
|
||||
| ir.cpp:1992:23:1992:45 | StoreValue | r1992_2 |
|
||||
| ir.cpp:1993:5:1993:7 | Address | &:r1993_3 |
|
||||
| ir.cpp:1993:13:1993:32 | StoreValue | r1993_2 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiPartial | partial:m1996_3 |
|
||||
| ir.cpp:1996:6:1996:19 | ChiTotal | total:m1996_2 |
|
||||
| ir.cpp:1996:6:1996:19 | SideEffect | ~m2000_9 |
|
||||
| ir.cpp:1996:26:1996:26 | Address | &:r1996_5 |
|
||||
| ir.cpp:1996:33:1996:33 | Address | &:r1996_7 |
|
||||
| ir.cpp:1996:40:1996:40 | Address | &:r1996_9 |
|
||||
| ir.cpp:1996:47:1996:47 | Address | &:r1996_11 |
|
||||
| ir.cpp:1997:5:1997:5 | Address | &:r1997_7 |
|
||||
| ir.cpp:1997:9:1997:9 | Address | &:r1997_1 |
|
||||
| ir.cpp:1997:9:1997:9 | Condition | r1997_2 |
|
||||
| ir.cpp:1997:9:1997:9 | Load | m1996_6 |
|
||||
| ir.cpp:1997:9:1997:17 | Address | &:r1997_5 |
|
||||
| ir.cpp:1997:9:1997:17 | Address | &:r1997_11 |
|
||||
| ir.cpp:1997:9:1997:17 | Address | &:r1997_15 |
|
||||
| ir.cpp:1997:9:1997:17 | Load | m1997_4 |
|
||||
| ir.cpp:1997:9:1997:17 | Phi | from 2:m1997_12 |
|
||||
| ir.cpp:1997:9:1997:17 | Phi | from 3:m1997_16 |
|
||||
| ir.cpp:1997:9:1997:17 | StoreValue | r1997_6 |
|
||||
| ir.cpp:1997:13:1997:13 | Address | &:r1997_9 |
|
||||
| ir.cpp:1997:13:1997:13 | Load | m1996_8 |
|
||||
| ir.cpp:1997:13:1997:13 | StoreValue | r1997_10 |
|
||||
| ir.cpp:1997:17:1997:17 | Address | &:r1997_13 |
|
||||
| ir.cpp:1997:17:1997:17 | Load | m1996_10 |
|
||||
| ir.cpp:1997:17:1997:17 | StoreValue | r1997_14 |
|
||||
| ir.cpp:1998:5:1998:5 | Address | &:r1998_7 |
|
||||
| ir.cpp:1998:9:1998:9 | Address | &:r1998_1 |
|
||||
| ir.cpp:1998:9:1998:9 | Condition | r1998_2 |
|
||||
| ir.cpp:1998:9:1998:9 | Load | m1996_6 |
|
||||
| ir.cpp:1998:9:1998:17 | Address | &:r1998_5 |
|
||||
| ir.cpp:1998:9:1998:17 | Address | &:r1998_11 |
|
||||
| ir.cpp:1998:9:1998:17 | Address | &:r1998_14 |
|
||||
| ir.cpp:1998:9:1998:17 | Load | m1998_4 |
|
||||
| ir.cpp:1998:9:1998:17 | Phi | from 5:m1998_12 |
|
||||
| ir.cpp:1998:9:1998:17 | Phi | from 6:m1998_15 |
|
||||
| ir.cpp:1998:9:1998:17 | StoreValue | r1998_6 |
|
||||
| ir.cpp:1998:13:1998:13 | Address | &:r1998_9 |
|
||||
| ir.cpp:1998:13:1998:13 | Load | m1996_8 |
|
||||
| ir.cpp:1998:13:1998:13 | StoreValue | r1998_10 |
|
||||
| ir.cpp:1998:17:1998:17 | StoreValue | r1998_13 |
|
||||
| ir.cpp:1999:5:1999:5 | Address | &:r1999_7 |
|
||||
| ir.cpp:1999:9:1999:9 | Address | &:r1999_1 |
|
||||
| ir.cpp:1999:9:1999:9 | Condition | r1999_2 |
|
||||
| ir.cpp:1999:9:1999:9 | Load | m1996_6 |
|
||||
| ir.cpp:1999:9:1999:17 | Address | &:r1999_5 |
|
||||
| ir.cpp:1999:9:1999:17 | Address | &:r1999_10 |
|
||||
| ir.cpp:1999:9:1999:17 | Address | &:r1999_13 |
|
||||
| ir.cpp:1999:9:1999:17 | Load | m1999_4 |
|
||||
| ir.cpp:1999:9:1999:17 | Phi | from 8:m1999_11 |
|
||||
| ir.cpp:1999:9:1999:17 | Phi | from 9:m1999_14 |
|
||||
| ir.cpp:1999:9:1999:17 | StoreValue | r1999_6 |
|
||||
| ir.cpp:1999:13:1999:13 | StoreValue | r1999_9 |
|
||||
| ir.cpp:1999:17:1999:17 | StoreValue | r1999_12 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiPartial | partial:m2000_8 |
|
||||
| ir.cpp:2000:5:2000:19 | ChiTotal | total:m1996_4 |
|
||||
| ir.cpp:2000:6:2000:6 | Address | &:r2000_2 |
|
||||
| ir.cpp:2000:6:2000:6 | Condition | r2000_3 |
|
||||
| ir.cpp:2000:6:2000:6 | Load | m1996_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_6 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_7 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_11 |
|
||||
| ir.cpp:2000:6:2000:14 | Address | &:r2000_14 |
|
||||
| ir.cpp:2000:6:2000:14 | Load | m2000_5 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 11:m2000_12 |
|
||||
| ir.cpp:2000:6:2000:14 | Phi | from 12:m2000_15 |
|
||||
| ir.cpp:2000:10:2000:10 | StoreValue | r2000_10 |
|
||||
| ir.cpp:2000:14:2000:14 | StoreValue | r2000_13 |
|
||||
| ir.cpp:2000:19:2000:19 | StoreValue | r2000_1 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiPartial | partial:m2006_3 |
|
||||
| ir.cpp:2006:6:2006:22 | ChiTotal | total:m2006_2 |
|
||||
| ir.cpp:2006:6:2006:22 | SideEffect | m2006_3 |
|
||||
| ir.cpp:2006:29:2006:29 | Address | &:r2006_5 |
|
||||
| ir.cpp:2006:46:2006:46 | Address | &:r2006_7 |
|
||||
| ir.cpp:2006:63:2006:63 | Address | &:r2006_9 |
|
||||
| ir.cpp:2006:80:2006:80 | Address | &:r2006_11 |
|
||||
| ir.cpp:2007:5:2007:5 | Address | &:r2007_7 |
|
||||
| ir.cpp:2007:9:2007:9 | Address | &:r2007_1 |
|
||||
| ir.cpp:2007:9:2007:9 | Condition | r2007_2 |
|
||||
| ir.cpp:2007:9:2007:9 | Load | m2006_6 |
|
||||
| ir.cpp:2007:9:2007:17 | Address | &:r2007_5 |
|
||||
| ir.cpp:2007:9:2007:17 | Address | &:r2007_11 |
|
||||
| ir.cpp:2007:9:2007:17 | Address | &:r2007_15 |
|
||||
| ir.cpp:2007:9:2007:17 | Load | m2007_4 |
|
||||
| ir.cpp:2007:9:2007:17 | Phi | from 2:m2007_12 |
|
||||
| ir.cpp:2007:9:2007:17 | Phi | from 3:m2007_16 |
|
||||
| ir.cpp:2007:9:2007:17 | StoreValue | r2007_6 |
|
||||
| ir.cpp:2007:13:2007:13 | Address | &:r2007_9 |
|
||||
| ir.cpp:2007:13:2007:13 | Load | m2006_8 |
|
||||
| ir.cpp:2007:13:2007:13 | StoreValue | r2007_10 |
|
||||
| ir.cpp:2007:17:2007:17 | Address | &:r2007_13 |
|
||||
| ir.cpp:2007:17:2007:17 | Load | m2006_10 |
|
||||
| ir.cpp:2007:17:2007:17 | StoreValue | r2007_14 |
|
||||
| ir.cpp:2008:5:2008:5 | Address | &:r2008_10 |
|
||||
| ir.cpp:2008:9:2008:9 | Address | &:r2008_2 |
|
||||
| ir.cpp:2008:9:2008:9 | Address | &:r2008_6 |
|
||||
| ir.cpp:2008:9:2008:9 | Address | &:r2008_17 |
|
||||
| ir.cpp:2008:9:2008:9 | Address | &:r2008_23 |
|
||||
| ir.cpp:2008:9:2008:9 | Condition | r2008_3 |
|
||||
| ir.cpp:2008:9:2008:9 | Load | m2006_6 |
|
||||
| ir.cpp:2008:9:2008:9 | Load | m2008_5 |
|
||||
| ir.cpp:2008:9:2008:9 | Phi | from 5:m2008_18 |
|
||||
| ir.cpp:2008:9:2008:9 | Phi | from 6:m2008_24 |
|
||||
| ir.cpp:2008:9:2008:9 | StoreValue | r2008_7 |
|
||||
| ir.cpp:2008:9:2008:31 | Address | &:r2008_1 |
|
||||
| ir.cpp:2008:9:2008:31 | Address | &:r2008_1 |
|
||||
| ir.cpp:2008:9:2008:31 | Load | m2008_8 |
|
||||
| ir.cpp:2008:9:2008:31 | StoreValue | r2008_9 |
|
||||
| ir.cpp:2008:13:2008:13 | Address | &:r2008_12 |
|
||||
| ir.cpp:2008:13:2008:13 | Address | &:r2008_12 |
|
||||
| ir.cpp:2008:13:2008:13 | Address | &:r2008_13 |
|
||||
| ir.cpp:2008:13:2008:13 | Load | m2006_8 |
|
||||
| ir.cpp:2008:13:2008:13 | Load | m2008_15 |
|
||||
| ir.cpp:2008:13:2008:13 | StoreValue | r2008_14 |
|
||||
| ir.cpp:2008:13:2008:13 | StoreValue | r2008_16 |
|
||||
| ir.cpp:2008:17:2008:31 | Address | &:r2008_19 |
|
||||
| ir.cpp:2008:17:2008:31 | Address | &:r2008_19 |
|
||||
| ir.cpp:2008:17:2008:31 | Load | m2008_21 |
|
||||
| ir.cpp:2008:17:2008:31 | StoreValue | r2008_20 |
|
||||
| ir.cpp:2008:17:2008:31 | StoreValue | r2008_22 |
|
||||
| ir.cpp:2009:5:2009:5 | Address | &:r2009_10 |
|
||||
| ir.cpp:2009:9:2009:9 | Address | &:r2009_2 |
|
||||
| ir.cpp:2009:9:2009:9 | Address | &:r2009_6 |
|
||||
| ir.cpp:2009:9:2009:9 | Address | &:r2009_16 |
|
||||
| ir.cpp:2009:9:2009:9 | Address | &:r2009_22 |
|
||||
| ir.cpp:2009:9:2009:9 | Condition | r2009_3 |
|
||||
| ir.cpp:2009:9:2009:9 | Load | m2006_6 |
|
||||
| ir.cpp:2009:9:2009:9 | Load | m2009_5 |
|
||||
| ir.cpp:2009:9:2009:9 | Phi | from 8:m2009_17 |
|
||||
| ir.cpp:2009:9:2009:9 | Phi | from 9:m2009_23 |
|
||||
| ir.cpp:2009:9:2009:9 | StoreValue | r2009_7 |
|
||||
| ir.cpp:2009:9:2009:45 | Address | &:r2009_1 |
|
||||
| ir.cpp:2009:9:2009:45 | Address | &:r2009_1 |
|
||||
| ir.cpp:2009:9:2009:45 | Load | m2009_8 |
|
||||
| ir.cpp:2009:9:2009:45 | StoreValue | r2009_9 |
|
||||
| ir.cpp:2009:13:2009:27 | Address | &:r2009_12 |
|
||||
| ir.cpp:2009:13:2009:27 | Address | &:r2009_12 |
|
||||
| ir.cpp:2009:13:2009:27 | Load | m2009_14 |
|
||||
| ir.cpp:2009:13:2009:27 | StoreValue | r2009_13 |
|
||||
| ir.cpp:2009:13:2009:27 | StoreValue | r2009_15 |
|
||||
| ir.cpp:2009:31:2009:45 | Address | &:r2009_18 |
|
||||
| ir.cpp:2009:31:2009:45 | Address | &:r2009_18 |
|
||||
| ir.cpp:2009:31:2009:45 | Load | m2009_20 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_19 |
|
||||
| ir.cpp:2009:31:2009:45 | StoreValue | r2009_21 |
|
||||
| ir.cpp:2010:6:2010:6 | Address | &:r2010_11 |
|
||||
| ir.cpp:2010:6:2010:6 | Unary | r2010_11 |
|
||||
| ir.cpp:2010:6:2010:18 | Address | &:r2010_13 |
|
||||
| ir.cpp:2010:10:2010:10 | Address | &:r2010_5 |
|
||||
| ir.cpp:2010:10:2010:10 | Condition | r2010_6 |
|
||||
| ir.cpp:2010:10:2010:10 | Load | m2006_6 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_9 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_17 |
|
||||
| ir.cpp:2010:10:2010:18 | Address | &:r2010_21 |
|
||||
| ir.cpp:2010:10:2010:18 | Load | m2010_8 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 11:m2010_18 |
|
||||
| ir.cpp:2010:10:2010:18 | Phi | from 12:m2010_22 |
|
||||
| ir.cpp:2010:10:2010:18 | StoreValue | r2010_10 |
|
||||
| ir.cpp:2010:14:2010:14 | Address | &:r2010_15 |
|
||||
| ir.cpp:2010:14:2010:14 | Load | m2006_8 |
|
||||
| ir.cpp:2010:14:2010:14 | StoreValue | r2010_16 |
|
||||
| ir.cpp:2010:18:2010:18 | Address | &:r2010_19 |
|
||||
| ir.cpp:2010:18:2010:18 | Load | m2006_10 |
|
||||
| ir.cpp:2010:18:2010:18 | StoreValue | r2010_20 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Address | &:r2010_1 |
|
||||
| ir.cpp:2010:23:2010:37 | Load | m2010_3 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_2 |
|
||||
| ir.cpp:2010:23:2010:37 | StoreValue | r2010_4 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_5 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_7 |
|
||||
| ir.cpp:2013:8:2013:8 | Address | &:r2013_10 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiPartial | partial:m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiPartial | partial:m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiPartial | partial:m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiTotal | total:m2013_2 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiTotal | total:m2013_2 |
|
||||
| ir.cpp:2013:8:2013:8 | ChiTotal | total:m2013_2 |
|
||||
| ir.cpp:2013:8:2013:8 | Load | m0_10 |
|
||||
| ir.cpp:2013:8:2013:8 | Load | m2013_6 |
|
||||
| ir.cpp:2013:8:2013:8 | Load | m2013_6 |
|
||||
| ir.cpp:2013:8:2013:8 | Load | m2013_6 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_3 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_8 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_8 |
|
||||
| ir.cpp:2013:8:2013:8 | SideEffect | m2013_8 |
|
||||
| ir.cpp:2014:13:2014:29 | Address | &:r2014_5 |
|
||||
| ir.cpp:2014:13:2014:29 | Address | &:r2014_5 |
|
||||
| ir.cpp:2014:13:2014:29 | Address | &:r2014_7 |
|
||||
| ir.cpp:2014:13:2014:29 | Address | &:r2014_7 |
|
||||
| ir.cpp:2014:13:2014:29 | ChiPartial | partial:m2014_3 |
|
||||
| ir.cpp:2014:13:2014:29 | ChiTotal | total:m2014_2 |
|
||||
| ir.cpp:2014:13:2014:29 | Load | m2014_6 |
|
||||
| ir.cpp:2014:13:2014:29 | SideEffect | m2014_3 |
|
||||
| ir.cpp:2014:13:2014:29 | SideEffect | m2014_8 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiPartial | partial:m2017_3 |
|
||||
| ir.cpp:2017:6:2017:25 | ChiTotal | total:m2017_2 |
|
||||
| ir.cpp:2017:6:2017:25 | SideEffect | ~m2021_32 |
|
||||
| ir.cpp:2017:32:2017:32 | Address | &:r2017_5 |
|
||||
| ir.cpp:2017:52:2017:52 | Address | &:r2017_7 |
|
||||
| ir.cpp:2017:72:2017:72 | Address | &:r2017_9 |
|
||||
| ir.cpp:2017:92:2017:92 | Address | &:r2017_11 |
|
||||
| ir.cpp:2018:5:2018:5 | Address | &:r2018_1 |
|
||||
| ir.cpp:2018:5:2018:5 | Address | &:r2018_1 |
|
||||
| ir.cpp:2018:5:2018:5 | Arg(this) | this:r2018_1 |
|
||||
| ir.cpp:2018:5:2018:5 | ChiPartial | partial:m2018_16 |
|
||||
| ir.cpp:2018:5:2018:5 | ChiTotal | total:m2017_12 |
|
||||
| ir.cpp:2018:5:2018:5 | SideEffect | m2017_12 |
|
||||
| ir.cpp:2018:7:2018:7 | CallTarget | func:r2018_2 |
|
||||
| ir.cpp:2018:7:2018:7 | ChiPartial | partial:m2018_12 |
|
||||
| ir.cpp:2018:7:2018:7 | ChiTotal | total:m2017_4 |
|
||||
| ir.cpp:2018:7:2018:7 | SideEffect | ~m2017_4 |
|
||||
| ir.cpp:2018:7:2018:7 | Unary | r2018_11 |
|
||||
| ir.cpp:2018:9:2018:9 | Address | &:r2018_3 |
|
||||
| ir.cpp:2018:9:2018:9 | Condition | r2018_4 |
|
||||
| ir.cpp:2018:9:2018:9 | Load | m2017_6 |
|
||||
| ir.cpp:2018:9:2018:17 | Address | &:r2018_7 |
|
||||
| ir.cpp:2018:9:2018:17 | Address | &:r2018_10 |
|
||||
| ir.cpp:2018:9:2018:17 | Address | &:r2018_20 |
|
||||
| ir.cpp:2018:9:2018:17 | Address | &:r2018_23 |
|
||||
| ir.cpp:2018:9:2018:17 | Arg(0) | 0:r2018_10 |
|
||||
| ir.cpp:2018:9:2018:17 | Load | m2018_6 |
|
||||
| ir.cpp:2018:9:2018:17 | Phi | from 2:m2018_21 |
|
||||
| ir.cpp:2018:9:2018:17 | Phi | from 3:m2018_24 |
|
||||
| ir.cpp:2018:9:2018:17 | SideEffect | ~m2018_13 |
|
||||
| ir.cpp:2018:9:2018:17 | Unary | r2018_8 |
|
||||
| ir.cpp:2018:9:2018:17 | Unary | r2018_9 |
|
||||
| ir.cpp:2018:13:2018:13 | StoreValue | r2018_19 |
|
||||
| ir.cpp:2018:17:2018:17 | StoreValue | r2018_22 |
|
||||
| ir.cpp:2019:5:2019:5 | Address | &:r2019_1 |
|
||||
| ir.cpp:2019:5:2019:5 | Address | &:r2019_1 |
|
||||
| ir.cpp:2019:5:2019:5 | Arg(this) | this:r2019_1 |
|
||||
| ir.cpp:2019:5:2019:5 | ChiPartial | partial:m2019_19 |
|
||||
| ir.cpp:2019:5:2019:5 | ChiTotal | total:m2018_17 |
|
||||
| ir.cpp:2019:5:2019:5 | SideEffect | m2018_17 |
|
||||
| ir.cpp:2019:7:2019:7 | CallTarget | func:r2019_2 |
|
||||
| ir.cpp:2019:7:2019:7 | ChiPartial | partial:m2019_15 |
|
||||
| ir.cpp:2019:7:2019:7 | ChiTotal | total:m2019_7 |
|
||||
| ir.cpp:2019:7:2019:7 | SideEffect | ~m2019_7 |
|
||||
| ir.cpp:2019:7:2019:7 | Unary | r2019_14 |
|
||||
| ir.cpp:2019:9:2019:9 | Address | &:r2019_4 |
|
||||
| ir.cpp:2019:9:2019:9 | Address | &:r2019_9 |
|
||||
| ir.cpp:2019:9:2019:9 | Address | &:r2019_35 |
|
||||
| ir.cpp:2019:9:2019:9 | Address | &:r2019_46 |
|
||||
| ir.cpp:2019:9:2019:9 | Condition | r2019_5 |
|
||||
| ir.cpp:2019:9:2019:9 | Load | m2017_6 |
|
||||
| ir.cpp:2019:9:2019:9 | Load | m2019_8 |
|
||||
| ir.cpp:2019:9:2019:9 | Phi | from 5:m2019_36 |
|
||||
| ir.cpp:2019:9:2019:9 | Phi | from 5:~m2019_30 |
|
||||
| ir.cpp:2019:9:2019:9 | Phi | from 6:m2019_47 |
|
||||
| ir.cpp:2019:9:2019:9 | Phi | from 6:~m2019_42 |
|
||||
| ir.cpp:2019:9:2019:9 | StoreValue | r2019_10 |
|
||||
| ir.cpp:2019:9:2019:34 | Address | &:r2019_3 |
|
||||
| ir.cpp:2019:9:2019:34 | Address | &:r2019_13 |
|
||||
| ir.cpp:2019:9:2019:34 | Arg(0) | 0:r2019_13 |
|
||||
| ir.cpp:2019:9:2019:34 | SideEffect | ~m2019_11 |
|
||||
| ir.cpp:2019:9:2019:34 | Unary | r2019_3 |
|
||||
| ir.cpp:2019:9:2019:34 | Unary | r2019_12 |
|
||||
| ir.cpp:2019:13:2019:13 | Address | &:r2019_22 |
|
||||
| ir.cpp:2019:13:2019:13 | Address | &:r2019_22 |
|
||||
| ir.cpp:2019:13:2019:13 | Address | &:r2019_22 |
|
||||
| ir.cpp:2019:13:2019:13 | Address | &:r2019_27 |
|
||||
| ir.cpp:2019:13:2019:13 | Arg(0) | 0:r2019_27 |
|
||||
| ir.cpp:2019:13:2019:13 | Arg(this) | this:r2019_22 |
|
||||
| ir.cpp:2019:13:2019:13 | CallTarget | func:r2019_24 |
|
||||
| ir.cpp:2019:13:2019:13 | ChiPartial | partial:m2019_29 |
|
||||
| ir.cpp:2019:13:2019:13 | ChiPartial | partial:m2019_32 |
|
||||
| ir.cpp:2019:13:2019:13 | ChiTotal | total:m2018_13 |
|
||||
| ir.cpp:2019:13:2019:13 | ChiTotal | total:m2019_23 |
|
||||
| ir.cpp:2019:13:2019:13 | Load | m2019_33 |
|
||||
| ir.cpp:2019:13:2019:13 | SideEffect | ~m2017_8 |
|
||||
| ir.cpp:2019:13:2019:13 | SideEffect | ~m2018_13 |
|
||||
| ir.cpp:2019:13:2019:13 | StoreValue | r2019_34 |
|
||||
| ir.cpp:2019:13:2019:13 | Unary | r2019_25 |
|
||||
| ir.cpp:2019:13:2019:13 | Unary | r2019_26 |
|
||||
| ir.cpp:2019:17:2019:34 | Address | &:r2019_37 |
|
||||
| ir.cpp:2019:17:2019:34 | Address | &:r2019_37 |
|
||||
| ir.cpp:2019:17:2019:34 | Address | &:r2019_37 |
|
||||
| ir.cpp:2019:17:2019:34 | Arg(this) | this:r2019_37 |
|
||||
| ir.cpp:2019:17:2019:34 | CallTarget | func:r2019_39 |
|
||||
| ir.cpp:2019:17:2019:34 | ChiPartial | partial:m2019_41 |
|
||||
| ir.cpp:2019:17:2019:34 | ChiPartial | partial:m2019_43 |
|
||||
| ir.cpp:2019:17:2019:34 | ChiTotal | total:m2018_13 |
|
||||
| ir.cpp:2019:17:2019:34 | ChiTotal | total:m2019_38 |
|
||||
| ir.cpp:2019:17:2019:34 | Load | m2019_44 |
|
||||
| ir.cpp:2019:17:2019:34 | SideEffect | ~m2018_13 |
|
||||
| ir.cpp:2019:17:2019:34 | StoreValue | r2019_45 |
|
||||
| ir.cpp:2020:5:2020:5 | Address | &:r2020_1 |
|
||||
| ir.cpp:2020:5:2020:5 | Address | &:r2020_1 |
|
||||
| ir.cpp:2020:5:2020:5 | Arg(this) | this:r2020_1 |
|
||||
| ir.cpp:2020:5:2020:5 | ChiPartial | partial:m2020_19 |
|
||||
| ir.cpp:2020:5:2020:5 | ChiTotal | total:m2019_20 |
|
||||
| ir.cpp:2020:5:2020:5 | SideEffect | m2019_20 |
|
||||
| ir.cpp:2020:7:2020:7 | CallTarget | func:r2020_2 |
|
||||
| ir.cpp:2020:7:2020:7 | ChiPartial | partial:m2020_15 |
|
||||
| ir.cpp:2020:7:2020:7 | ChiTotal | total:m2020_7 |
|
||||
| ir.cpp:2020:7:2020:7 | SideEffect | ~m2020_7 |
|
||||
| ir.cpp:2020:7:2020:7 | Unary | r2020_14 |
|
||||
| ir.cpp:2020:9:2020:9 | Address | &:r2020_4 |
|
||||
| ir.cpp:2020:9:2020:9 | Address | &:r2020_9 |
|
||||
| ir.cpp:2020:9:2020:9 | Address | &:r2020_31 |
|
||||
| ir.cpp:2020:9:2020:9 | Address | &:r2020_42 |
|
||||
| ir.cpp:2020:9:2020:9 | Condition | r2020_5 |
|
||||
| ir.cpp:2020:9:2020:9 | Load | m2017_6 |
|
||||
| ir.cpp:2020:9:2020:9 | Load | m2020_8 |
|
||||
| ir.cpp:2020:9:2020:9 | Phi | from 8:m2020_32 |
|
||||
| ir.cpp:2020:9:2020:9 | Phi | from 8:~m2020_27 |
|
||||
| ir.cpp:2020:9:2020:9 | Phi | from 9:m2020_43 |
|
||||
| ir.cpp:2020:9:2020:9 | Phi | from 9:~m2020_38 |
|
||||
| ir.cpp:2020:9:2020:9 | StoreValue | r2020_10 |
|
||||
| ir.cpp:2020:9:2020:51 | Address | &:r2020_3 |
|
||||
| ir.cpp:2020:9:2020:51 | Address | &:r2020_13 |
|
||||
| ir.cpp:2020:9:2020:51 | Arg(0) | 0:r2020_13 |
|
||||
| ir.cpp:2020:9:2020:51 | SideEffect | ~m2020_11 |
|
||||
| ir.cpp:2020:9:2020:51 | Unary | r2020_3 |
|
||||
| ir.cpp:2020:9:2020:51 | Unary | r2020_12 |
|
||||
| ir.cpp:2020:13:2020:30 | Address | &:r2020_22 |
|
||||
| ir.cpp:2020:13:2020:30 | Address | &:r2020_22 |
|
||||
| ir.cpp:2020:13:2020:30 | Address | &:r2020_22 |
|
||||
| ir.cpp:2020:13:2020:30 | Arg(this) | this:r2020_22 |
|
||||
| ir.cpp:2020:13:2020:30 | CallTarget | func:r2020_24 |
|
||||
| ir.cpp:2020:13:2020:30 | ChiPartial | partial:m2020_26 |
|
||||
| ir.cpp:2020:13:2020:30 | ChiPartial | partial:m2020_28 |
|
||||
| ir.cpp:2020:13:2020:30 | ChiTotal | total:m2019_16 |
|
||||
| ir.cpp:2020:13:2020:30 | ChiTotal | total:m2020_23 |
|
||||
| ir.cpp:2020:13:2020:30 | Load | m2020_29 |
|
||||
| ir.cpp:2020:13:2020:30 | SideEffect | ~m2019_16 |
|
||||
| ir.cpp:2020:13:2020:30 | StoreValue | r2020_30 |
|
||||
| ir.cpp:2020:34:2020:51 | Address | &:r2020_33 |
|
||||
| ir.cpp:2020:34:2020:51 | Address | &:r2020_33 |
|
||||
| ir.cpp:2020:34:2020:51 | Address | &:r2020_33 |
|
||||
| ir.cpp:2020:34:2020:51 | Arg(this) | this:r2020_33 |
|
||||
| ir.cpp:2020:34:2020:51 | CallTarget | func:r2020_35 |
|
||||
| ir.cpp:2020:34:2020:51 | ChiPartial | partial:m2020_37 |
|
||||
| ir.cpp:2020:34:2020:51 | ChiPartial | partial:m2020_39 |
|
||||
| ir.cpp:2020:34:2020:51 | ChiTotal | total:m2019_16 |
|
||||
| ir.cpp:2020:34:2020:51 | ChiTotal | total:m2020_34 |
|
||||
| ir.cpp:2020:34:2020:51 | Load | m2020_40 |
|
||||
| ir.cpp:2020:34:2020:51 | SideEffect | ~m2019_16 |
|
||||
| ir.cpp:2020:34:2020:51 | StoreValue | r2020_41 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiPartial | partial:m2021_35 |
|
||||
| ir.cpp:2021:5:2021:19 | ChiTotal | total:m2021_17 |
|
||||
| ir.cpp:2021:5:2021:19 | SideEffect | m2021_17 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Address | &:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | Arg(this) | this:r2021_1 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiPartial | partial:m2021_16 |
|
||||
| ir.cpp:2021:6:2021:6 | ChiTotal | total:m2020_20 |
|
||||
| ir.cpp:2021:6:2021:6 | SideEffect | m2020_20 |
|
||||
| ir.cpp:2021:8:2021:8 | CallTarget | func:r2021_2 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiPartial | partial:m2021_12 |
|
||||
| ir.cpp:2021:8:2021:8 | ChiTotal | total:m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | SideEffect | ~m2020_16 |
|
||||
| ir.cpp:2021:8:2021:8 | Unary | r2021_11 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Address | &:r2021_18 |
|
||||
| ir.cpp:2021:8:2021:19 | Arg(this) | this:r2021_18 |
|
||||
| ir.cpp:2021:10:2021:10 | Address | &:r2021_3 |
|
||||
| ir.cpp:2021:10:2021:10 | Condition | r2021_4 |
|
||||
| ir.cpp:2021:10:2021:10 | Load | m2017_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_7 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_39 |
|
||||
| ir.cpp:2021:10:2021:18 | Address | &:r2021_42 |
|
||||
| ir.cpp:2021:10:2021:18 | Arg(0) | 0:r2021_10 |
|
||||
| ir.cpp:2021:10:2021:18 | Load | m2021_6 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 11:m2021_40 |
|
||||
| ir.cpp:2021:10:2021:18 | Phi | from 12:m2021_43 |
|
||||
| ir.cpp:2021:10:2021:18 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_8 |
|
||||
| ir.cpp:2021:10:2021:18 | Unary | r2021_9 |
|
||||
| ir.cpp:2021:14:2021:14 | StoreValue | r2021_38 |
|
||||
| ir.cpp:2021:18:2021:18 | StoreValue | r2021_41 |
|
||||
| ir.cpp:2021:21:2021:21 | CallTarget | func:r2021_19 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiPartial | partial:m2021_31 |
|
||||
| ir.cpp:2021:21:2021:21 | ChiTotal | total:m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | SideEffect | ~m2021_25 |
|
||||
| ir.cpp:2021:21:2021:21 | Unary | r2021_30 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Address | &:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(0) | 0:r2021_29 |
|
||||
| ir.cpp:2021:23:2021:40 | Arg(this) | this:r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | CallTarget | func:r2021_22 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_24 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiPartial | partial:m2021_26 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | ChiTotal | total:m2021_21 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_13 |
|
||||
| ir.cpp:2021:23:2021:40 | SideEffect | ~m2021_27 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_20 |
|
||||
| ir.cpp:2021:23:2021:40 | Unary | r2021_28 |
|
||||
| ir.cpp:2026:14:2026:22 | ChiPartial | partial:m2026_3 |
|
||||
| ir.cpp:2026:14:2026:22 | ChiTotal | total:m2026_2 |
|
||||
| ir.cpp:2026:37:2026:37 | Address | &:r2026_5 |
|
||||
| ir.cpp:2027:16:2027:16 | Address | &:r2027_1 |
|
||||
| ir.cpp:2028:3:2028:3 | Address | &:r2028_9 |
|
||||
| ir.cpp:2028:7:2028:7 | Address | &:r2028_1 |
|
||||
| ir.cpp:2028:7:2028:7 | Left | r2028_2 |
|
||||
| ir.cpp:2028:7:2028:7 | Load | m2026_6 |
|
||||
| ir.cpp:2028:7:2028:13 | Condition | r2028_4 |
|
||||
| ir.cpp:2028:7:2030:28 | Address | &:r2028_7 |
|
||||
| ir.cpp:2028:7:2030:28 | Address | &:r2028_11 |
|
||||
| ir.cpp:2028:7:2030:28 | Address | &:r2028_13 |
|
||||
| ir.cpp:2028:7:2030:28 | Load | m2028_6 |
|
||||
| ir.cpp:2028:7:2030:28 | Phi | from 2:m2028_12 |
|
||||
| ir.cpp:2028:7:2030:28 | Phi | from 3:m2028_14 |
|
||||
| ir.cpp:2028:7:2030:28 | StoreValue | r2028_8 |
|
||||
| ir.cpp:2028:11:2028:13 | Right | r2028_3 |
|
||||
| ir.cpp:2029:6:2029:20 | CallTarget | func:r2029_1 |
|
||||
| ir.cpp:2029:6:2029:20 | ChiPartial | partial:m2029_5 |
|
||||
| ir.cpp:2029:6:2029:20 | ChiTotal | total:m2026_4 |
|
||||
| ir.cpp:2029:6:2029:20 | SideEffect | ~m2026_4 |
|
||||
| ir.cpp:2029:6:2029:26 | StoreValue | r2029_9 |
|
||||
| ir.cpp:2029:22:2029:22 | Address | &:r2029_2 |
|
||||
| ir.cpp:2029:22:2029:22 | Arg(0) | 0:r2029_3 |
|
||||
| ir.cpp:2029:22:2029:22 | Load | m2026_6 |
|
||||
| ir.cpp:2029:26:2029:26 | Address | &:r2029_7 |
|
||||
| ir.cpp:2029:26:2029:26 | Load | m2026_6 |
|
||||
| ir.cpp:2029:26:2029:26 | Unary | r2029_8 |
|
||||
| ir.cpp:2030:5:2030:28 | StoreValue | r2030_9 |
|
||||
| ir.cpp:2030:6:2030:20 | CallTarget | func:r2030_1 |
|
||||
| ir.cpp:2030:6:2030:20 | ChiPartial | partial:m2030_5 |
|
||||
| ir.cpp:2030:6:2030:20 | ChiTotal | total:m2026_4 |
|
||||
| ir.cpp:2030:6:2030:20 | SideEffect | ~m2026_4 |
|
||||
| ir.cpp:2030:6:2030:27 | Unary | r2030_8 |
|
||||
| ir.cpp:2030:22:2030:22 | Address | &:r2030_2 |
|
||||
| ir.cpp:2030:22:2030:22 | Arg(0) | 0:r2030_3 |
|
||||
| ir.cpp:2030:22:2030:22 | Load | m2026_6 |
|
||||
| ir.cpp:2030:26:2030:27 | Unary | r2030_7 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
|
||||
@@ -724,6 +724,48 @@ complex.c:
|
||||
# 58| v58_5(void) = AliasedUse : ~m?
|
||||
# 58| v58_6(void) = ExitFunction :
|
||||
|
||||
ir.c:
|
||||
# 7| void MyCoordsTest(int)
|
||||
# 7| Block 0
|
||||
# 7| v7_1(void) = EnterFunction :
|
||||
# 7| mu7_2(unknown) = AliasedDefinition :
|
||||
# 7| mu7_3(unknown) = InitializeNonLocal :
|
||||
# 7| r7_4(glval<int>) = VariableAddress[pos] :
|
||||
# 7| mu7_5(int) = InitializeParameter[pos] : &:r7_4
|
||||
# 8| r8_1(glval<(unnamed class/struct/union)>) = VariableAddress[coords] :
|
||||
# 8| mu8_2((unnamed class/struct/union)) = Uninitialized[coords] : &:r8_1
|
||||
# 8| r8_3(glval<int>) = FieldAddress[x] : r8_1
|
||||
# 8| r8_4(int) = Constant[0] :
|
||||
# 8| mu8_5(int) = Store[?] : &:r8_3, r8_4
|
||||
# 8| r8_6(glval<int>) = FieldAddress[y] : r8_1
|
||||
# 8| r8_7(int) = Constant[0] :
|
||||
# 8| mu8_8(int) = Store[?] : &:r8_6, r8_7
|
||||
# 9| r9_1(glval<int>) = VariableAddress[pos] :
|
||||
# 9| r9_2(int) = Load[pos] : &:r9_1, ~m?
|
||||
# 9| r9_3(int) = Constant[1] :
|
||||
# 9| r9_4(int) = Add : r9_2, r9_3
|
||||
# 9| r9_5(glval<(unnamed class/struct/union)>) = VariableAddress[coords] :
|
||||
# 9| r9_6(glval<int>) = FieldAddress[y] : r9_5
|
||||
# 9| mu9_7(int) = Store[?] : &:r9_6, r9_4
|
||||
# 9| r9_8(int) = CopyValue : r9_4
|
||||
# 9| r9_9(glval<(unnamed class/struct/union)>) = VariableAddress[coords] :
|
||||
# 9| r9_10(glval<int>) = FieldAddress[x] : r9_9
|
||||
# 9| mu9_11(int) = Store[?] : &:r9_10, r9_8
|
||||
# 10| r10_1(glval<unknown>) = FunctionAddress[getX] :
|
||||
# 10| r10_2(glval<(unnamed class/struct/union)>) = VariableAddress[coords] :
|
||||
# 10| r10_3(struct <unnamed> *) = CopyValue : r10_2
|
||||
# 10| r10_4(int) = Call[getX] : func:r10_1, 0:r10_3
|
||||
# 10| mu10_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 10| v10_6(void) = ^BufferReadSideEffect[0] : &:r10_3, ~m?
|
||||
# 10| mu10_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_3
|
||||
# 10| r10_8(glval<(unnamed class/struct/union)>) = VariableAddress[coords] :
|
||||
# 10| r10_9(glval<int>) = FieldAddress[x] : r10_8
|
||||
# 10| mu10_10(int) = Store[?] : &:r10_9, r10_4
|
||||
# 11| v11_1(void) = NoOp :
|
||||
# 7| v7_6(void) = ReturnVoid :
|
||||
# 7| v7_7(void) = AliasedUse : ~m?
|
||||
# 7| v7_8(void) = ExitFunction :
|
||||
|
||||
ir.cpp:
|
||||
# 1| void Constants()
|
||||
# 1| Block 0
|
||||
@@ -10456,6 +10498,579 @@ ir.cpp:
|
||||
# 1990| v1990_5(void) = AliasedUse : ~m?
|
||||
# 1990| v1990_6(void) = ExitFunction :
|
||||
|
||||
# 1996| void TernaryTestInt(bool, int, int, int)
|
||||
# 1996| Block 0
|
||||
# 1996| v1996_1(void) = EnterFunction :
|
||||
# 1996| mu1996_2(unknown) = AliasedDefinition :
|
||||
# 1996| mu1996_3(unknown) = InitializeNonLocal :
|
||||
# 1996| r1996_4(glval<bool>) = VariableAddress[a] :
|
||||
# 1996| mu1996_5(bool) = InitializeParameter[a] : &:r1996_4
|
||||
# 1996| r1996_6(glval<int>) = VariableAddress[x] :
|
||||
# 1996| mu1996_7(int) = InitializeParameter[x] : &:r1996_6
|
||||
# 1996| r1996_8(glval<int>) = VariableAddress[y] :
|
||||
# 1996| mu1996_9(int) = InitializeParameter[y] : &:r1996_8
|
||||
# 1996| r1996_10(glval<int>) = VariableAddress[z] :
|
||||
# 1996| mu1996_11(int) = InitializeParameter[z] : &:r1996_10
|
||||
# 1997| r1997_1(glval<bool>) = VariableAddress[a] :
|
||||
# 1997| r1997_2(bool) = Load[a] : &:r1997_1, ~m?
|
||||
# 1997| v1997_3(void) = ConditionalBranch : r1997_2
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 1997| Block 1
|
||||
# 1997| r1997_4(glval<int>) = VariableAddress[#temp1997:9] :
|
||||
# 1997| r1997_5(int) = Load[#temp1997:9] : &:r1997_4, ~m?
|
||||
# 1997| r1997_6(glval<int>) = VariableAddress[z] :
|
||||
# 1997| mu1997_7(int) = Store[z] : &:r1997_6, r1997_5
|
||||
# 1998| r1998_1(glval<bool>) = VariableAddress[a] :
|
||||
# 1998| r1998_2(bool) = Load[a] : &:r1998_1, ~m?
|
||||
# 1998| v1998_3(void) = ConditionalBranch : r1998_2
|
||||
#-----| False -> Block 6
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 1997| Block 2
|
||||
# 1997| r1997_8(glval<int>) = VariableAddress[x] :
|
||||
# 1997| r1997_9(int) = Load[x] : &:r1997_8, ~m?
|
||||
# 1997| r1997_10(glval<int>) = VariableAddress[#temp1997:9] :
|
||||
# 1997| mu1997_11(int) = Store[#temp1997:9] : &:r1997_10, r1997_9
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1997| Block 3
|
||||
# 1997| r1997_12(glval<int>) = VariableAddress[y] :
|
||||
# 1997| r1997_13(int) = Load[y] : &:r1997_12, ~m?
|
||||
# 1997| r1997_14(glval<int>) = VariableAddress[#temp1997:9] :
|
||||
# 1997| mu1997_15(int) = Store[#temp1997:9] : &:r1997_14, r1997_13
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 1998| Block 4
|
||||
# 1998| r1998_4(glval<int>) = VariableAddress[#temp1998:9] :
|
||||
# 1998| r1998_5(int) = Load[#temp1998:9] : &:r1998_4, ~m?
|
||||
# 1998| r1998_6(glval<int>) = VariableAddress[z] :
|
||||
# 1998| mu1998_7(int) = Store[z] : &:r1998_6, r1998_5
|
||||
# 1999| r1999_1(glval<bool>) = VariableAddress[a] :
|
||||
# 1999| r1999_2(bool) = Load[a] : &:r1999_1, ~m?
|
||||
# 1999| v1999_3(void) = ConditionalBranch : r1999_2
|
||||
#-----| False -> Block 9
|
||||
#-----| True -> Block 8
|
||||
|
||||
# 1998| Block 5
|
||||
# 1998| r1998_8(glval<int>) = VariableAddress[x] :
|
||||
# 1998| r1998_9(int) = Load[x] : &:r1998_8, ~m?
|
||||
# 1998| r1998_10(glval<int>) = VariableAddress[#temp1998:9] :
|
||||
# 1998| mu1998_11(int) = Store[#temp1998:9] : &:r1998_10, r1998_9
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 1998| Block 6
|
||||
# 1998| r1998_12(int) = Constant[5] :
|
||||
# 1998| r1998_13(glval<int>) = VariableAddress[#temp1998:9] :
|
||||
# 1998| mu1998_14(int) = Store[#temp1998:9] : &:r1998_13, r1998_12
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 1999| Block 7
|
||||
# 1999| r1999_4(glval<int>) = VariableAddress[#temp1999:9] :
|
||||
# 1999| r1999_5(int) = Load[#temp1999:9] : &:r1999_4, ~m?
|
||||
# 1999| r1999_6(glval<int>) = VariableAddress[z] :
|
||||
# 1999| mu1999_7(int) = Store[z] : &:r1999_6, r1999_5
|
||||
# 2000| r2000_1(int) = Constant[7] :
|
||||
# 2000| r2000_2(glval<bool>) = VariableAddress[a] :
|
||||
# 2000| r2000_3(bool) = Load[a] : &:r2000_2, ~m?
|
||||
# 2000| v2000_4(void) = ConditionalBranch : r2000_3
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
# 1999| Block 8
|
||||
# 1999| r1999_8(int) = Constant[3] :
|
||||
# 1999| r1999_9(glval<int>) = VariableAddress[#temp1999:9] :
|
||||
# 1999| mu1999_10(int) = Store[#temp1999:9] : &:r1999_9, r1999_8
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 1999| Block 9
|
||||
# 1999| r1999_11(int) = Constant[5] :
|
||||
# 1999| r1999_12(glval<int>) = VariableAddress[#temp1999:9] :
|
||||
# 1999| mu1999_13(int) = Store[#temp1999:9] : &:r1999_12, r1999_11
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2000| Block 10
|
||||
# 2000| r2000_5(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| r2000_6(glval<int>) = Load[#temp2000:6] : &:r2000_5, ~m?
|
||||
# 2000| mu2000_7(int) = Store[?] : &:r2000_6, r2000_1
|
||||
# 2001| v2001_1(void) = NoOp :
|
||||
# 1996| v1996_12(void) = ReturnVoid :
|
||||
# 1996| v1996_13(void) = AliasedUse : ~m?
|
||||
# 1996| v1996_14(void) = ExitFunction :
|
||||
|
||||
# 2000| Block 11
|
||||
# 2000| r2000_8(glval<int>) = VariableAddress[x] :
|
||||
# 2000| r2000_9(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_10(glval<int>) = Store[#temp2000:6] : &:r2000_9, r2000_8
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2000| Block 12
|
||||
# 2000| r2000_11(glval<int>) = VariableAddress[y] :
|
||||
# 2000| r2000_12(glval<unknown>) = VariableAddress[#temp2000:6] :
|
||||
# 2000| mu2000_13(glval<int>) = Store[#temp2000:6] : &:r2000_12, r2000_11
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2006| void TernaryTestPodObj(bool, TernaryPodObj, TernaryPodObj, TernaryPodObj)
|
||||
# 2006| Block 0
|
||||
# 2006| v2006_1(void) = EnterFunction :
|
||||
# 2006| mu2006_2(unknown) = AliasedDefinition :
|
||||
# 2006| mu2006_3(unknown) = InitializeNonLocal :
|
||||
# 2006| r2006_4(glval<bool>) = VariableAddress[a] :
|
||||
# 2006| mu2006_5(bool) = InitializeParameter[a] : &:r2006_4
|
||||
# 2006| r2006_6(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2006| mu2006_7(TernaryPodObj) = InitializeParameter[x] : &:r2006_6
|
||||
# 2006| r2006_8(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2006| mu2006_9(TernaryPodObj) = InitializeParameter[y] : &:r2006_8
|
||||
# 2006| r2006_10(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2006| mu2006_11(TernaryPodObj) = InitializeParameter[z] : &:r2006_10
|
||||
# 2007| r2007_1(glval<bool>) = VariableAddress[a] :
|
||||
# 2007| r2007_2(bool) = Load[a] : &:r2007_1, ~m?
|
||||
# 2007| v2007_3(void) = ConditionalBranch : r2007_2
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 2007| Block 1
|
||||
# 2007| r2007_4(glval<TernaryPodObj>) = VariableAddress[#temp2007:9] :
|
||||
# 2007| r2007_5(TernaryPodObj) = Load[#temp2007:9] : &:r2007_4, ~m?
|
||||
# 2007| r2007_6(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2007| mu2007_7(TernaryPodObj) = Store[z] : &:r2007_6, r2007_5
|
||||
# 2008| r2008_1(glval<TernaryPodObj>) = VariableAddress[#temp2008:9] :
|
||||
# 2008| r2008_2(glval<bool>) = VariableAddress[a] :
|
||||
# 2008| r2008_3(bool) = Load[a] : &:r2008_2, ~m?
|
||||
# 2008| v2008_4(void) = ConditionalBranch : r2008_3
|
||||
#-----| False -> Block 6
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 2007| Block 2
|
||||
# 2007| r2007_8(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2007| r2007_9(TernaryPodObj) = Load[x] : &:r2007_8, ~m?
|
||||
# 2007| r2007_10(glval<TernaryPodObj>) = VariableAddress[#temp2007:9] :
|
||||
# 2007| mu2007_11(TernaryPodObj) = Store[#temp2007:9] : &:r2007_10, r2007_9
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 2007| Block 3
|
||||
# 2007| r2007_12(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2007| r2007_13(TernaryPodObj) = Load[y] : &:r2007_12, ~m?
|
||||
# 2007| r2007_14(glval<TernaryPodObj>) = VariableAddress[#temp2007:9] :
|
||||
# 2007| mu2007_15(TernaryPodObj) = Store[#temp2007:9] : &:r2007_14, r2007_13
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 2008| Block 4
|
||||
# 2008| r2008_5(glval<TernaryPodObj>) = VariableAddress[#temp2008:9] :
|
||||
# 2008| r2008_6(TernaryPodObj) = Load[#temp2008:9] : &:r2008_5, ~m?
|
||||
# 2008| mu2008_7(TernaryPodObj) = Store[#temp2008:9] : &:r2008_1, r2008_6
|
||||
# 2008| r2008_8(TernaryPodObj) = Load[#temp2008:9] : &:r2008_1, ~m?
|
||||
# 2008| r2008_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2008| mu2008_10(TernaryPodObj) = Store[z] : &:r2008_9, r2008_8
|
||||
# 2009| r2009_1(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_2(glval<bool>) = VariableAddress[a] :
|
||||
# 2009| r2009_3(bool) = Load[a] : &:r2009_2, ~m?
|
||||
# 2009| v2009_4(void) = ConditionalBranch : r2009_3
|
||||
#-----| False -> Block 9
|
||||
#-----| True -> Block 8
|
||||
|
||||
# 2008| Block 5
|
||||
# 2008| r2008_11(glval<TernaryPodObj>) = VariableAddress[#temp2008:13] :
|
||||
# 2008| r2008_12(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2008| r2008_13(TernaryPodObj) = Load[x] : &:r2008_12, ~m?
|
||||
# 2008| mu2008_14(TernaryPodObj) = Store[#temp2008:13] : &:r2008_11, r2008_13
|
||||
# 2008| r2008_15(TernaryPodObj) = Load[#temp2008:13] : &:r2008_11, ~m?
|
||||
# 2008| r2008_16(glval<TernaryPodObj>) = VariableAddress[#temp2008:9] :
|
||||
# 2008| mu2008_17(TernaryPodObj) = Store[#temp2008:9] : &:r2008_16, r2008_15
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2008| Block 6
|
||||
# 2008| r2008_18(glval<TernaryPodObj>) = VariableAddress[#temp2008:17] :
|
||||
# 2008| r2008_19(TernaryPodObj) = Constant[0] :
|
||||
# 2008| mu2008_20(TernaryPodObj) = Store[#temp2008:17] : &:r2008_18, r2008_19
|
||||
# 2008| r2008_21(TernaryPodObj) = Load[#temp2008:17] : &:r2008_18, ~m?
|
||||
# 2008| r2008_22(glval<TernaryPodObj>) = VariableAddress[#temp2008:9] :
|
||||
# 2008| mu2008_23(TernaryPodObj) = Store[#temp2008:9] : &:r2008_22, r2008_21
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2009| Block 7
|
||||
# 2009| r2009_5(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| r2009_6(TernaryPodObj) = Load[#temp2009:9] : &:r2009_5, ~m?
|
||||
# 2009| mu2009_7(TernaryPodObj) = Store[#temp2009:9] : &:r2009_1, r2009_6
|
||||
# 2009| r2009_8(TernaryPodObj) = Load[#temp2009:9] : &:r2009_1, ~m?
|
||||
# 2009| r2009_9(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2009| mu2009_10(TernaryPodObj) = Store[z] : &:r2009_9, r2009_8
|
||||
# 2010| r2010_1(glval<TernaryPodObj>) = VariableAddress[#temp2010:23] :
|
||||
# 2010| r2010_2(TernaryPodObj) = Constant[0] :
|
||||
# 2010| mu2010_3(TernaryPodObj) = Store[#temp2010:23] : &:r2010_1, r2010_2
|
||||
# 2010| r2010_4(TernaryPodObj) = Load[#temp2010:23] : &:r2010_1, ~m?
|
||||
# 2010| r2010_5(glval<bool>) = VariableAddress[a] :
|
||||
# 2010| r2010_6(bool) = Load[a] : &:r2010_5, ~m?
|
||||
# 2010| v2010_7(void) = ConditionalBranch : r2010_6
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
# 2009| Block 8
|
||||
# 2009| r2009_11(glval<TernaryPodObj>) = VariableAddress[#temp2009:13] :
|
||||
# 2009| r2009_12(TernaryPodObj) = Constant[0] :
|
||||
# 2009| mu2009_13(TernaryPodObj) = Store[#temp2009:13] : &:r2009_11, r2009_12
|
||||
# 2009| r2009_14(TernaryPodObj) = Load[#temp2009:13] : &:r2009_11, ~m?
|
||||
# 2009| r2009_15(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| mu2009_16(TernaryPodObj) = Store[#temp2009:9] : &:r2009_15, r2009_14
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2009| Block 9
|
||||
# 2009| r2009_17(glval<TernaryPodObj>) = VariableAddress[#temp2009:31] :
|
||||
# 2009| r2009_18(TernaryPodObj) = Constant[0] :
|
||||
# 2009| mu2009_19(TernaryPodObj) = Store[#temp2009:31] : &:r2009_17, r2009_18
|
||||
# 2009| r2009_20(TernaryPodObj) = Load[#temp2009:31] : &:r2009_17, ~m?
|
||||
# 2009| r2009_21(glval<TernaryPodObj>) = VariableAddress[#temp2009:9] :
|
||||
# 2009| mu2009_22(TernaryPodObj) = Store[#temp2009:9] : &:r2009_21, r2009_20
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2010| Block 10
|
||||
# 2010| r2010_8(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| r2010_9(TernaryPodObj) = Load[#temp2010:10] : &:r2010_8, ~m?
|
||||
# 2010| r2010_10(glval<TernaryPodObj>) = VariableAddress[z] :
|
||||
# 2010| mu2010_11(TernaryPodObj) = Store[z] : &:r2010_10, r2010_9
|
||||
# 2010| r2010_12(glval<TernaryPodObj>) = CopyValue : r2010_10
|
||||
# 2010| mu2010_13(TernaryPodObj) = Store[?] : &:r2010_12, r2010_4
|
||||
# 2011| v2011_1(void) = NoOp :
|
||||
# 2006| v2006_12(void) = ReturnVoid :
|
||||
# 2006| v2006_13(void) = AliasedUse : ~m?
|
||||
# 2006| v2006_14(void) = ExitFunction :
|
||||
|
||||
# 2010| Block 11
|
||||
# 2010| r2010_14(glval<TernaryPodObj>) = VariableAddress[x] :
|
||||
# 2010| r2010_15(TernaryPodObj) = Load[x] : &:r2010_14, ~m?
|
||||
# 2010| r2010_16(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_17(TernaryPodObj) = Store[#temp2010:10] : &:r2010_16, r2010_15
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2010| Block 12
|
||||
# 2010| r2010_18(glval<TernaryPodObj>) = VariableAddress[y] :
|
||||
# 2010| r2010_19(TernaryPodObj) = Load[y] : &:r2010_18, ~m?
|
||||
# 2010| r2010_20(glval<TernaryPodObj>) = VariableAddress[#temp2010:10] :
|
||||
# 2010| mu2010_21(TernaryPodObj) = Store[#temp2010:10] : &:r2010_20, r2010_19
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2013| TernaryNonPodObj& TernaryNonPodObj::operator=(TernaryNonPodObj const&)
|
||||
# 2013| Block 0
|
||||
# 2013| v2013_1(void) = EnterFunction :
|
||||
# 2013| mu2013_2(unknown) = AliasedDefinition :
|
||||
# 2013| mu2013_3(unknown) = InitializeNonLocal :
|
||||
# 2013| r2013_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 2013| mu2013_5(glval<TernaryNonPodObj>) = InitializeParameter[#this] : &:r2013_4
|
||||
# 2013| r2013_6(glval<TernaryNonPodObj>) = Load[#this] : &:r2013_4, ~m?
|
||||
# 2013| mu2013_7(TernaryNonPodObj) = InitializeIndirection[#this] : &:r2013_6
|
||||
#-----| r0_1(glval<TernaryNonPodObj &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(TernaryNonPodObj &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(TernaryNonPodObj &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
#-----| r0_5(glval<TernaryNonPodObj &>) = VariableAddress[#return] :
|
||||
#-----| r0_6(glval<unknown>) = VariableAddress[#this] :
|
||||
#-----| r0_7(TernaryNonPodObj *) = Load[#this] : &:r0_6, ~m?
|
||||
#-----| r0_8(glval<TernaryNonPodObj>) = CopyValue : r0_7
|
||||
#-----| r0_9(TernaryNonPodObj &) = CopyValue : r0_8
|
||||
#-----| mu0_10(TernaryNonPodObj &) = Store[#return] : &:r0_5, r0_9
|
||||
# 2013| v2013_8(void) = ReturnIndirection[#this] : &:r2013_6, ~m?
|
||||
#-----| v0_11(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 2013| r2013_9(glval<TernaryNonPodObj &>) = VariableAddress[#return] :
|
||||
# 2013| v2013_10(void) = ReturnValue : &:r2013_9, ~m?
|
||||
# 2013| v2013_11(void) = AliasedUse : ~m?
|
||||
# 2013| v2013_12(void) = ExitFunction :
|
||||
|
||||
# 2013| void TernaryNonPodObj::TernaryNonPodObj()
|
||||
# 2013| Block 0
|
||||
# 2013| v2013_1(void) = EnterFunction :
|
||||
# 2013| mu2013_2(unknown) = AliasedDefinition :
|
||||
# 2013| mu2013_3(unknown) = InitializeNonLocal :
|
||||
# 2013| r2013_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 2013| mu2013_5(glval<TernaryNonPodObj>) = InitializeParameter[#this] : &:r2013_4
|
||||
# 2013| r2013_6(glval<TernaryNonPodObj>) = Load[#this] : &:r2013_4, ~m?
|
||||
# 2013| mu2013_7(TernaryNonPodObj) = InitializeIndirection[#this] : &:r2013_6
|
||||
# 2013| v2013_8(void) = NoOp :
|
||||
# 2013| v2013_9(void) = ReturnIndirection[#this] : &:r2013_6, ~m?
|
||||
# 2013| v2013_10(void) = ReturnVoid :
|
||||
# 2013| v2013_11(void) = AliasedUse : ~m?
|
||||
# 2013| v2013_12(void) = ExitFunction :
|
||||
|
||||
# 2013| void TernaryNonPodObj::TernaryNonPodObj(TernaryNonPodObj const&)
|
||||
# 2013| Block 0
|
||||
# 2013| v2013_1(void) = EnterFunction :
|
||||
# 2013| mu2013_2(unknown) = AliasedDefinition :
|
||||
# 2013| mu2013_3(unknown) = InitializeNonLocal :
|
||||
# 2013| r2013_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 2013| mu2013_5(glval<TernaryNonPodObj>) = InitializeParameter[#this] : &:r2013_4
|
||||
# 2013| r2013_6(glval<TernaryNonPodObj>) = Load[#this] : &:r2013_4, ~m?
|
||||
# 2013| mu2013_7(TernaryNonPodObj) = InitializeIndirection[#this] : &:r2013_6
|
||||
#-----| r0_1(glval<TernaryNonPodObj &>) = VariableAddress[(unnamed parameter 0)] :
|
||||
#-----| mu0_2(TernaryNonPodObj &) = InitializeParameter[(unnamed parameter 0)] : &:r0_1
|
||||
#-----| r0_3(TernaryNonPodObj &) = Load[(unnamed parameter 0)] : &:r0_1, ~m?
|
||||
#-----| mu0_4(unknown) = InitializeIndirection[(unnamed parameter 0)] : &:r0_3
|
||||
# 2013| v2013_8(void) = NoOp :
|
||||
# 2013| v2013_9(void) = ReturnIndirection[#this] : &:r2013_6, ~m?
|
||||
#-----| v0_5(void) = ReturnIndirection[(unnamed parameter 0)] : &:r0_3, ~m?
|
||||
# 2013| v2013_10(void) = ReturnVoid :
|
||||
# 2013| v2013_11(void) = AliasedUse : ~m?
|
||||
# 2013| v2013_12(void) = ExitFunction :
|
||||
|
||||
# 2014| void TernaryNonPodObj::~TernaryNonPodObj()
|
||||
# 2014| Block 0
|
||||
# 2014| v2014_1(void) = EnterFunction :
|
||||
# 2014| mu2014_2(unknown) = AliasedDefinition :
|
||||
# 2014| mu2014_3(unknown) = InitializeNonLocal :
|
||||
# 2014| r2014_4(glval<unknown>) = VariableAddress[#this] :
|
||||
# 2014| mu2014_5(glval<TernaryNonPodObj>) = InitializeParameter[#this] : &:r2014_4
|
||||
# 2014| r2014_6(glval<TernaryNonPodObj>) = Load[#this] : &:r2014_4, ~m?
|
||||
# 2014| mu2014_7(TernaryNonPodObj) = InitializeIndirection[#this] : &:r2014_6
|
||||
# 2014| v2014_8(void) = NoOp :
|
||||
# 2014| v2014_9(void) = ReturnIndirection[#this] : &:r2014_6, ~m?
|
||||
# 2014| v2014_10(void) = ReturnVoid :
|
||||
# 2014| v2014_11(void) = AliasedUse : ~m?
|
||||
# 2014| v2014_12(void) = ExitFunction :
|
||||
|
||||
# 2017| void TernaryTestNonPodObj(bool, TernaryNonPodObj, TernaryNonPodObj, TernaryNonPodObj)
|
||||
# 2017| Block 0
|
||||
# 2017| v2017_1(void) = EnterFunction :
|
||||
# 2017| mu2017_2(unknown) = AliasedDefinition :
|
||||
# 2017| mu2017_3(unknown) = InitializeNonLocal :
|
||||
# 2017| r2017_4(glval<bool>) = VariableAddress[a] :
|
||||
# 2017| mu2017_5(bool) = InitializeParameter[a] : &:r2017_4
|
||||
# 2017| r2017_6(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2017| mu2017_7(TernaryNonPodObj) = InitializeParameter[x] : &:r2017_6
|
||||
# 2017| r2017_8(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2017| mu2017_9(TernaryNonPodObj) = InitializeParameter[y] : &:r2017_8
|
||||
# 2017| r2017_10(glval<TernaryNonPodObj>) = VariableAddress[z] :
|
||||
# 2017| mu2017_11(TernaryNonPodObj) = InitializeParameter[z] : &:r2017_10
|
||||
# 2018| r2018_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
|
||||
# 2018| r2018_2(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2018| r2018_3(glval<bool>) = VariableAddress[a] :
|
||||
# 2018| r2018_4(bool) = Load[a] : &:r2018_3, ~m?
|
||||
# 2018| v2018_5(void) = ConditionalBranch : r2018_4
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 2018| Block 1
|
||||
# 2018| r2018_6(glval<unknown>) = VariableAddress[#temp2018:9] :
|
||||
# 2018| r2018_7(glval<TernaryNonPodObj>) = Load[#temp2018:9] : &:r2018_6, ~m?
|
||||
# 2018| r2018_8(glval<TernaryNonPodObj>) = Convert : r2018_7
|
||||
# 2018| r2018_9(TernaryNonPodObj &) = CopyValue : r2018_8
|
||||
# 2018| r2018_10(TernaryNonPodObj &) = Call[operator=] : func:r2018_2, this:r2018_1, 0:r2018_9
|
||||
# 2018| mu2018_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2018| v2018_12(void) = ^IndirectReadSideEffect[-1] : &:r2018_1, ~m?
|
||||
# 2018| v2018_13(void) = ^BufferReadSideEffect[0] : &:r2018_9, ~m?
|
||||
# 2018| mu2018_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2018_1
|
||||
# 2018| r2018_15(glval<TernaryNonPodObj>) = CopyValue : r2018_10
|
||||
# 2019| r2019_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
|
||||
# 2019| r2019_2(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2019| r2019_3(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:9] :
|
||||
# 2019| r2019_4(glval<bool>) = VariableAddress[a] :
|
||||
# 2019| r2019_5(bool) = Load[a] : &:r2019_4, ~m?
|
||||
# 2019| v2019_6(void) = ConditionalBranch : r2019_5
|
||||
#-----| False -> Block 6
|
||||
#-----| True -> Block 5
|
||||
|
||||
# 2018| Block 2
|
||||
# 2018| r2018_16(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2018| r2018_17(glval<unknown>) = VariableAddress[#temp2018:9] :
|
||||
# 2018| mu2018_18(glval<TernaryNonPodObj>) = Store[#temp2018:9] : &:r2018_17, r2018_16
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 2018| Block 3
|
||||
# 2018| r2018_19(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2018| r2018_20(glval<unknown>) = VariableAddress[#temp2018:9] :
|
||||
# 2018| mu2018_21(glval<TernaryNonPodObj>) = Store[#temp2018:9] : &:r2018_20, r2018_19
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 2019| Block 4
|
||||
# 2019| r2019_7(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:9] :
|
||||
# 2019| r2019_8(TernaryNonPodObj) = Load[#temp2019:9] : &:r2019_7, ~m?
|
||||
# 2019| mu2019_9(TernaryNonPodObj) = Store[#temp2019:9] : &:r2019_3, r2019_8
|
||||
# 2019| r2019_10(glval<TernaryNonPodObj>) = Convert : r2019_3
|
||||
# 2019| r2019_11(TernaryNonPodObj &) = CopyValue : r2019_10
|
||||
# 2019| r2019_12(TernaryNonPodObj &) = Call[operator=] : func:r2019_2, this:r2019_1, 0:r2019_11
|
||||
# 2019| mu2019_13(unknown) = ^CallSideEffect : ~m?
|
||||
# 2019| v2019_14(void) = ^IndirectReadSideEffect[-1] : &:r2019_1, ~m?
|
||||
# 2019| v2019_15(void) = ^BufferReadSideEffect[0] : &:r2019_11, ~m?
|
||||
# 2019| mu2019_16(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2019_1
|
||||
# 2019| r2019_17(glval<TernaryNonPodObj>) = CopyValue : r2019_12
|
||||
# 2020| r2020_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
|
||||
# 2020| r2020_2(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2020| r2020_3(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:9] :
|
||||
# 2020| r2020_4(glval<bool>) = VariableAddress[a] :
|
||||
# 2020| r2020_5(bool) = Load[a] : &:r2020_4, ~m?
|
||||
# 2020| v2020_6(void) = ConditionalBranch : r2020_5
|
||||
#-----| False -> Block 9
|
||||
#-----| True -> Block 8
|
||||
|
||||
# 2019| Block 5
|
||||
# 2019| r2019_18(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:13] :
|
||||
# 2019| mu2019_19(TernaryNonPodObj) = Uninitialized[#temp2019:13] : &:r2019_18
|
||||
# 2019| r2019_20(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2019| r2019_21(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2019| r2019_22(glval<TernaryNonPodObj>) = Convert : r2019_21
|
||||
# 2019| r2019_23(TernaryNonPodObj &) = CopyValue : r2019_22
|
||||
# 2019| v2019_24(void) = Call[TernaryNonPodObj] : func:r2019_20, this:r2019_18, 0:r2019_23
|
||||
# 2019| mu2019_25(unknown) = ^CallSideEffect : ~m?
|
||||
# 2019| v2019_26(void) = ^BufferReadSideEffect[0] : &:r2019_23, ~m?
|
||||
# 2019| mu2019_27(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2019_18
|
||||
# 2019| r2019_28(TernaryNonPodObj) = Load[#temp2019:13] : &:r2019_18, ~m?
|
||||
# 2019| r2019_29(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:9] :
|
||||
# 2019| mu2019_30(TernaryNonPodObj) = Store[#temp2019:9] : &:r2019_29, r2019_28
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2019| Block 6
|
||||
# 2019| r2019_31(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:17] :
|
||||
# 2019| mu2019_32(TernaryNonPodObj) = Uninitialized[#temp2019:17] : &:r2019_31
|
||||
# 2019| r2019_33(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2019| v2019_34(void) = Call[TernaryNonPodObj] : func:r2019_33, this:r2019_31
|
||||
# 2019| mu2019_35(unknown) = ^CallSideEffect : ~m?
|
||||
# 2019| mu2019_36(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2019_31
|
||||
# 2019| r2019_37(TernaryNonPodObj) = Load[#temp2019:17] : &:r2019_31, ~m?
|
||||
# 2019| r2019_38(glval<TernaryNonPodObj>) = VariableAddress[#temp2019:9] :
|
||||
# 2019| mu2019_39(TernaryNonPodObj) = Store[#temp2019:9] : &:r2019_38, r2019_37
|
||||
#-----| Goto -> Block 4
|
||||
|
||||
# 2020| Block 7
|
||||
# 2020| r2020_7(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:9] :
|
||||
# 2020| r2020_8(TernaryNonPodObj) = Load[#temp2020:9] : &:r2020_7, ~m?
|
||||
# 2020| mu2020_9(TernaryNonPodObj) = Store[#temp2020:9] : &:r2020_3, r2020_8
|
||||
# 2020| r2020_10(glval<TernaryNonPodObj>) = Convert : r2020_3
|
||||
# 2020| r2020_11(TernaryNonPodObj &) = CopyValue : r2020_10
|
||||
# 2020| r2020_12(TernaryNonPodObj &) = Call[operator=] : func:r2020_2, this:r2020_1, 0:r2020_11
|
||||
# 2020| mu2020_13(unknown) = ^CallSideEffect : ~m?
|
||||
# 2020| v2020_14(void) = ^IndirectReadSideEffect[-1] : &:r2020_1, ~m?
|
||||
# 2020| v2020_15(void) = ^BufferReadSideEffect[0] : &:r2020_11, ~m?
|
||||
# 2020| mu2020_16(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2020_1
|
||||
# 2020| r2020_17(glval<TernaryNonPodObj>) = CopyValue : r2020_12
|
||||
# 2021| r2021_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
|
||||
# 2021| r2021_2(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_3(glval<bool>) = VariableAddress[a] :
|
||||
# 2021| r2021_4(bool) = Load[a] : &:r2021_3, ~m?
|
||||
# 2021| v2021_5(void) = ConditionalBranch : r2021_4
|
||||
#-----| False -> Block 12
|
||||
#-----| True -> Block 11
|
||||
|
||||
# 2020| Block 8
|
||||
# 2020| r2020_18(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:13] :
|
||||
# 2020| mu2020_19(TernaryNonPodObj) = Uninitialized[#temp2020:13] : &:r2020_18
|
||||
# 2020| r2020_20(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2020| v2020_21(void) = Call[TernaryNonPodObj] : func:r2020_20, this:r2020_18
|
||||
# 2020| mu2020_22(unknown) = ^CallSideEffect : ~m?
|
||||
# 2020| mu2020_23(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2020_18
|
||||
# 2020| r2020_24(TernaryNonPodObj) = Load[#temp2020:13] : &:r2020_18, ~m?
|
||||
# 2020| r2020_25(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:9] :
|
||||
# 2020| mu2020_26(TernaryNonPodObj) = Store[#temp2020:9] : &:r2020_25, r2020_24
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2020| Block 9
|
||||
# 2020| r2020_27(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:34] :
|
||||
# 2020| mu2020_28(TernaryNonPodObj) = Uninitialized[#temp2020:34] : &:r2020_27
|
||||
# 2020| r2020_29(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2020| v2020_30(void) = Call[TernaryNonPodObj] : func:r2020_29, this:r2020_27
|
||||
# 2020| mu2020_31(unknown) = ^CallSideEffect : ~m?
|
||||
# 2020| mu2020_32(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2020_27
|
||||
# 2020| r2020_33(TernaryNonPodObj) = Load[#temp2020:34] : &:r2020_27, ~m?
|
||||
# 2020| r2020_34(glval<TernaryNonPodObj>) = VariableAddress[#temp2020:9] :
|
||||
# 2020| mu2020_35(TernaryNonPodObj) = Store[#temp2020:9] : &:r2020_34, r2020_33
|
||||
#-----| Goto -> Block 7
|
||||
|
||||
# 2021| Block 10
|
||||
# 2021| r2021_6(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| r2021_7(glval<TernaryNonPodObj>) = Load[#temp2021:10] : &:r2021_6, ~m?
|
||||
# 2021| r2021_8(glval<TernaryNonPodObj>) = Convert : r2021_7
|
||||
# 2021| r2021_9(TernaryNonPodObj &) = CopyValue : r2021_8
|
||||
# 2021| r2021_10(TernaryNonPodObj &) = Call[operator=] : func:r2021_2, this:r2021_1, 0:r2021_9
|
||||
# 2021| mu2021_11(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_12(void) = ^IndirectReadSideEffect[-1] : &:r2021_1, ~m?
|
||||
# 2021| v2021_13(void) = ^BufferReadSideEffect[0] : &:r2021_9, ~m?
|
||||
# 2021| mu2021_14(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_1
|
||||
# 2021| r2021_15(glval<TernaryNonPodObj>) = CopyValue : r2021_10
|
||||
# 2021| r2021_16(glval<unknown>) = FunctionAddress[operator=] :
|
||||
# 2021| r2021_17(glval<TernaryNonPodObj>) = VariableAddress[#temp2021:23] :
|
||||
# 2021| mu2021_18(TernaryNonPodObj) = Uninitialized[#temp2021:23] : &:r2021_17
|
||||
# 2021| r2021_19(glval<unknown>) = FunctionAddress[TernaryNonPodObj] :
|
||||
# 2021| v2021_20(void) = Call[TernaryNonPodObj] : func:r2021_19, this:r2021_17
|
||||
# 2021| mu2021_21(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| mu2021_22(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_17
|
||||
# 2021| r2021_23(glval<TernaryNonPodObj>) = Convert : r2021_17
|
||||
# 2021| r2021_24(TernaryNonPodObj &) = CopyValue : r2021_23
|
||||
# 2021| r2021_25(TernaryNonPodObj &) = Call[operator=] : func:r2021_16, this:r2021_15, 0:r2021_24
|
||||
# 2021| mu2021_26(unknown) = ^CallSideEffect : ~m?
|
||||
# 2021| v2021_27(void) = ^IndirectReadSideEffect[-1] : &:r2021_15, ~m?
|
||||
# 2021| v2021_28(void) = ^BufferReadSideEffect[0] : &:r2021_24, ~m?
|
||||
# 2021| mu2021_29(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2021_15
|
||||
# 2021| r2021_30(glval<TernaryNonPodObj>) = CopyValue : r2021_25
|
||||
# 2022| v2022_1(void) = NoOp :
|
||||
# 2017| v2017_12(void) = ReturnVoid :
|
||||
# 2017| v2017_13(void) = AliasedUse : ~m?
|
||||
# 2017| v2017_14(void) = ExitFunction :
|
||||
|
||||
# 2021| Block 11
|
||||
# 2021| r2021_31(glval<TernaryNonPodObj>) = VariableAddress[x] :
|
||||
# 2021| r2021_32(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_33(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_32, r2021_31
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2021| Block 12
|
||||
# 2021| r2021_34(glval<TernaryNonPodObj>) = VariableAddress[y] :
|
||||
# 2021| r2021_35(glval<unknown>) = VariableAddress[#temp2021:10] :
|
||||
# 2021| mu2021_36(glval<TernaryNonPodObj>) = Store[#temp2021:10] : &:r2021_35, r2021_34
|
||||
#-----| Goto -> Block 10
|
||||
|
||||
# 2026| unsigned int CommaTest(unsigned int)
|
||||
# 2026| Block 0
|
||||
# 2026| v2026_1(void) = EnterFunction :
|
||||
# 2026| mu2026_2(unknown) = AliasedDefinition :
|
||||
# 2026| mu2026_3(unknown) = InitializeNonLocal :
|
||||
# 2026| r2026_4(glval<unsigned int>) = VariableAddress[x] :
|
||||
# 2026| mu2026_5(unsigned int) = InitializeParameter[x] : &:r2026_4
|
||||
# 2027| r2027_1(glval<unsigned int>) = VariableAddress[y] :
|
||||
# 2027| mu2027_2(unsigned int) = Uninitialized[y] : &:r2027_1
|
||||
# 2028| r2028_1(glval<unsigned int>) = VariableAddress[x] :
|
||||
# 2028| r2028_2(unsigned int) = Load[x] : &:r2028_1, ~m?
|
||||
# 2028| r2028_3(unsigned int) = Constant[100] :
|
||||
# 2028| r2028_4(bool) = CompareLT : r2028_2, r2028_3
|
||||
# 2028| v2028_5(void) = ConditionalBranch : r2028_4
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
|
||||
# 2026| Block 1
|
||||
# 2026| r2026_6(glval<unsigned int>) = VariableAddress[#return] :
|
||||
# 2026| v2026_7(void) = ReturnValue : &:r2026_6, ~m?
|
||||
# 2026| v2026_8(void) = AliasedUse : ~m?
|
||||
# 2026| v2026_9(void) = ExitFunction :
|
||||
|
||||
# 2028| Block 2
|
||||
# 2028| r2028_6(glval<unsigned int>) = VariableAddress[#temp2028:7] :
|
||||
# 2028| r2028_7(unsigned int) = Load[#temp2028:7] : &:r2028_6, ~m?
|
||||
# 2028| r2028_8(glval<unsigned int>) = VariableAddress[y] :
|
||||
# 2028| mu2028_9(unsigned int) = Store[y] : &:r2028_8, r2028_7
|
||||
# 2031| v2031_1(void) = Unreached :
|
||||
|
||||
# 2029| Block 3
|
||||
# 2029| r2029_1(glval<unknown>) = FunctionAddress[CommaTestHelper] :
|
||||
# 2029| r2029_2(glval<unsigned int>) = VariableAddress[x] :
|
||||
# 2029| r2029_3(unsigned int) = Load[x] : &:r2029_2, ~m?
|
||||
# 2029| v2029_4(void) = Call[CommaTestHelper] : func:r2029_1, 0:r2029_3
|
||||
# 2029| mu2029_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 2029| r2029_6(glval<unsigned int>) = VariableAddress[x] :
|
||||
# 2029| r2029_7(unsigned int) = Load[x] : &:r2029_6, ~m?
|
||||
# 2029| r2029_8(unsigned int) = CopyValue : r2029_7
|
||||
# 2028| r2028_10(glval<unsigned int>) = VariableAddress[#temp2028:7] :
|
||||
# 2028| mu2028_11(unsigned int) = Store[#temp2028:7] : &:r2028_10, r2029_8
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
# 2030| Block 4
|
||||
# 2030| r2030_1(glval<unknown>) = FunctionAddress[CommaTestHelper] :
|
||||
# 2030| r2030_2(glval<unsigned int>) = VariableAddress[x] :
|
||||
# 2030| r2030_3(unsigned int) = Load[x] : &:r2030_2, ~m?
|
||||
# 2030| v2030_4(void) = Call[CommaTestHelper] : func:r2030_1, 0:r2030_3
|
||||
# 2030| mu2030_5(unknown) = ^CallSideEffect : ~m?
|
||||
# 2030| r2030_6(int) = Constant[10] :
|
||||
# 2030| r2030_7(int) = CopyValue : r2030_6
|
||||
# 2030| r2030_8(unsigned int) = Convert : r2030_7
|
||||
# 2028| r2028_12(glval<unsigned int>) = VariableAddress[#temp2028:7] :
|
||||
# 2028| mu2028_13(unsigned int) = Store[#temp2028:7] : &:r2028_12, r2030_8
|
||||
#-----| Goto -> Block 2
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
|
||||
@@ -7,5 +7,5 @@ private import semmle.code.cpp.ir.implementation.raw.PrintIR
|
||||
private import PrintConfig
|
||||
|
||||
private class PrintConfig extends PrintIRConfiguration {
|
||||
override predicate shouldPrintFunction(Declaration decl) { shouldDumpFunction(decl) }
|
||||
override predicate shouldPrintDeclaration(Declaration decl) { shouldDumpDeclaration(decl) }
|
||||
}
|
||||
|
||||
@@ -95,3 +95,25 @@ void gotoLoop(bool b1, bool b2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_sub(int x, int y, int n) {
|
||||
if(x > 0 && x < 500) {
|
||||
if(y > 0 && y < 10) {
|
||||
range(x - y); // $ range=<=498 range=>=-8
|
||||
}
|
||||
|
||||
if(n > 0 && n < 100) {
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
range(n - i); // $ range=">=Phi: i-97" range=<=99 range=>=-97
|
||||
range(i - n); // $ range="<=Phi: i-1" range=">=Phi: i-99" range=<=97 range=>=-99
|
||||
}
|
||||
|
||||
for (int i = n; i != 0; i--)
|
||||
{
|
||||
range(n - i); // $ SPURIOUS: overflow=+
|
||||
range(i - n); // $ range=">=Phi: i-99"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2157,3 +2157,46 @@ ssa.cpp:
|
||||
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
|
||||
# 431| v431_10(void) = AliasedUse : m431_3
|
||||
# 431| v431_11(void) = ExitFunction :
|
||||
|
||||
# 438| void Conditional(bool, int, int)
|
||||
# 438| Block 0
|
||||
# 438| v438_1(void) = EnterFunction :
|
||||
# 438| m438_2(unknown) = AliasedDefinition :
|
||||
# 438| m438_3(unknown) = InitializeNonLocal :
|
||||
# 438| m438_4(unknown) = Chi : total:m438_2, partial:m438_3
|
||||
# 438| r438_5(glval<bool>) = VariableAddress[a] :
|
||||
# 438| m438_6(bool) = InitializeParameter[a] : &:r438_5
|
||||
# 438| r438_7(glval<int>) = VariableAddress[x] :
|
||||
# 438| m438_8(int) = InitializeParameter[x] : &:r438_7
|
||||
# 438| r438_9(glval<int>) = VariableAddress[y] :
|
||||
# 438| m438_10(int) = InitializeParameter[y] : &:r438_9
|
||||
# 439| r439_1(glval<int>) = VariableAddress[z] :
|
||||
# 439| r439_2(glval<bool>) = VariableAddress[a] :
|
||||
# 439| r439_3(bool) = Load[a] : &:r439_2, m438_6
|
||||
# 439| v439_4(void) = ConditionalBranch : r439_3
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 439| Block 1
|
||||
# 439| m439_5(int) = Phi : from 2:m439_12, from 3:m439_16
|
||||
# 439| r439_6(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| r439_7(int) = Load[#temp439:13] : &:r439_6, m439_5
|
||||
# 439| m439_8(int) = Store[z] : &:r439_1, r439_7
|
||||
# 440| v440_1(void) = NoOp :
|
||||
# 438| v438_11(void) = ReturnVoid :
|
||||
# 438| v438_12(void) = AliasedUse : m438_3
|
||||
# 438| v438_13(void) = ExitFunction :
|
||||
|
||||
# 439| Block 2
|
||||
# 439| r439_9(glval<int>) = VariableAddress[x] :
|
||||
# 439| r439_10(int) = Load[x] : &:r439_9, m438_8
|
||||
# 439| r439_11(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_12(int) = Store[#temp439:13] : &:r439_11, r439_10
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 439| Block 3
|
||||
# 439| r439_13(glval<int>) = VariableAddress[y] :
|
||||
# 439| r439_14(int) = Load[y] : &:r439_13, m438_10
|
||||
# 439| r439_15(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_16(int) = Store[#temp439:13] : &:r439_15, r439_14
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -2146,3 +2146,46 @@ ssa.cpp:
|
||||
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
|
||||
# 431| v431_10(void) = AliasedUse : m431_3
|
||||
# 431| v431_11(void) = ExitFunction :
|
||||
|
||||
# 438| void Conditional(bool, int, int)
|
||||
# 438| Block 0
|
||||
# 438| v438_1(void) = EnterFunction :
|
||||
# 438| m438_2(unknown) = AliasedDefinition :
|
||||
# 438| m438_3(unknown) = InitializeNonLocal :
|
||||
# 438| m438_4(unknown) = Chi : total:m438_2, partial:m438_3
|
||||
# 438| r438_5(glval<bool>) = VariableAddress[a] :
|
||||
# 438| m438_6(bool) = InitializeParameter[a] : &:r438_5
|
||||
# 438| r438_7(glval<int>) = VariableAddress[x] :
|
||||
# 438| m438_8(int) = InitializeParameter[x] : &:r438_7
|
||||
# 438| r438_9(glval<int>) = VariableAddress[y] :
|
||||
# 438| m438_10(int) = InitializeParameter[y] : &:r438_9
|
||||
# 439| r439_1(glval<int>) = VariableAddress[z] :
|
||||
# 439| r439_2(glval<bool>) = VariableAddress[a] :
|
||||
# 439| r439_3(bool) = Load[a] : &:r439_2, m438_6
|
||||
# 439| v439_4(void) = ConditionalBranch : r439_3
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 439| Block 1
|
||||
# 439| m439_5(int) = Phi : from 2:m439_12, from 3:m439_16
|
||||
# 439| r439_6(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| r439_7(int) = Load[#temp439:13] : &:r439_6, m439_5
|
||||
# 439| m439_8(int) = Store[z] : &:r439_1, r439_7
|
||||
# 440| v440_1(void) = NoOp :
|
||||
# 438| v438_11(void) = ReturnVoid :
|
||||
# 438| v438_12(void) = AliasedUse : m438_3
|
||||
# 438| v438_13(void) = ExitFunction :
|
||||
|
||||
# 439| Block 2
|
||||
# 439| r439_9(glval<int>) = VariableAddress[x] :
|
||||
# 439| r439_10(int) = Load[x] : &:r439_9, m438_8
|
||||
# 439| r439_11(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_12(int) = Store[#temp439:13] : &:r439_11, r439_10
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 439| Block 3
|
||||
# 439| r439_13(glval<int>) = VariableAddress[y] :
|
||||
# 439| r439_14(int) = Load[y] : &:r439_13, m438_10
|
||||
# 439| r439_15(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_16(int) = Store[#temp439:13] : &:r439_15, r439_14
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -434,3 +434,7 @@ int noreturnTest2(int x) {
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
void Conditional(bool a, int x, int y) {
|
||||
int z = a ? x : y;
|
||||
}
|
||||
|
||||
@@ -2002,3 +2002,45 @@ ssa.cpp:
|
||||
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
|
||||
# 431| v431_9(void) = AliasedUse : ~m?
|
||||
# 431| v431_10(void) = ExitFunction :
|
||||
|
||||
# 438| void Conditional(bool, int, int)
|
||||
# 438| Block 0
|
||||
# 438| v438_1(void) = EnterFunction :
|
||||
# 438| mu438_2(unknown) = AliasedDefinition :
|
||||
# 438| mu438_3(unknown) = InitializeNonLocal :
|
||||
# 438| r438_4(glval<bool>) = VariableAddress[a] :
|
||||
# 438| m438_5(bool) = InitializeParameter[a] : &:r438_4
|
||||
# 438| r438_6(glval<int>) = VariableAddress[x] :
|
||||
# 438| m438_7(int) = InitializeParameter[x] : &:r438_6
|
||||
# 438| r438_8(glval<int>) = VariableAddress[y] :
|
||||
# 438| m438_9(int) = InitializeParameter[y] : &:r438_8
|
||||
# 439| r439_1(glval<int>) = VariableAddress[z] :
|
||||
# 439| r439_2(glval<bool>) = VariableAddress[a] :
|
||||
# 439| r439_3(bool) = Load[a] : &:r439_2, m438_5
|
||||
# 439| v439_4(void) = ConditionalBranch : r439_3
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 439| Block 1
|
||||
# 439| m439_5(int) = Phi : from 2:m439_12, from 3:m439_16
|
||||
# 439| r439_6(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| r439_7(int) = Load[#temp439:13] : &:r439_6, m439_5
|
||||
# 439| m439_8(int) = Store[z] : &:r439_1, r439_7
|
||||
# 440| v440_1(void) = NoOp :
|
||||
# 438| v438_10(void) = ReturnVoid :
|
||||
# 438| v438_11(void) = AliasedUse : ~m?
|
||||
# 438| v438_12(void) = ExitFunction :
|
||||
|
||||
# 439| Block 2
|
||||
# 439| r439_9(glval<int>) = VariableAddress[x] :
|
||||
# 439| r439_10(int) = Load[x] : &:r439_9, m438_7
|
||||
# 439| r439_11(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_12(int) = Store[#temp439:13] : &:r439_11, r439_10
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 439| Block 3
|
||||
# 439| r439_13(glval<int>) = VariableAddress[y] :
|
||||
# 439| r439_14(int) = Load[y] : &:r439_13, m438_9
|
||||
# 439| r439_15(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_16(int) = Store[#temp439:13] : &:r439_15, r439_14
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -2002,3 +2002,45 @@ ssa.cpp:
|
||||
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
|
||||
# 431| v431_9(void) = AliasedUse : ~m?
|
||||
# 431| v431_10(void) = ExitFunction :
|
||||
|
||||
# 438| void Conditional(bool, int, int)
|
||||
# 438| Block 0
|
||||
# 438| v438_1(void) = EnterFunction :
|
||||
# 438| mu438_2(unknown) = AliasedDefinition :
|
||||
# 438| mu438_3(unknown) = InitializeNonLocal :
|
||||
# 438| r438_4(glval<bool>) = VariableAddress[a] :
|
||||
# 438| m438_5(bool) = InitializeParameter[a] : &:r438_4
|
||||
# 438| r438_6(glval<int>) = VariableAddress[x] :
|
||||
# 438| m438_7(int) = InitializeParameter[x] : &:r438_6
|
||||
# 438| r438_8(glval<int>) = VariableAddress[y] :
|
||||
# 438| m438_9(int) = InitializeParameter[y] : &:r438_8
|
||||
# 439| r439_1(glval<int>) = VariableAddress[z] :
|
||||
# 439| r439_2(glval<bool>) = VariableAddress[a] :
|
||||
# 439| r439_3(bool) = Load[a] : &:r439_2, m438_5
|
||||
# 439| v439_4(void) = ConditionalBranch : r439_3
|
||||
#-----| False -> Block 3
|
||||
#-----| True -> Block 2
|
||||
|
||||
# 439| Block 1
|
||||
# 439| m439_5(int) = Phi : from 2:m439_12, from 3:m439_16
|
||||
# 439| r439_6(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| r439_7(int) = Load[#temp439:13] : &:r439_6, m439_5
|
||||
# 439| m439_8(int) = Store[z] : &:r439_1, r439_7
|
||||
# 440| v440_1(void) = NoOp :
|
||||
# 438| v438_10(void) = ReturnVoid :
|
||||
# 438| v438_11(void) = AliasedUse : ~m?
|
||||
# 438| v438_12(void) = ExitFunction :
|
||||
|
||||
# 439| Block 2
|
||||
# 439| r439_9(glval<int>) = VariableAddress[x] :
|
||||
# 439| r439_10(int) = Load[x] : &:r439_9, m438_7
|
||||
# 439| r439_11(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_12(int) = Store[#temp439:13] : &:r439_11, r439_10
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
# 439| Block 3
|
||||
# 439| r439_13(glval<int>) = VariableAddress[y] :
|
||||
# 439| r439_14(int) = Load[y] : &:r439_13, m438_9
|
||||
# 439| r439_15(glval<int>) = VariableAddress[#temp439:13] :
|
||||
# 439| m439_16(int) = Store[#temp439:13] : &:r439_15, r439_14
|
||||
#-----| Goto -> Block 1
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
| file://:0:0:0:0 | _Float64 |
|
||||
| file://:0:0:0:0 | _Float64x |
|
||||
| file://:0:0:0:0 | _Float128 |
|
||||
| file://:0:0:0:0 | _Float128x |
|
||||
| file://:0:0:0:0 | _Imaginary double |
|
||||
| file://:0:0:0:0 | _Imaginary float |
|
||||
| file://:0:0:0:0 | _Imaginary long double |
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
| file://:0:0:0:0 | _Float64 | 8 |
|
||||
| file://:0:0:0:0 | _Float64x | 16 |
|
||||
| file://:0:0:0:0 | _Float128 | 16 |
|
||||
| file://:0:0:0:0 | _Float128x | 32 |
|
||||
| file://:0:0:0:0 | _Imaginary double | 8 |
|
||||
| file://:0:0:0:0 | _Imaginary float | 4 |
|
||||
| file://:0:0:0:0 | _Imaginary long double | 16 |
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
| file://:0:0:0:0 | _Float64 | _Float64 |
|
||||
| file://:0:0:0:0 | _Float64x | _Float64x |
|
||||
| file://:0:0:0:0 | _Float128 | _Float128 |
|
||||
| file://:0:0:0:0 | _Float128x | _Float128x |
|
||||
| file://:0:0:0:0 | _Imaginary double | _Imaginary double |
|
||||
| file://:0:0:0:0 | _Imaginary float | _Imaginary float |
|
||||
| file://:0:0:0:0 | _Imaginary long double | _Imaginary long double |
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
| _Float64 | BinaryFloatingPointType, RealNumberType | | | | |
|
||||
| _Float64x | BinaryFloatingPointType, RealNumberType | | | | |
|
||||
| _Float128 | BinaryFloatingPointType, RealNumberType | | | | |
|
||||
| _Float128x | BinaryFloatingPointType, RealNumberType | | | | |
|
||||
| _Imaginary double | BinaryFloatingPointType, ImaginaryNumberType | | | | |
|
||||
| _Imaginary float | BinaryFloatingPointType, ImaginaryNumberType | | | | |
|
||||
| _Imaginary long double | BinaryFloatingPointType, ImaginaryNumberType | | | | |
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
| tests2.cpp:59:3:59:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 0 bytes. |
|
||||
| tests2.cpp:59:3:59:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 2 bytes. |
|
||||
| tests2.cpp:63:3:63:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 0 bytes. |
|
||||
| tests2.cpp:63:3:63:10 | call to snprintf | This 'call to snprintf' operation is limited to 13 bytes but the destination is only 3 bytes. |
|
||||
| tests.c:43:3:43:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. |
|
||||
| tests.c:46:3:46:10 | call to snprintf | This 'call to snprintf' operation is limited to 111 bytes but the destination is only 110 bytes. |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user