Reverting merge from trunk
[official-gcc.git] / gcc / testsuite / go.test / test / recover.go
blob7c27d7c4d63c73fd9181b44439c8b5e3d24d7220
1 // run
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.
7 // Test of basic recover functionality.
9 package main
11 import (
12 "os"
13 "runtime"
16 func main() {
17 test1()
18 test1WithClosures()
19 test2()
20 test3()
21 // exp/ssa/interp still has some bugs in recover().
22 if os.Getenv("GOSSAINTERP") == "" {
23 test4()
24 test5()
26 test6()
27 test6WithClosures()
28 test7()
31 func die() {
32 runtime.Breakpoint() // can't depend on panic
35 func mustRecover(x interface{}) {
36 mustNotRecover() // because it's not a defer call
37 v := recover()
38 if v == nil {
39 println("missing recover")
40 die() // panic is useless here
42 if v != x {
43 println("wrong value", v, x)
44 die()
47 // the value should be gone now regardless
48 v = recover()
49 if v != nil {
50 println("recover didn't recover")
51 die()
55 func mustNotRecover() {
56 v := recover()
57 if v != nil {
58 println("spurious recover", v)
59 die()
63 func withoutRecover() {
64 mustNotRecover() // because it's a sub-call
67 func test1() {
68 defer mustNotRecover() // because mustRecover will squelch it
69 defer mustRecover(1) // because of panic below
70 defer withoutRecover() // should be no-op, leaving for mustRecover to find
71 panic(1)
74 // Repeat test1 with closures instead of standard function.
75 // Interesting because recover bases its decision
76 // on the frame pointer of its caller, and a closure's
77 // frame pointer is in the middle of its actual arguments
78 // (after the hidden ones for the closed-over variables).
79 func test1WithClosures() {
80 defer func() {
81 v := recover()
82 if v != nil {
83 println("spurious recover in closure")
84 die()
86 }()
87 defer func(x interface{}) {
88 mustNotRecover()
89 v := recover()
90 if v == nil {
91 println("missing recover")
92 die()
94 if v != x {
95 println("wrong value", v, x)
96 die()
98 }(1)
99 defer func() {
100 mustNotRecover()
102 panic(1)
105 func test2() {
106 // Recover only sees the panic argument
107 // if it is called from a deferred call.
108 // It does not see the panic when called from a call within a deferred call (too late)
109 // nor does it see the panic when it *is* the deferred call (too early).
110 defer mustRecover(2)
111 defer recover() // should be no-op
112 panic(2)
115 func test3() {
116 defer mustNotRecover()
117 defer func() {
118 recover() // should squelch
120 panic(3)
123 func test4() {
124 // Equivalent to test3 but using defer to make the call.
125 defer mustNotRecover()
126 defer func() {
127 defer recover() // should squelch
129 panic(4)
132 // Check that closures can set output arguments.
133 // Run g(). If it panics, return x; else return deflt.
134 func try(g func(), deflt interface{}) (x interface{}) {
135 defer func() {
136 if v := recover(); v != nil {
137 x = v
140 defer g()
141 return deflt
144 // Check that closures can set output arguments.
145 // Run g(). If it panics, return x; else return deflt.
146 func try1(g func(), deflt interface{}) (x interface{}) {
147 defer func() {
148 if v := recover(); v != nil {
149 x = v
152 defer g()
153 x = deflt
154 return
157 func test5() {
158 v := try(func() { panic(5) }, 55).(int)
159 if v != 5 {
160 println("wrong value", v, 5)
161 die()
164 s := try(func() {}, "hi").(string)
165 if s != "hi" {
166 println("wrong value", s, "hi")
167 die()
170 v = try1(func() { panic(5) }, 55).(int)
171 if v != 5 {
172 println("try1 wrong value", v, 5)
173 die()
176 s = try1(func() {}, "hi").(string)
177 if s != "hi" {
178 println("try1 wrong value", s, "hi")
179 die()
183 // When a deferred big call starts, it must first
184 // create yet another stack segment to hold the
185 // giant frame for x. Make sure that doesn't
186 // confuse recover.
187 func big(mustRecover bool) {
188 var x [100000]int
189 x[0] = 1
190 x[99999] = 1
191 _ = x
193 v := recover()
194 if mustRecover {
195 if v == nil {
196 println("missing big recover")
197 die()
199 } else {
200 if v != nil {
201 println("spurious big recover")
202 die()
207 func test6() {
208 defer big(false)
209 defer big(true)
210 panic(6)
213 func test6WithClosures() {
214 defer func() {
215 var x [100000]int
216 x[0] = 1
217 x[99999] = 1
218 _ = x
219 if recover() != nil {
220 println("spurious big closure recover")
221 die()
224 defer func() {
225 var x [100000]int
226 x[0] = 1
227 x[99999] = 1
228 _ = x
229 if recover() == nil {
230 println("missing big closure recover")
231 die()
234 panic("6WithClosures")
237 func test7() {
238 ok := false
239 func() {
240 // should panic, then call mustRecover 7, which stops the panic.
241 // then should keep processing ordinary defers earlier than that one
242 // before returning.
243 // this test checks that the defer func on the next line actually runs.
244 defer func() { ok = true }()
245 defer mustRecover(7)
246 panic(7)
248 if !ok {
249 println("did not run ok func")
250 die()
254 func varargs(s *int, a ...int) {
255 *s = 0
256 for _, v := range a {
257 *s += v
259 if recover() != nil {
260 *s += 100
264 func test8a() (r int) {
265 defer varargs(&r, 1, 2, 3)
266 panic(0)
269 func test8b() (r int) {
270 defer varargs(&r, 4, 5, 6)
271 return
274 func test8() {
275 if test8a() != 106 || test8b() != 15 {
276 println("wrong value")
277 die()