]> Cypherpunks.ru repositories - gostls13.git/blob - test/prove.go
[dev.boringcrypto] all: merge master into dev.boringcrypto
[gostls13.git] / test / prove.go
1 // +build amd64
2 // errorcheck -0 -d=ssa/prove/debug=1
3
4 // Copyright 2016 The Go Authors. All rights reserved.
5 // Use of this source code is governed by a BSD-style
6 // license that can be found in the LICENSE file.
7
8 package main
9
10 import "math"
11
12 func f0(a []int) int {
13         a[0] = 1
14         a[0] = 1 // ERROR "Proved IsInBounds$"
15         a[6] = 1
16         a[6] = 1 // ERROR "Proved IsInBounds$"
17         a[5] = 1 // ERROR "Proved IsInBounds$"
18         a[5] = 1 // ERROR "Proved IsInBounds$"
19         return 13
20 }
21
22 func f1(a []int) int {
23         if len(a) <= 5 {
24                 return 18
25         }
26         a[0] = 1 // ERROR "Proved IsInBounds$"
27         a[0] = 1 // ERROR "Proved IsInBounds$"
28         a[6] = 1
29         a[6] = 1 // ERROR "Proved IsInBounds$"
30         a[5] = 1 // ERROR "Proved IsInBounds$"
31         a[5] = 1 // ERROR "Proved IsInBounds$"
32         return 26
33 }
34
35 func f1b(a []int, i int, j uint) int {
36         if i >= 0 && i < len(a) {
37                 return a[i] // ERROR "Proved IsInBounds$"
38         }
39         if i >= 10 && i < len(a) {
40                 return a[i] // ERROR "Proved IsInBounds$"
41         }
42         if i >= 10 && i < len(a) {
43                 return a[i] // ERROR "Proved IsInBounds$"
44         }
45         if i >= 10 && i < len(a) {
46                 return a[i-10] // ERROR "Proved IsInBounds$"
47         }
48         if j < uint(len(a)) {
49                 return a[j] // ERROR "Proved IsInBounds$"
50         }
51         return 0
52 }
53
54 func f1c(a []int, i int64) int {
55         c := uint64(math.MaxInt64 + 10) // overflows int
56         d := int64(c)
57         if i >= d && i < int64(len(a)) {
58                 // d overflows, should not be handled.
59                 return a[i]
60         }
61         return 0
62 }
63
64 func f2(a []int) int {
65         for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1"
66                 a[i+1] = i
67                 a[i+1] = i // ERROR "Proved IsInBounds$"
68         }
69         return 34
70 }
71
72 func f3(a []uint) int {
73         for i := uint(0); i < uint(len(a)); i++ {
74                 a[i] = i // ERROR "Proved IsInBounds$"
75         }
76         return 41
77 }
78
79 func f4a(a, b, c int) int {
80         if a < b {
81                 if a == b { // ERROR "Disproved Eq64$"
82                         return 47
83                 }
84                 if a > b { // ERROR "Disproved Greater64$"
85                         return 50
86                 }
87                 if a < b { // ERROR "Proved Less64$"
88                         return 53
89                 }
90                 // We can't get to this point and prove knows that, so
91                 // there's no message for the next (obvious) branch.
92                 if a != a {
93                         return 56
94                 }
95                 return 61
96         }
97         return 63
98 }
99
100 func f4b(a, b, c int) int {
101         if a <= b {
102                 if a >= b {
103                         if a == b { // ERROR "Proved Eq64$"
104                                 return 70
105                         }
106                         return 75
107                 }
108                 return 77
109         }
110         return 79
111 }
112
113 func f4c(a, b, c int) int {
114         if a <= b {
115                 if a >= b {
116                         if a != b { // ERROR "Disproved Neq64$"
117                                 return 73
118                         }
119                         return 75
120                 }
121                 return 77
122         }
123         return 79
124 }
125
126 func f4d(a, b, c int) int {
127         if a < b {
128                 if a < c {
129                         if a < b { // ERROR "Proved Less64$"
130                                 if a < c { // ERROR "Proved Less64$"
131                                         return 87
132                                 }
133                                 return 89
134                         }
135                         return 91
136                 }
137                 return 93
138         }
139         return 95
140 }
141
142 func f4e(a, b, c int) int {
143         if a < b {
144                 if b > a { // ERROR "Proved Greater64$"
145                         return 101
146                 }
147                 return 103
148         }
149         return 105
150 }
151
152 func f4f(a, b, c int) int {
153         if a <= b {
154                 if b > a {
155                         if b == a { // ERROR "Disproved Eq64$"
156                                 return 112
157                         }
158                         return 114
159                 }
160                 if b >= a { // ERROR "Proved Geq64$"
161                         if b == a { // ERROR "Proved Eq64$"
162                                 return 118
163                         }
164                         return 120
165                 }
166                 return 122
167         }
168         return 124
169 }
170
171 func f5(a, b uint) int {
172         if a == b {
173                 if a <= b { // ERROR "Proved Leq64U$"
174                         return 130
175                 }
176                 return 132
177         }
178         return 134
179 }
180
181 // These comparisons are compile time constants.
182 func f6a(a uint8) int {
183         if a < a { // ERROR "Disproved Less8U$"
184                 return 140
185         }
186         return 151
187 }
188
189 func f6b(a uint8) int {
190         if a < a { // ERROR "Disproved Less8U$"
191                 return 140
192         }
193         return 151
194 }
195
196 func f6x(a uint8) int {
197         if a > a { // ERROR "Disproved Greater8U$"
198                 return 143
199         }
200         return 151
201 }
202
203 func f6d(a uint8) int {
204         if a <= a { // ERROR "Proved Leq8U$"
205                 return 146
206         }
207         return 151
208 }
209
210 func f6e(a uint8) int {
211         if a >= a { // ERROR "Proved Geq8U$"
212                 return 149
213         }
214         return 151
215 }
216
217 func f7(a []int, b int) int {
218         if b < len(a) {
219                 a[b] = 3
220                 if b < len(a) { // ERROR "Proved Less64$"
221                         a[b] = 5 // ERROR "Proved IsInBounds$"
222                 }
223         }
224         return 161
225 }
226
227 func f8(a, b uint) int {
228         if a == b {
229                 return 166
230         }
231         if a > b {
232                 return 169
233         }
234         if a < b { // ERROR "Proved Less64U$"
235                 return 172
236         }
237         return 174
238 }
239
240 func f9(a, b bool) int {
241         if a {
242                 return 1
243         }
244         if a || b { // ERROR "Disproved Arg$"
245                 return 2
246         }
247         return 3
248 }
249
250 func f10(a string) int {
251         n := len(a)
252         // We optimize comparisons with small constant strings (see cmd/compile/internal/gc/walk.go),
253         // so this string literal must be long.
254         if a[:n>>1] == "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" {
255                 return 0
256         }
257         return 1
258 }
259
260 func f11a(a []int, i int) {
261         useInt(a[i])
262         useInt(a[i]) // ERROR "Proved IsInBounds$"
263 }
264
265 func f11b(a []int, i int) {
266         useSlice(a[i:])
267         useSlice(a[i:]) // ERROR "Proved IsSliceInBounds$"
268 }
269
270 func f11c(a []int, i int) {
271         useSlice(a[:i])
272         useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
273 }
274
275 func f11d(a []int, i int) {
276         useInt(a[2*i+7])
277         useInt(a[2*i+7]) // ERROR "Proved IsInBounds$"
278 }
279
280 func f12(a []int, b int) {
281         useSlice(a[:b])
282 }
283
284 func f13a(a, b, c int, x bool) int {
285         if a > 12 {
286                 if x {
287                         if a < 12 { // ERROR "Disproved Less64$"
288                                 return 1
289                         }
290                 }
291                 if x {
292                         if a <= 12 { // ERROR "Disproved Leq64$"
293                                 return 2
294                         }
295                 }
296                 if x {
297                         if a == 12 { // ERROR "Disproved Eq64$"
298                                 return 3
299                         }
300                 }
301                 if x {
302                         if a >= 12 { // ERROR "Proved Geq64$"
303                                 return 4
304                         }
305                 }
306                 if x {
307                         if a > 12 { // ERROR "Proved Greater64$"
308                                 return 5
309                         }
310                 }
311                 return 6
312         }
313         return 0
314 }
315
316 func f13b(a int, x bool) int {
317         if a == -9 {
318                 if x {
319                         if a < -9 { // ERROR "Disproved Less64$"
320                                 return 7
321                         }
322                 }
323                 if x {
324                         if a <= -9 { // ERROR "Proved Leq64$"
325                                 return 8
326                         }
327                 }
328                 if x {
329                         if a == -9 { // ERROR "Proved Eq64$"
330                                 return 9
331                         }
332                 }
333                 if x {
334                         if a >= -9 { // ERROR "Proved Geq64$"
335                                 return 10
336                         }
337                 }
338                 if x {
339                         if a > -9 { // ERROR "Disproved Greater64$"
340                                 return 11
341                         }
342                 }
343                 return 12
344         }
345         return 0
346 }
347
348 func f13c(a int, x bool) int {
349         if a < 90 {
350                 if x {
351                         if a < 90 { // ERROR "Proved Less64$"
352                                 return 13
353                         }
354                 }
355                 if x {
356                         if a <= 90 { // ERROR "Proved Leq64$"
357                                 return 14
358                         }
359                 }
360                 if x {
361                         if a == 90 { // ERROR "Disproved Eq64$"
362                                 return 15
363                         }
364                 }
365                 if x {
366                         if a >= 90 { // ERROR "Disproved Geq64$"
367                                 return 16
368                         }
369                 }
370                 if x {
371                         if a > 90 { // ERROR "Disproved Greater64$"
372                                 return 17
373                         }
374                 }
375                 return 18
376         }
377         return 0
378 }
379
380 func f13d(a int) int {
381         if a < 5 {
382                 if a < 9 { // ERROR "Proved Less64$"
383                         return 1
384                 }
385         }
386         return 0
387 }
388
389 func f13e(a int) int {
390         if a > 9 {
391                 if a > 5 { // ERROR "Proved Greater64$"
392                         return 1
393                 }
394         }
395         return 0
396 }
397
398 func f13f(a int64) int64 {
399         if a > math.MaxInt64 {
400                 if a == 0 { // ERROR "Disproved Eq64$"
401                         return 1
402                 }
403         }
404         return 0
405 }
406
407 func f13g(a int) int {
408         if a < 3 {
409                 return 5
410         }
411         if a > 3 {
412                 return 6
413         }
414         if a == 3 { // ERROR "Proved Eq64$"
415                 return 7
416         }
417         return 8
418 }
419
420 func f13h(a int) int {
421         if a < 3 {
422                 if a > 1 {
423                         if a == 2 { // ERROR "Proved Eq64$"
424                                 return 5
425                         }
426                 }
427         }
428         return 0
429 }
430
431 func f13i(a uint) int {
432         if a == 0 {
433                 return 1
434         }
435         if a > 0 { // ERROR "Proved Greater64U$"
436                 return 2
437         }
438         return 3
439 }
440
441 func f14(p, q *int, a []int) {
442         // This crazy ordering usually gives i1 the lowest value ID,
443         // j the middle value ID, and i2 the highest value ID.
444         // That used to confuse CSE because it ordered the args
445         // of the two + ops below differently.
446         // That in turn foiled bounds check elimination.
447         i1 := *p
448         j := *q
449         i2 := *p
450         useInt(a[i1+j])
451         useInt(a[i2+j]) // ERROR "Proved IsInBounds$"
452 }
453
454 func f15(s []int, x int) {
455         useSlice(s[x:])
456         useSlice(s[:x]) // ERROR "Proved IsSliceInBounds$"
457 }
458
459 func f16(s []int) []int {
460         if len(s) >= 10 {
461                 return s[:10] // ERROR "Proved IsSliceInBounds$"
462         }
463         return nil
464 }
465
466 func f17(b []int) {
467         for i := 0; i < len(b); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1"
468                 // This tests for i <= cap, which we can only prove
469                 // using the derived relation between len and cap.
470                 // This depends on finding the contradiction, since we
471                 // don't query this condition directly.
472                 useSlice(b[:i]) // ERROR "Proved IsSliceInBounds$"
473         }
474 }
475
476 func f18(b []int, x int, y uint) {
477         _ = b[x]
478         _ = b[y]
479
480         if x > len(b) { // ERROR "Disproved Greater64$"
481                 return
482         }
483         if y > uint(len(b)) { // ERROR "Disproved Greater64U$"
484                 return
485         }
486         if int(y) > len(b) { // ERROR "Disproved Greater64$"
487                 return
488         }
489 }
490
491 func sm1(b []int, x int) {
492         // Test constant argument to slicemask.
493         useSlice(b[2:8]) // ERROR "Proved slicemask not needed$"
494         // Test non-constant argument with known limits.
495         if cap(b) > 10 {
496                 useSlice(b[2:]) // ERROR "Proved slicemask not needed$"
497         }
498 }
499
500 func lim1(x, y, z int) {
501         // Test relations between signed and unsigned limits.
502         if x > 5 {
503                 if uint(x) > 5 { // ERROR "Proved Greater64U$"
504                         return
505                 }
506         }
507         if y >= 0 && y < 4 {
508                 if uint(y) > 4 { // ERROR "Disproved Greater64U$"
509                         return
510                 }
511                 if uint(y) < 5 { // ERROR "Proved Less64U$"
512                         return
513                 }
514         }
515         if z < 4 {
516                 if uint(z) > 4 { // Not provable without disjunctions.
517                         return
518                 }
519         }
520 }
521
522 // fence1–4 correspond to the four fence-post implications.
523
524 func fence1(b []int, x, y int) {
525         // Test proofs that rely on fence-post implications.
526         if x+1 > y {
527                 if x < y { // ERROR "Disproved Less64$"
528                         return
529                 }
530         }
531         if len(b) < cap(b) {
532                 // This eliminates the growslice path.
533                 b = append(b, 1) // ERROR "Disproved Greater64$"
534         }
535 }
536
537 func fence2(x, y int) {
538         if x-1 < y {
539                 if x > y { // ERROR "Disproved Greater64$"
540                         return
541                 }
542         }
543 }
544
545 func fence3(b, c []int, x, y int64) {
546         if x-1 >= y {
547                 if x <= y { // Can't prove because x may have wrapped.
548                         return
549                 }
550         }
551
552         if x != math.MinInt64 && x-1 >= y {
553                 if x <= y { // ERROR "Disproved Leq64$"
554                         return
555                 }
556         }
557
558         c[len(c)-1] = 0 // Can't prove because len(c) might be 0
559
560         if n := len(b); n > 0 {
561                 b[n-1] = 0 // ERROR "Proved IsInBounds$"
562         }
563 }
564
565 func fence4(x, y int64) {
566         if x >= y+1 {
567                 if x <= y {
568                         return
569                 }
570         }
571         if y != math.MaxInt64 && x >= y+1 {
572                 if x <= y { // ERROR "Disproved Leq64$"
573                         return
574                 }
575         }
576 }
577
578 // Check transitive relations
579 func trans1(x, y int64) {
580         if x > 5 {
581                 if y > x {
582                         if y > 2 { // ERROR "Proved Greater64"
583                                 return
584                         }
585                 } else if y == x {
586                         if y > 5 { // ERROR "Proved Greater64"
587                                 return
588                         }
589                 }
590         }
591         if x >= 10 {
592                 if y > x {
593                         if y > 10 { // ERROR "Proved Greater64"
594                                 return
595                         }
596                 }
597         }
598 }
599
600 func trans2(a, b []int, i int) {
601         if len(a) != len(b) {
602                 return
603         }
604
605         _ = a[i]
606         _ = b[i] // ERROR "Proved IsInBounds$"
607 }
608
609 func trans3(a, b []int, i int) {
610         if len(a) > len(b) {
611                 return
612         }
613
614         _ = a[i]
615         _ = b[i] // ERROR "Proved IsInBounds$"
616 }
617
618 // Derived from nat.cmp
619 func natcmp(x, y []uint) (r int) {
620         m := len(x)
621         n := len(y)
622         if m != n || m == 0 {
623                 return
624         }
625
626         i := m - 1
627         for i > 0 && // ERROR "Induction variable: limits \(0,\?\], increment 1"
628                 x[i] == // ERROR "Proved IsInBounds$"
629                         y[i] { // ERROR "Proved IsInBounds$"
630                 i--
631         }
632
633         switch {
634         case x[i] < // todo, cannot prove this because it's dominated by i<=0 || x[i]==y[i]
635                 y[i]: // ERROR "Proved IsInBounds$"
636                 r = -1
637         case x[i] > // ERROR "Proved IsInBounds$"
638                 y[i]: // ERROR "Proved IsInBounds$"
639                 r = 1
640         }
641         return
642 }
643
644 func suffix(s, suffix string) bool {
645         // todo, we're still not able to drop the bound check here in the general case
646         return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
647 }
648
649 func constsuffix(s string) bool {
650         return suffix(s, "abc") // ERROR "Proved IsSliceInBounds$"
651 }
652
653 // oforuntil tests the pattern created by OFORUNTIL blocks. These are
654 // handled by addLocalInductiveFacts rather than findIndVar.
655 func oforuntil(b []int) {
656         i := 0
657         if len(b) > i {
658         top:
659                 println(b[i]) // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
660                 i++
661                 if i < len(b) {
662                         goto top
663                 }
664         }
665 }
666
667 // The range tests below test the index variable of range loops.
668
669 // range1 compiles to the "efficiently indexable" form of a range loop.
670 func range1(b []int) {
671         for i, v := range b { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
672                 b[i] = v + 1    // ERROR "Proved IsInBounds$"
673                 if i < len(b) { // ERROR "Proved Less64$"
674                         println("x")
675                 }
676                 if i >= 0 { // ERROR "Proved Geq64$"
677                         println("x")
678                 }
679         }
680 }
681
682 // range2 elements are larger, so they use the general form of a range loop.
683 func range2(b [][32]int) {
684         for i, v := range b {
685                 b[i][0] = v[0] + 1 // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
686                 if i < len(b) {    // ERROR "Proved Less64$"
687                         println("x")
688                 }
689                 if i >= 0 { // ERROR "Proved Geq64"
690                         println("x")
691                 }
692         }
693 }
694
695 //go:noinline
696 func useInt(a int) {
697 }
698
699 //go:noinline
700 func useSlice(a []int) {
701 }
702
703 func main() {
704 }