1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "go/constant"
12 . "internal/types/errors"
13 )
14
15
16
17
18 func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst bool) {
19 check.exprOrType(x, e.X, true)
20
21
22 switch x.mode {
23 case invalid:
24 check.use(e.Index)
25 return false
26
27 case typexpr:
28
29 x.mode = invalid
30
31 x.typ = check.varType(e)
32 if isValid(x.typ) {
33 x.mode = typexpr
34 }
35 return false
36
37 case value:
38 if sig, _ := under(x.typ).(*Signature); sig != nil && sig.TypeParams().Len() > 0 {
39
40 return true
41 }
42 }
43
44
45 check.nonGeneric(nil, x)
46 if x.mode == invalid {
47 return false
48 }
49
50
51 valid := false
52 length := int64(-1)
53 switch typ := under(x.typ).(type) {
54 case *Basic:
55 if isString(typ) {
56 valid = true
57 if x.mode == constant_ {
58 length = int64(len(constant.StringVal(x.val)))
59 }
60
61
62
63 x.mode = value
64 x.typ = universeByte
65 }
66
67 case *Array:
68 valid = true
69 length = typ.len
70 if x.mode != variable {
71 x.mode = value
72 }
73 x.typ = typ.elem
74
75 case *Pointer:
76 if typ, _ := under(typ.base).(*Array); typ != nil {
77 valid = true
78 length = typ.len
79 x.mode = variable
80 x.typ = typ.elem
81 }
82
83 case *Slice:
84 valid = true
85 x.mode = variable
86 x.typ = typ.elem
87
88 case *Map:
89 index := check.singleIndex(e)
90 if index == nil {
91 x.mode = invalid
92 return false
93 }
94 var key operand
95 check.expr(nil, &key, index)
96 check.assignment(&key, typ.key, "map index")
97
98 x.mode = mapindex
99 x.typ = typ.elem
100 x.expr = e
101 return false
102
103 case *Interface:
104 if !isTypeParam(x.typ) {
105 break
106 }
107
108 var key, elem Type
109 mode := variable
110
111 if typ.typeSet().underIs(func(u Type) bool {
112 l := int64(-1)
113 var k, e Type
114 switch t := u.(type) {
115 case *Basic:
116 if isString(t) {
117 e = universeByte
118 mode = value
119 }
120 case *Array:
121 l = t.len
122 e = t.elem
123 if x.mode != variable {
124 mode = value
125 }
126 case *Pointer:
127 if t, _ := under(t.base).(*Array); t != nil {
128 l = t.len
129 e = t.elem
130 }
131 case *Slice:
132 e = t.elem
133 case *Map:
134 k = t.key
135 e = t.elem
136 }
137 if e == nil {
138 return false
139 }
140 if elem == nil {
141
142 length = l
143 key, elem = k, e
144 return true
145 }
146
147
148 if !Identical(key, k) {
149 return false
150 }
151
152 if !Identical(elem, e) {
153 return false
154 }
155
156 if l >= 0 && l < length {
157 length = l
158 }
159 return true
160 }) {
161
162 if key != nil {
163 index := check.singleIndex(e)
164 if index == nil {
165 x.mode = invalid
166 return false
167 }
168 var k operand
169 check.expr(nil, &k, index)
170 check.assignment(&k, key, "map index")
171
172 x.mode = mapindex
173 x.typ = elem
174 x.expr = e
175 return false
176 }
177
178
179 valid = true
180 x.mode = mode
181 x.typ = elem
182 }
183 }
184
185 if !valid {
186 check.errorf(e.Pos(), NonSliceableOperand, invalidOp+"cannot index %s", x)
187 check.use(e.Index)
188 x.mode = invalid
189 return false
190 }
191
192 index := check.singleIndex(e)
193 if index == nil {
194 x.mode = invalid
195 return false
196 }
197
198
199
200
201 if x.typ == nil {
202 x.typ = Typ[Invalid]
203 }
204
205 check.index(index, length)
206 return false
207 }
208
209 func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) {
210 check.expr(nil, x, e.X)
211 if x.mode == invalid {
212 check.use(e.Index[:]...)
213 return
214 }
215
216 valid := false
217 length := int64(-1)
218 switch u := coreString(x.typ).(type) {
219 case nil:
220 check.errorf(x, NonSliceableOperand, invalidOp+"cannot slice %s: %s has no core type", x, x.typ)
221 x.mode = invalid
222 return
223
224 case *Basic:
225 if isString(u) {
226 if e.Full {
227 at := e.Index[2]
228 if at == nil {
229 at = e
230 }
231 check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string")
232 x.mode = invalid
233 return
234 }
235 valid = true
236 if x.mode == constant_ {
237 length = int64(len(constant.StringVal(x.val)))
238 }
239
240
241 if isUntyped(x.typ) {
242 x.typ = Typ[String]
243 }
244 }
245
246 case *Array:
247 valid = true
248 length = u.len
249 if x.mode != variable {
250 check.errorf(x, NonSliceableOperand, invalidOp+"%s (slice of unaddressable value)", x)
251 x.mode = invalid
252 return
253 }
254 x.typ = &Slice{elem: u.elem}
255
256 case *Pointer:
257 if u, _ := under(u.base).(*Array); u != nil {
258 valid = true
259 length = u.len
260 x.typ = &Slice{elem: u.elem}
261 }
262
263 case *Slice:
264 valid = true
265
266 }
267
268 if !valid {
269 check.errorf(x, NonSliceableOperand, invalidOp+"cannot slice %s", x)
270 x.mode = invalid
271 return
272 }
273
274 x.mode = value
275
276
277 if e.Full && (e.Index[1] == nil || e.Index[2] == nil) {
278 check.error(e, InvalidSyntaxTree, "2nd and 3rd index required in 3-index slice")
279 x.mode = invalid
280 return
281 }
282
283
284 var ind [3]int64
285 for i, expr := range e.Index {
286 x := int64(-1)
287 switch {
288 case expr != nil:
289
290
291
292 max := int64(-1)
293 if length >= 0 {
294 max = length + 1
295 }
296 if _, v := check.index(expr, max); v >= 0 {
297 x = v
298 }
299 case i == 0:
300
301 x = 0
302 case length >= 0:
303
304 x = length
305 }
306 ind[i] = x
307 }
308
309
310
311 L:
312 for i, x := range ind[:len(ind)-1] {
313 if x > 0 {
314 for j, y := range ind[i+1:] {
315 if y >= 0 && y < x {
316
317
318
319 check.errorf(e.Index[i+1+j], SwappedSliceIndices, "invalid slice indices: %d < %d", y, x)
320 break L
321 }
322 }
323 }
324 }
325 }
326
327
328
329
330 func (check *Checker) singleIndex(e *syntax.IndexExpr) syntax.Expr {
331 index := e.Index
332 if index == nil {
333 check.errorf(e, InvalidSyntaxTree, "missing index for %s", e.X)
334 return nil
335 }
336 if l, _ := index.(*syntax.ListExpr); l != nil {
337 if n := len(l.ElemList); n <= 1 {
338 check.errorf(e, InvalidSyntaxTree, "invalid use of ListExpr for index expression %v with %d indices", e, n)
339 return nil
340 }
341
342 check.error(l.ElemList[1], InvalidIndex, invalidOp+"more than one index")
343 index = l.ElemList[0]
344 }
345 return index
346 }
347
348
349
350
351
352 func (check *Checker) index(index syntax.Expr, max int64) (typ Type, val int64) {
353 typ = Typ[Invalid]
354 val = -1
355
356 var x operand
357 check.expr(nil, &x, index)
358 if !check.isValidIndex(&x, InvalidIndex, "index", false) {
359 return
360 }
361
362 if x.mode != constant_ {
363 return x.typ, -1
364 }
365
366 if x.val.Kind() == constant.Unknown {
367 return
368 }
369
370 v, ok := constant.Int64Val(x.val)
371 assert(ok)
372 if max >= 0 && v >= max {
373 check.errorf(&x, InvalidIndex, invalidArg+"index %s out of bounds [0:%d]", x.val.String(), max)
374 return
375 }
376
377
378 return x.typ, v
379 }
380
381
382
383
384
385 func (check *Checker) isValidIndex(x *operand, code Code, what string, allowNegative bool) bool {
386 if x.mode == invalid {
387 return false
388 }
389
390
391 check.convertUntyped(x, Typ[Int])
392 if x.mode == invalid {
393 return false
394 }
395
396
397 if !allInteger(x.typ) {
398 check.errorf(x, code, invalidArg+"%s %s must be integer", what, x)
399 return false
400 }
401
402 if x.mode == constant_ {
403
404 if !allowNegative && constant.Sign(x.val) < 0 {
405 check.errorf(x, code, invalidArg+"%s %s must not be negative", what, x)
406 return false
407 }
408
409
410 if !representableConst(x.val, check, Typ[Int], &x.val) {
411 check.errorf(x, code, invalidArg+"%s %s overflows int", what, x)
412 return false
413 }
414 }
415
416 return true
417 }
418
419
420
421
422
423 func (check *Checker) indexedElts(elts []syntax.Expr, typ Type, length int64) int64 {
424 visited := make(map[int64]bool, len(elts))
425 var index, max int64
426 for _, e := range elts {
427
428 validIndex := false
429 eval := e
430 if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
431 if typ, i := check.index(kv.Key, length); isValid(typ) {
432 if i >= 0 {
433 index = i
434 validIndex = true
435 } else {
436 check.errorf(e, InvalidLitIndex, "index %s must be integer constant", kv.Key)
437 }
438 }
439 eval = kv.Value
440 } else if length >= 0 && index >= length {
441 check.errorf(e, OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
442 } else {
443 validIndex = true
444 }
445
446
447 if validIndex {
448 if visited[index] {
449 check.errorf(e, DuplicateLitKey, "duplicate index %d in array or slice literal", index)
450 }
451 visited[index] = true
452 }
453 index++
454 if index > max {
455 max = index
456 }
457
458
459 var x operand
460 check.exprWithHint(&x, eval, typ)
461 check.assignment(&x, typ, "array or slice literal")
462 }
463 return max
464 }
465
View as plain text