]> Cypherpunks.ru repositories - gostls13.git/blob - test/index.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / index.go
1 // skip
2
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Generate test of index and slice bounds checks.
8 // The actual tests are index0.go, index1.go, index2.go.
9
10 package main
11
12 import (
13         "bufio"
14         "fmt"
15         "os"
16         "unsafe"
17 )
18
19 const prolog = `
20
21 package main
22
23 import (
24         "runtime"
25 )
26
27 type quad struct { x, y, z, w int }
28
29 const (
30         cj = 100011
31         ci int = 100012
32         ci8 int8 = 115
33         ci16 int16 = 10016
34         ci32 int32 = 100013
35         ci64 int64 = 100014
36         ci64big int64 = 1<<31
37         ci64bigger int64 = 1<<32
38         chuge = 1<<100
39         cfgood = 2.0
40         cfbad = 2.1
41
42         cnj = -2
43         cni int = -3
44         cni8 int8 = -6
45         cni16 int16 = -7
46         cni32 int32 = -4
47         cni64 int64 = -5
48         cni64big int64 = -1<<31
49         cni64bigger int64 = -1<<32
50         cnhuge = -1<<100
51         cnfgood = -2.0
52         cnfbad = -2.1
53 )
54
55 var j int = 100020
56 var i int = 100021
57 var i8 int8 = 126
58 var i16 int16 = 10025
59 var i32 int32 = 100022
60 var i64 int64 = 100023
61 var i64big int64 = 1<<31
62 var i64bigger int64 = 1<<32
63 var huge uint64 = 1<<64 - 1
64 var fgood float64 = 2.0
65 var fbad float64 = 2.1
66
67 var nj int = -10
68 var ni int = -11
69 var ni8 int8 = -14
70 var ni16 int16 = -15
71 var ni32 int32 = -12
72 var ni64 int64 = -13
73 var ni64big int64 = -1<<31
74 var ni64bigger int64 = -1<<32
75 var nhuge int64 = -1<<63
76 var nfgood float64 = -2.0
77 var nfbad float64 = -2.1
78
79 var si []int = make([]int, 10)
80 var ai [10]int
81 var pai *[10]int = &ai
82
83 var sq []quad = make([]quad, 10)
84 var aq [10]quad
85 var paq *[10]quad = &aq
86
87 var sib []int = make([]int, 100000)
88 var aib [100000]int
89 var paib *[100000]int = &aib
90
91 var sqb []quad = make([]quad, 100000)
92 var aqb [100000]quad
93 var paqb *[100000]quad = &aqb
94
95 type T struct {
96         si []int
97         ai [10]int
98         pai *[10]int
99         sq []quad
100         aq [10]quad
101         paq *[10]quad
102
103         sib []int
104         aib [100000]int
105         paib *[100000]int
106         sqb []quad
107         aqb [100000]quad
108         paqb *[100000]quad
109 }
110
111 var t = T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}
112
113 var pt = &T{si, ai, pai, sq, aq, paq, sib, aib, paib, sqb, aqb, paqb}
114
115 // test that f panics
116 func test(f func(), s string) {
117         defer func() {
118                 if err := recover(); err == nil {
119                         _, file, line, _ := runtime.Caller(2)
120                         bug()
121                         print(file, ":", line, ": ", s, " did not panic\n")
122                 } else if !contains(err.(error).Error(), "out of range") {
123                         _, file, line, _ := runtime.Caller(2)
124                         bug()
125                         print(file, ":", line, ": ", s, " unexpected panic: ", err.(error).Error(), "\n")
126                 }
127         }()
128         f()
129 }
130
131 func contains(x, y string) bool {
132         for i := 0; i+len(y) <= len(x); i++ {
133                 if x[i:i+len(y)] == y {
134                         return true
135                 }
136         }
137         return false
138 }
139
140
141 var X interface{}
142 func use(y interface{}) {
143         X = y
144 }
145
146 var didBug = false
147
148 func bug() {
149         if !didBug {
150                 didBug = true
151                 println("BUG")
152         }
153 }
154
155 func main() {
156 `
157
158 // pass variable set in index[012].go
159 //      0 - dynamic checks
160 //      1 - static checks of invalid constants (cannot assign to types)
161 //      2 - static checks of array bounds
162
163 func testExpr(b *bufio.Writer, expr string) {
164         if pass == 0 {
165                 fmt.Fprintf(b, "\ttest(func(){use(%s)}, %q)\n", expr, expr)
166         } else {
167                 fmt.Fprintf(b, "\tuse(%s)  // ERROR \"index|overflow|truncated|must be integer\"\n", expr)
168         }
169 }
170
171 func main() {
172         b := bufio.NewWriter(os.Stdout)
173
174         if pass == 0 {
175                 fmt.Fprint(b, "// run\n\n")
176         } else {
177                 fmt.Fprint(b, "// errorcheck\n\n")
178         }
179         fmt.Fprint(b, prolog)
180
181         var choices = [][]string{
182                 // Direct value, fetch from struct, fetch from struct pointer.
183                 // The last two cases get us to oindex_const_sudo in gsubr.c.
184                 []string{"", "t.", "pt."},
185
186                 // Array, pointer to array, slice.
187                 []string{"a", "pa", "s"},
188
189                 // Element is int, element is quad (struct).
190                 // This controls whether we end up in gsubr.c (i) or cgen.c (q).
191                 []string{"i", "q"},
192
193                 // Small or big len.
194                 []string{"", "b"},
195
196                 // Variable or constant.
197                 []string{"", "c"},
198
199                 // Positive or negative.
200                 []string{"", "n"},
201
202                 // Size of index.
203                 []string{"j", "i", "i8", "i16", "i32", "i64", "i64big", "i64bigger", "huge", "fgood", "fbad"},
204         }
205
206         forall(choices, func(x []string) {
207                 p, a, e, big, c, n, i := x[0], x[1], x[2], x[3], x[4], x[5], x[6]
208
209                 // Pass: dynamic=0, static=1, 2.
210                 // Which cases should be caught statically?
211                 // Only constants, obviously.
212                 // Beyond that, must be one of these:
213                 //      indexing into array or pointer to array
214                 //      negative constant
215                 //      large constant
216                 thisPass := 0
217                 if c == "c" && (a == "a" || a == "pa" || n == "n" || i == "i64big" || i == "i64bigger" || i == "huge" || i == "fbad") {
218                         if i == "huge" {
219                                 // Due to a detail of gc's internals,
220                                 // the huge constant errors happen in an
221                                 // earlier pass than the others and inhibits
222                                 // the next pass from running.
223                                 // So run it as a separate check.
224                                 thisPass = 1
225                         } else if a == "s" && n == "" && (i == "i64big" || i == "i64bigger") && unsafe.Sizeof(int(0)) > 4 {
226                                 // If int is 64 bits, these huge
227                                 // numbers do fit in an int, so they
228                                 // are not rejected at compile time.
229                                 thisPass = 0
230                         } else {
231                                 thisPass = 2
232                         }
233                 }
234
235                 pae := p + a + e + big
236                 cni := c + n + i
237
238                 // If we're using the big-len data, positive int8 and int16 cannot overflow.
239                 if big == "b" && n == "" && (i == "i8" || i == "i16") {
240                         if pass == 0 {
241                                 fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
242                                 fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
243                                 fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
244                                 fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
245                                 fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
246                         }
247                         return
248                 }
249
250                 // Float variables cannot be used as indices.
251                 if c == "" && (i == "fgood" || i == "fbad") {
252                         return
253                 }
254                 // Integral float constant is ok.
255                 if c == "c" && n == "" && i == "fgood" {
256                         if pass == 0 {
257                                 fmt.Fprintf(b, "\tuse(%s[%s])\n", pae, cni)
258                                 fmt.Fprintf(b, "\tuse(%s[0:%s])\n", pae, cni)
259                                 fmt.Fprintf(b, "\tuse(%s[1:%s])\n", pae, cni)
260                                 fmt.Fprintf(b, "\tuse(%s[%s:])\n", pae, cni)
261                                 fmt.Fprintf(b, "\tuse(%s[%s:%s])\n", pae, cni, cni)
262                         }
263                         return
264                 }
265
266                 // Only print the test case if it is appropriate for this pass.
267                 if thisPass == pass {
268                         // Index operation
269                         testExpr(b, pae+"["+cni+"]")
270
271                         // Slice operation.
272                         // Low index 0 is a special case in ggen.c
273                         // so test both 0 and 1.
274                         testExpr(b, pae+"[0:"+cni+"]")
275                         testExpr(b, pae+"[1:"+cni+"]")
276                         testExpr(b, pae+"["+cni+":]")
277                         testExpr(b, pae+"["+cni+":"+cni+"]")
278                 }
279         })
280
281         fmt.Fprintln(b, "}")
282         b.Flush()
283 }
284
285 func forall(choices [][]string, f func([]string)) {
286         x := make([]string, len(choices))
287
288         var recurse func(d int)
289         recurse = func(d int) {
290                 if d >= len(choices) {
291                         f(x)
292                         return
293                 }
294                 for _, x[d] = range choices[d] {
295                         recurse(d + 1)
296                 }
297         }
298         recurse(0)
299 }