]> Cypherpunks.ru repositories - gostls13.git/blob - test/prove.go
cmd/compile: check indirect connection between if block and phi block in addLocalIndu...
[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 Less64$"
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 Less64$"
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 Leq64$"
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 Less8U$"
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 Leq8U$"
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 Leq64$"
303                                 return 4
304                         }
305                 }
306                 if x {
307                         if a > 12 { // ERROR "Proved Less64$"
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 Leq64$"
335                                 return 10
336                         }
337                 }
338                 if x {
339                         if a > -9 { // ERROR "Disproved Less64$"
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 Leq64$"
367                                 return 16
368                         }
369                 }
370                 if x {
371                         if a > 90 { // ERROR "Disproved Less64$"
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 Less64$"
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 Less64U$"
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 Less64$"
481                 return
482         }
483         if y > uint(len(b)) { // ERROR "Disproved Less64U$"
484                 return
485         }
486         if int(y) > len(b) { // ERROR "Disproved Less64$"
487                 return
488         }
489 }
490
491 func f19() (e int64, err error) {
492         // Issue 29502: slice[:0] is incorrectly disproved.
493         var stack []int64
494         stack = append(stack, 123)
495         if len(stack) > 1 {
496                 panic("too many elements")
497         }
498         last := len(stack) - 1
499         e = stack[last]
500         // Buggy compiler prints "Disproved Leq64" for the next line.
501         stack = stack[:last] // ERROR "Proved IsSliceInBounds"
502         return e, nil
503 }
504
505 func sm1(b []int, x int) {
506         // Test constant argument to slicemask.
507         useSlice(b[2:8]) // ERROR "Proved slicemask not needed$"
508         // Test non-constant argument with known limits.
509         if cap(b) > 10 {
510                 useSlice(b[2:])
511         }
512 }
513
514 func lim1(x, y, z int) {
515         // Test relations between signed and unsigned limits.
516         if x > 5 {
517                 if uint(x) > 5 { // ERROR "Proved Less64U$"
518                         return
519                 }
520         }
521         if y >= 0 && y < 4 {
522                 if uint(y) > 4 { // ERROR "Disproved Less64U$"
523                         return
524                 }
525                 if uint(y) < 5 { // ERROR "Proved Less64U$"
526                         return
527                 }
528         }
529         if z < 4 {
530                 if uint(z) > 4 { // Not provable without disjunctions.
531                         return
532                 }
533         }
534 }
535
536 // fence1–4 correspond to the four fence-post implications.
537
538 func fence1(b []int, x, y int) {
539         // Test proofs that rely on fence-post implications.
540         if x+1 > y {
541                 if x < y { // ERROR "Disproved Less64$"
542                         return
543                 }
544         }
545         if len(b) < cap(b) {
546                 // This eliminates the growslice path.
547                 b = append(b, 1) // ERROR "Disproved Less64U$"
548         }
549 }
550
551 func fence2(x, y int) {
552         if x-1 < y {
553                 if x > y { // ERROR "Disproved Less64$"
554                         return
555                 }
556         }
557 }
558
559 func fence3(b, c []int, x, y int64) {
560         if x-1 >= y {
561                 if x <= y { // Can't prove because x may have wrapped.
562                         return
563                 }
564         }
565
566         if x != math.MinInt64 && x-1 >= y {
567                 if x <= y { // ERROR "Disproved Leq64$"
568                         return
569                 }
570         }
571
572         c[len(c)-1] = 0 // Can't prove because len(c) might be 0
573
574         if n := len(b); n > 0 {
575                 b[n-1] = 0 // ERROR "Proved IsInBounds$"
576         }
577 }
578
579 func fence4(x, y int64) {
580         if x >= y+1 {
581                 if x <= y {
582                         return
583                 }
584         }
585         if y != math.MaxInt64 && x >= y+1 {
586                 if x <= y { // ERROR "Disproved Leq64$"
587                         return
588                 }
589         }
590 }
591
592 // Check transitive relations
593 func trans1(x, y int64) {
594         if x > 5 {
595                 if y > x {
596                         if y > 2 { // ERROR "Proved Less64$"
597                                 return
598                         }
599                 } else if y == x {
600                         if y > 5 { // ERROR "Proved Less64$"
601                                 return
602                         }
603                 }
604         }
605         if x >= 10 {
606                 if y > x {
607                         if y > 10 { // ERROR "Proved Less64$"
608                                 return
609                         }
610                 }
611         }
612 }
613
614 func trans2(a, b []int, i int) {
615         if len(a) != len(b) {
616                 return
617         }
618
619         _ = a[i]
620         _ = b[i] // ERROR "Proved IsInBounds$"
621 }
622
623 func trans3(a, b []int, i int) {
624         if len(a) > len(b) {
625                 return
626         }
627
628         _ = a[i]
629         _ = b[i] // ERROR "Proved IsInBounds$"
630 }
631
632 // Derived from nat.cmp
633 func natcmp(x, y []uint) (r int) {
634         m := len(x)
635         n := len(y)
636         if m != n || m == 0 {
637                 return
638         }
639
640         i := m - 1
641         for i > 0 && // ERROR "Induction variable: limits \(0,\?\], increment 1$"
642                 x[i] == // ERROR "Proved IsInBounds$"
643                         y[i] { // ERROR "Proved IsInBounds$"
644                 i--
645         }
646
647         switch {
648         case x[i] < // todo, cannot prove this because it's dominated by i<=0 || x[i]==y[i]
649                 y[i]: // ERROR "Proved IsInBounds$"
650                 r = -1
651         case x[i] > // ERROR "Proved IsInBounds$"
652                 y[i]: // ERROR "Proved IsInBounds$"
653                 r = 1
654         }
655         return
656 }
657
658 func suffix(s, suffix string) bool {
659         // todo, we're still not able to drop the bound check here in the general case
660         return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
661 }
662
663 func constsuffix(s string) bool {
664         return suffix(s, "abc") // ERROR "Proved IsSliceInBounds$"
665 }
666
667 // oforuntil tests the pattern created by OFORUNTIL blocks. These are
668 // handled by addLocalInductiveFacts rather than findIndVar.
669 func oforuntil(b []int) {
670         i := 0
671         if len(b) > i {
672         top:
673                 println(b[i]) // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
674                 i++
675                 if i < len(b) {
676                         goto top
677                 }
678         }
679 }
680
681 func atexit(foobar []func()) {
682         for i := len(foobar) - 1; i >= 0; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1"
683                 f := foobar[i]
684                 foobar = foobar[:i] // ERROR "IsSliceInBounds"
685                 f()
686         }
687 }
688
689 func make1(n int) []int {
690         s := make([]int, n)
691         for i := 0; i < n; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1"
692                 s[i] = 1 // ERROR "Proved IsInBounds$"
693         }
694         return s
695 }
696
697 func make2(n int) []int {
698         s := make([]int, n)
699         for i := range s { // ERROR "Induction variable: limits \[0,\?\), increment 1"
700                 s[i] = 1 // ERROR "Proved IsInBounds$"
701         }
702         return s
703 }
704
705 // The range tests below test the index variable of range loops.
706
707 // range1 compiles to the "efficiently indexable" form of a range loop.
708 func range1(b []int) {
709         for i, v := range b { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
710                 b[i] = v + 1    // ERROR "Proved IsInBounds$"
711                 if i < len(b) { // ERROR "Proved Less64$"
712                         println("x")
713                 }
714                 if i >= 0 { // ERROR "Proved Leq64$"
715                         println("x")
716                 }
717         }
718 }
719
720 // range2 elements are larger, so they use the general form of a range loop.
721 func range2(b [][32]int) {
722         for i, v := range b {
723                 b[i][0] = v[0] + 1 // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
724                 if i < len(b) {    // ERROR "Proved Less64$"
725                         println("x")
726                 }
727                 if i >= 0 { // ERROR "Proved Leq64$"
728                         println("x")
729                 }
730         }
731 }
732
733 // signhint1-2 test whether the hint (int >= 0) is propagated into the loop.
734 func signHint1(i int, data []byte) {
735         if i >= 0 {
736                 for i < len(data) { // ERROR "Induction variable: limits \[\?,\?\), increment 1$"
737                         _ = data[i] // ERROR "Proved IsInBounds$"
738                         i++
739                 }
740         }
741 }
742
743 func signHint2(b []byte, n int) {
744         if n < 0 {
745                 panic("")
746         }
747         _ = b[25]
748         for i := n; i <= 25; i++ { // ERROR "Induction variable: limits \[\?,25\], increment 1$"
749                 b[i] = 123 // ERROR "Proved IsInBounds$"
750         }
751 }
752
753 // indexGT0 tests whether prove learns int index >= 0 from bounds check.
754 func indexGT0(b []byte, n int) {
755         _ = b[n]
756         _ = b[25]
757
758         for i := n; i <= 25; i++ { // ERROR "Induction variable: limits \[\?,25\], increment 1$"
759                 b[i] = 123 // ERROR "Proved IsInBounds$"
760         }
761 }
762
763 // Induction variable in unrolled loop.
764 func unrollUpExcl(a []int) int {
765         var i, x int
766         for i = 0; i < len(a)-1; i += 2 { // ERROR "Induction variable: limits \[0,\?\), increment 2$"
767                 x += a[i] // ERROR "Proved IsInBounds$"
768                 x += a[i+1]
769         }
770         if i == len(a)-1 {
771                 x += a[i]
772         }
773         return x
774 }
775
776 // Induction variable in unrolled loop.
777 func unrollUpIncl(a []int) int {
778         var i, x int
779         for i = 0; i <= len(a)-2; i += 2 { // ERROR "Induction variable: limits \[0,\?\], increment 2$"
780                 x += a[i]
781                 x += a[i+1]
782         }
783         if i == len(a)-1 {
784                 x += a[i]
785         }
786         return x
787 }
788
789 // Induction variable in unrolled loop.
790 func unrollDownExcl0(a []int) int {
791         var i, x int
792         for i = len(a) - 1; i > 0; i -= 2 { // ERROR "Induction variable: limits \(0,\?\], increment 2$"
793                 x += a[i]   // ERROR "Proved IsInBounds$"
794                 x += a[i-1] // ERROR "Proved IsInBounds$"
795         }
796         if i == 0 {
797                 x += a[i]
798         }
799         return x
800 }
801
802 // Induction variable in unrolled loop.
803 func unrollDownExcl1(a []int) int {
804         var i, x int
805         for i = len(a) - 1; i >= 1; i -= 2 { // ERROR "Induction variable: limits \[1,\?\], increment 2$"
806                 x += a[i]   // ERROR "Proved IsInBounds$"
807                 x += a[i-1] // ERROR "Proved IsInBounds$"
808         }
809         if i == 0 {
810                 x += a[i]
811         }
812         return x
813 }
814
815 // Induction variable in unrolled loop.
816 func unrollDownInclStep(a []int) int {
817         var i, x int
818         for i = len(a); i >= 2; i -= 2 { // ERROR "Induction variable: limits \[2,\?\], increment 2$"
819                 x += a[i-1] // ERROR "Proved IsInBounds$"
820                 x += a[i-2]
821         }
822         if i == 1 {
823                 x += a[i-1]
824         }
825         return x
826 }
827
828 // Not an induction variable (step too large)
829 func unrollExclStepTooLarge(a []int) int {
830         var i, x int
831         for i = 0; i < len(a)-1; i += 3 {
832                 x += a[i]
833                 x += a[i+1]
834         }
835         if i == len(a)-1 {
836                 x += a[i]
837         }
838         return x
839 }
840
841 // Not an induction variable (step too large)
842 func unrollInclStepTooLarge(a []int) int {
843         var i, x int
844         for i = 0; i <= len(a)-2; i += 3 {
845                 x += a[i]
846                 x += a[i+1]
847         }
848         if i == len(a)-1 {
849                 x += a[i]
850         }
851         return x
852 }
853
854 // Not an induction variable (min too small, iterating down)
855 func unrollDecMin(a []int) int {
856         var i, x int
857         for i = len(a); i >= math.MinInt64; i -= 2 {
858                 x += a[i-1]
859                 x += a[i-2]
860         }
861         if i == 1 { // ERROR "Disproved Eq64$"
862                 x += a[i-1]
863         }
864         return x
865 }
866
867 // Not an induction variable (min too small, iterating up -- perhaps could allow, but why bother?)
868 func unrollIncMin(a []int) int {
869         var i, x int
870         for i = len(a); i >= math.MinInt64; i += 2 {
871                 x += a[i-1]
872                 x += a[i-2]
873         }
874         if i == 1 { // ERROR "Disproved Eq64$"
875                 x += a[i-1]
876         }
877         return x
878 }
879
880 // The 4 xxxxExtNto64 functions below test whether prove is looking
881 // through value-preserving sign/zero extensions of index values (issue #26292).
882
883 // Look through all extensions
884 func signExtNto64(x []int, j8 int8, j16 int16, j32 int32) int {
885         if len(x) < 22 {
886                 return 0
887         }
888         if j8 >= 0 && j8 < 22 {
889                 return x[j8] // ERROR "Proved IsInBounds$"
890         }
891         if j16 >= 0 && j16 < 22 {
892                 return x[j16] // ERROR "Proved IsInBounds$"
893         }
894         if j32 >= 0 && j32 < 22 {
895                 return x[j32] // ERROR "Proved IsInBounds$"
896         }
897         return 0
898 }
899
900 func zeroExtNto64(x []int, j8 uint8, j16 uint16, j32 uint32) int {
901         if len(x) < 22 {
902                 return 0
903         }
904         if j8 >= 0 && j8 < 22 {
905                 return x[j8] // ERROR "Proved IsInBounds$"
906         }
907         if j16 >= 0 && j16 < 22 {
908                 return x[j16] // ERROR "Proved IsInBounds$"
909         }
910         if j32 >= 0 && j32 < 22 {
911                 return x[j32] // ERROR "Proved IsInBounds$"
912         }
913         return 0
914 }
915
916 // Process fence-post implications through 32to64 extensions (issue #29964)
917 func signExt32to64Fence(x []int, j int32) int {
918         if x[j] != 0 {
919                 return 1
920         }
921         if j > 0 && x[j-1] != 0 { // ERROR "Proved IsInBounds$"
922                 return 1
923         }
924         return 0
925 }
926
927 func zeroExt32to64Fence(x []int, j uint32) int {
928         if x[j] != 0 {
929                 return 1
930         }
931         if j > 0 && x[j-1] != 0 { // ERROR "Proved IsInBounds$"
932                 return 1
933         }
934         return 0
935 }
936
937 // Ensure that bounds checks with negative indexes are not incorrectly removed.
938 func negIndex() {
939         n := make([]int, 1)
940         for i := -1; i <= 0; i++ { // ERROR "Induction variable: limits \[-1,0\], increment 1$"
941                 n[i] = 1
942         }
943 }
944 func negIndex2(n int) {
945         a := make([]int, 5)
946         b := make([]int, 5)
947         c := make([]int, 5)
948         for i := -1; i <= 0; i-- {
949                 b[i] = i
950                 n++
951                 if n > 10 {
952                         break
953                 }
954         }
955         useSlice(a)
956         useSlice(c)
957 }
958
959 // Check that prove is zeroing these right shifts of positive ints by bit-width - 1.
960 // e.g (Rsh64x64 <t> n (Const64 <typ.UInt64> [63])) && ft.isNonNegative(n) -> 0
961 func sh64(n int64) int64 {
962         if n < 0 {
963                 return n
964         }
965         return n >> 63 // ERROR "Proved Rsh64x64 shifts to zero"
966 }
967
968 func sh32(n int32) int32 {
969         if n < 0 {
970                 return n
971         }
972         return n >> 31 // ERROR "Proved Rsh32x64 shifts to zero"
973 }
974
975 func sh32x64(n int32) int32 {
976         if n < 0 {
977                 return n
978         }
979         return n >> uint64(31) // ERROR "Proved Rsh32x64 shifts to zero"
980 }
981
982 func sh16(n int16) int16 {
983         if n < 0 {
984                 return n
985         }
986         return n >> 15 // ERROR "Proved Rsh16x64 shifts to zero"
987 }
988
989 func sh64noopt(n int64) int64 {
990         return n >> 63 // not optimized; n could be negative
991 }
992
993 // These cases are division of a positive signed integer by a power of 2.
994 // The opt pass doesnt have sufficient information to see that n is positive.
995 // So, instead, opt rewrites the division with a less-than-optimal replacement.
996 // Prove, which can see that n is nonnegative, cannot see the division because
997 // opt, an earlier pass, has already replaced it.
998 // The fix for this issue allows prove to zero a right shift that was added as
999 // part of the less-than-optimal reqwrite. That change by prove then allows
1000 // lateopt to clean up all the unneccesary parts of the original division
1001 // replacement. See issue #36159.
1002 func divShiftClean(n int) int {
1003         if n < 0 {
1004                 return n
1005         }
1006         return n / int(8) // ERROR "Proved Rsh64x64 shifts to zero"
1007 }
1008
1009 func divShiftClean64(n int64) int64 {
1010         if n < 0 {
1011                 return n
1012         }
1013         return n / int64(16) // ERROR "Proved Rsh64x64 shifts to zero"
1014 }
1015
1016 func divShiftClean32(n int32) int32 {
1017         if n < 0 {
1018                 return n
1019         }
1020         return n / int32(16) // ERROR "Proved Rsh32x64 shifts to zero"
1021 }
1022
1023 //go:noinline
1024 func useInt(a int) {
1025 }
1026
1027 //go:noinline
1028 func useSlice(a []int) {
1029 }
1030
1031 func main() {
1032 }