1// errorcheck
2
3// Copyright 2011 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// Verify goto semantics.
8// Does not compile.
9//
10// Each test is in a separate function just so that if the
11// compiler stops processing after one error, we don't
12// lose other ones.
13
14package main
15
16var (
17	i, n int
18	x    []int
19	c    chan int
20	m    map[int]int
21	s    string
22)
23
24// goto after declaration okay
25func _() {
26	x := 1
27	goto L
28L:
29	_ = x
30}
31
32// goto before declaration okay
33func _() {
34	goto L
35L:
36	x := 1
37	_ = x
38}
39
40// goto across declaration not okay
41func _() {
42	goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
43	x := 1	// GCCGO_ERROR "defined here"
44	_ = x
45L:
46}
47
48// goto across declaration in inner scope okay
49func _() {
50	goto L
51	{
52		x := 1
53		_ = x
54	}
55L:
56}
57
58// goto across declaration after inner scope not okay
59func _() {
60	goto L // ERROR "goto L jumps over declaration of x at LINE+5|goto jumps over declaration"
61	{
62		x := 1
63		_ = x
64	}
65	x := 1	// GCCGO_ERROR "defined here"
66	_ = x
67L:
68}
69
70// goto across declaration in reverse okay
71func _() {
72L:
73	x := 1
74	_ = x
75	goto L
76}
77
78// error shows first offending variable
79func _() {
80	goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
81	x := 1	// GCCGO_ERROR "defined here"
82	_ = x
83	y := 1
84	_ = y
85L:
86}
87
88// goto not okay even if code path is dead
89func _() {
90	goto L // ERROR "goto L jumps over declaration of x at LINE+1|goto jumps over declaration"
91	x := 1	// GCCGO_ERROR "defined here"
92	_ = x
93	y := 1
94	_ = y
95	return
96L:
97}
98
99// goto into outer block okay
100func _() {
101	{
102		goto L
103	}
104L:
105}
106
107// goto backward into outer block okay
108func _() {
109L:
110	{
111		goto L
112	}
113}
114
115// goto into inner block not okay
116func _() {
117	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
118	{	// GCCGO_ERROR "block starts here"
119	L:
120	}
121}
122
123// goto backward into inner block still not okay
124func _() {
125	{	// GCCGO_ERROR "block starts here"
126	L:
127	}
128	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
129}
130
131// error shows first (outermost) offending block
132func _() {
133	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
134	{
135		{
136			{	// GCCGO_ERROR "block starts here"
137			L:
138			}
139		}
140	}
141}
142
143// error prefers block diagnostic over declaration diagnostic
144func _() {
145	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
146	x := 1
147	_ = x
148	{	// GCCGO_ERROR "block starts here"
149	L:
150	}
151}
152
153// many kinds of blocks, all invalid to jump into or among,
154// but valid to jump out of
155
156// if
157
158func _() {
159L:
160	if true {
161		goto L
162	}
163}
164
165func _() {
166L:
167	if true {
168		goto L
169	} else {
170	}
171}
172
173func _() {
174L:
175	if false {
176	} else {
177		goto L
178	}
179}
180
181func _() {
182	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
183	if true {	// GCCGO_ERROR "block starts here"
184	L:
185	}
186}
187
188func _() {
189	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
190	if true {	// GCCGO_ERROR "block starts here"
191	L:
192	} else {
193	}
194}
195
196func _() {
197	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
198	if true {
199	} else {	// GCCGO_ERROR "block starts here"
200	L:
201	}
202}
203
204func _() {
205	if false {	// GCCGO_ERROR "block starts here"
206	L:
207	} else {
208		goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
209	}
210}
211
212func _() {
213	if true {
214		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
215	} else {	// GCCGO_ERROR "block starts here"
216	L:
217	}
218}
219
220func _() {
221	if true {
222		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
223	} else if false {	// GCCGO_ERROR "block starts here"
224	L:
225	}
226}
227
228func _() {
229	if true {
230		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
231	} else if false {	// GCCGO_ERROR "block starts here"
232	L:
233	} else {
234	}
235}
236
237func _() {
238	// This one is tricky.  There is an implicit scope
239	// starting at the second if statement, and it contains
240	// the final else, so the outermost offending scope
241	// really is LINE+1 (like in the previous test),
242	// even though it looks like it might be LINE+3 instead.
243	if true {
244		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
245	} else if false {
246	} else {	// GCCGO_ERROR "block starts here"
247	L:
248	}
249}
250
251/* Want to enable these tests but gofmt mangles them.  Issue 1972.
252
253func _() {
254	// This one is okay, because the else is in the
255	// implicit whole-if block and has no inner block
256	// (no { }) around it.
257	if true {
258		goto L
259	} else
260		L:
261}
262
263func _() {
264	// Still not okay.
265	if true {	//// GCCGO_ERROR "block starts here"
266	L:
267	} else
268		goto L //// ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
269}
270
271*/
272
273// for
274
275func _() {
276	for {
277		goto L
278	}
279L:
280}
281
282func _() {
283	for {
284		goto L
285	L:
286	}
287}
288
289func _() {
290	for {	// GCCGO_ERROR "block starts here"
291	L:
292	}
293	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
294}
295
296func _() {
297	for {	// GCCGO_ERROR "block starts here"
298		goto L
299	L1:
300	}
301L:
302	goto L1 // ERROR "goto L1 jumps into block starting at LINE-5|goto jumps into block"
303}
304
305func _() {
306	for i < n {	// GCCGO_ERROR "block starts here"
307	L:
308	}
309	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
310}
311
312func _() {
313	for i = 0; i < n; i++ {	// GCCGO_ERROR "block starts here"
314	L:
315	}
316	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
317}
318
319func _() {
320	for i = range x {	// GCCGO_ERROR "block starts here"
321	L:
322	}
323	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
324}
325
326func _() {
327	for i = range c {	// GCCGO_ERROR "block starts here"
328	L:
329	}
330	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
331}
332
333func _() {
334	for i = range m {	// GCCGO_ERROR "block starts here"
335	L:
336	}
337	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
338}
339
340func _() {
341	for i = range s {	// GCCGO_ERROR "block starts here"
342	L:
343	}
344	goto L // ERROR "goto L jumps into block starting at LINE-3|goto jumps into block"
345}
346
347// switch
348
349func _() {
350L:
351	switch i {
352	case 0:
353		goto L
354	}
355}
356
357func _() {
358L:
359	switch i {
360	case 0:
361
362	default:
363		goto L
364	}
365}
366
367func _() {
368	switch i {
369	case 0:
370
371	default:
372	L:
373		goto L
374	}
375}
376
377func _() {
378	switch i {
379	case 0:
380
381	default:
382		goto L
383	L:
384	}
385}
386
387func _() {
388	switch i {
389	case 0:
390		goto L
391	L:
392		;
393	default:
394	}
395}
396
397func _() {
398	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
399	switch i {
400	case 0:
401	L:	// GCCGO_ERROR "block starts here"
402	}
403}
404
405func _() {
406	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
407	switch i {
408	case 0:
409	L:	// GCCGO_ERROR "block starts here"
410		;
411	default:
412	}
413}
414
415func _() {
416	goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
417	switch i {
418	case 0:
419	default:
420	L:	// GCCGO_ERROR "block starts here"
421	}
422}
423
424func _() {
425	switch i {
426	default:
427		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
428	case 0:
429	L:	// GCCGO_ERROR "block starts here"
430	}
431}
432
433func _() {
434	switch i {
435	case 0:
436	L:	// GCCGO_ERROR "block starts here"
437		;
438	default:
439		goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
440	}
441}
442
443// select
444// different from switch.  the statement has no implicit block around it.
445
446func _() {
447L:
448	select {
449	case <-c:
450		goto L
451	}
452}
453
454func _() {
455L:
456	select {
457	case c <- 1:
458
459	default:
460		goto L
461	}
462}
463
464func _() {
465	select {
466	case <-c:
467
468	default:
469	L:
470		goto L
471	}
472}
473
474func _() {
475	select {
476	case c <- 1:
477
478	default:
479		goto L
480	L:
481	}
482}
483
484func _() {
485	select {
486	case <-c:
487		goto L
488	L:
489		;
490	default:
491	}
492}
493
494func _() {
495	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
496	select {
497	case c <- 1:
498	L:	// GCCGO_ERROR "block starts here"
499	}
500}
501
502func _() {
503	goto L // ERROR "goto L jumps into block starting at LINE+2|goto jumps into block"
504	select {
505	case c <- 1:
506	L:	// GCCGO_ERROR "block starts here"
507		;
508	default:
509	}
510}
511
512func _() {
513	goto L // ERROR "goto L jumps into block starting at LINE+3|goto jumps into block"
514	select {
515	case <-c:
516	default:
517	L:	// GCCGO_ERROR "block starts here"
518	}
519}
520
521func _() {
522	select {
523	default:
524		goto L // ERROR "goto L jumps into block starting at LINE+1|goto jumps into block"
525	case <-c:
526	L:	// GCCGO_ERROR "block starts here"
527	}
528}
529
530func _() {
531	select {
532	case <-c:
533	L:	// GCCGO_ERROR "block starts here"
534		;
535	default:
536		goto L // ERROR "goto L jumps into block starting at LINE-4|goto jumps into block"
537	}
538}
539