1// errorcheck -0 -l -d=defer
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// check that open-coded defers are used in expected situations
8
9package main
10
11import "fmt"
12
13var glob = 3
14
15func f1() {
16
17	for i := 0; i < 10; i++ {
18		fmt.Println("loop")
19	}
20	defer func() { // ERROR "open-coded defer"
21		fmt.Println("defer")
22	}()
23}
24
25func f2() {
26	for {
27		defer func() { // ERROR "heap-allocated defer"
28			fmt.Println("defer1")
29		}()
30		if glob > 2 {
31			break
32		}
33	}
34	defer func() { // ERROR "stack-allocated defer"
35		fmt.Println("defer2")
36	}()
37}
38
39func f3() {
40	defer func() { // ERROR "stack-allocated defer"
41		fmt.Println("defer2")
42	}()
43	for {
44		defer func() { // ERROR "heap-allocated defer"
45			fmt.Println("defer1")
46		}()
47		if glob > 2 {
48			break
49		}
50	}
51}
52
53func f4() {
54	defer func() { // ERROR "open-coded defer"
55		fmt.Println("defer")
56	}()
57label:
58	fmt.Println("goto loop")
59	if glob > 2 {
60		goto label
61	}
62}
63
64func f5() {
65label:
66	fmt.Println("goto loop")
67	defer func() { // ERROR "heap-allocated defer"
68		fmt.Println("defer")
69	}()
70	if glob > 2 {
71		goto label
72	}
73}
74
75func f6() {
76label:
77	fmt.Println("goto loop")
78	if glob > 2 {
79		goto label
80	}
81	// The current analysis doesn't end a backward goto loop, so this defer is
82	// considered to be inside a loop
83	defer func() { // ERROR "heap-allocated defer"
84		fmt.Println("defer")
85	}()
86}
87