1// run
2
3// Copyright 2019 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// Make sure that in code involving indexing, the bounds
8// check always fails at the line number of the '[' token.
9
10package main
11
12import (
13	"fmt"
14	"runtime"
15	"strings"
16)
17
18type T struct{ a, b, c, d, e int } // unSSAable
19
20func main() {
21	shouldPanic(func() {
22		var a [1]int
23		sink = a /*line :999999:1*/ [ /*line :100:1*/ i]
24	})
25	shouldPanic(func() {
26		var a [3]int
27		sink = a /*line :999999:1*/ [ /*line :200:1*/ i]
28	})
29	shouldPanic(func() {
30		var a []int
31		sink = a /*line :999999:1*/ [ /*line :300:1*/ i]
32	})
33	shouldPanic(func() {
34		var a [1]int
35		a /*line :999999:1*/ [ /*line :400:1*/ i] = 1
36	})
37	shouldPanic(func() {
38		var a [3]int
39		a /*line :999999:1*/ [ /*line :500:1*/ i] = 1
40	})
41	shouldPanic(func() {
42		var a []int
43		a /*line :999999:1*/ [ /*line :600:1*/ i] = 1
44	})
45
46	shouldPanic(func() {
47		var a [3]T
48		sinkT = a /*line :999999:1*/ [ /*line :700:1*/ i]
49	})
50	shouldPanic(func() {
51		var a []T
52		sinkT = a /*line :999999:1*/ [ /*line :800:1*/ i]
53	})
54	shouldPanic(func() {
55		var a [3]T
56		a /*line :999999:1*/ [ /*line :900:1*/ i] = T{}
57	})
58	shouldPanic(func() {
59		var a []T
60		a /*line :999999:1*/ [ /*line :1000:1*/ i] = T{}
61	})
62
63	shouldPanic(func() {
64		var a [3]int
65		sinkS = a /*line :999999:1*/ [ /*line :1100:1*/ i:]
66	})
67	shouldPanic(func() {
68		var a []int
69		sinkS = a /*line :999999:1*/ [ /*line :1200:1*/ i:]
70	})
71	shouldPanic(func() {
72		var a [3]int
73		sinkS = a /*line :999999:1*/ [: /*line :1300:1*/ i]
74	})
75	shouldPanic(func() {
76		var a []int
77		sinkS = a /*line :999999:1*/ [: /*line :1400:1*/ i]
78	})
79
80	shouldPanic(func() {
81		var a [3]T
82		sinkST = a /*line :999999:1*/ [ /*line :1500:1*/ i:]
83	})
84	shouldPanic(func() {
85		var a []T
86		sinkST = a /*line :999999:1*/ [ /*line :1600:1*/ i:]
87	})
88	shouldPanic(func() {
89		var a [3]T
90		sinkST = a /*line :999999:1*/ [: /*line :1700:1*/ i]
91	})
92	shouldPanic(func() {
93		var a []T
94		sinkST = a /*line :999999:1*/ [: /*line :1800:1*/ i]
95	})
96
97	shouldPanic(func() {
98		s := "foo"
99		sinkB = s /*line :999999:1*/ [ /*line :1900:1*/ i]
100	})
101	shouldPanic(func() {
102		s := "foo"
103		sinkStr = s /*line :999999:1*/ [ /*line :2000:1*/ i:]
104	})
105	shouldPanic(func() {
106		s := "foo"
107		sinkStr = s /*line :999999:1*/ [: /*line :2100:1*/ i]
108	})
109
110	if bad {
111		panic("ERRORS")
112	}
113}
114
115var i = 9
116var sink int
117var sinkS []int
118var sinkT T
119var sinkST []T
120var sinkB byte
121var sinkStr string
122
123var bad = false
124
125func shouldPanic(f func()) {
126	defer func() {
127		if recover() == nil {
128			panic("did not panic")
129		}
130		var pcs [10]uintptr
131		n := runtime.Callers(1, pcs[:])
132		iter := runtime.CallersFrames(pcs[:n])
133		buf := ""
134		for {
135			frame, more := iter.Next()
136			buf += fmt.Sprintf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
137			if !more {
138				break
139			}
140		}
141		if !strings.Contains(buf, "999999") {
142			fmt.Printf("could not find marker line in traceback:\n%s\n", buf)
143			bad = true
144		}
145	}()
146	f()
147}
148