1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 // Make sure open-coded defer exit code is not lost, even when there is an
15 // unconditional panic (hence no return from the function)
16 func TestUnconditionalPanic(t
*testing
.T
) {
18 if recover() != "testUnconditional" {
19 t
.Fatal("expected unconditional panic")
22 panic("testUnconditional")
27 // Test an open-coded defer and non-open-coded defer - make sure both defers run
29 func TestOpenAndNonOpenDefers(t
*testing
.T
) {
31 // Non-open defer because in a loop
33 if recover() != "testNonOpenDefer" {
34 t
.Fatal("expected testNonOpen panic")
42 panic("testNonOpenDefer")
46 func testOpen(t
*testing
.T
, arg
int) {
48 if recover() != "testOpenDefer" {
49 t
.Fatal("expected testOpen panic")
53 panic("testOpenDefer")
57 // Test a non-open-coded defer and an open-coded defer - make sure both defers run
59 func TestNonOpenAndOpenDefers(t
*testing
.T
) {
62 // Non-open defer because in a loop
64 if recover() != "testNonOpenDefer" {
65 t
.Fatal("expected testNonOpen panic")
72 panic("testNonOpenDefer")
77 // Make sure that conditional open-coded defers are activated correctly and run in
79 func TestConditionalDefers(t
*testing
.T
) {
80 list
= make([]int, 0, 10)
83 if recover() != "testConditional" {
84 t
.Fatal("expected panic")
86 want
:= []int{4, 2, 1}
87 if !reflect
.DeepEqual(want
, list
) {
88 t
.Fatal(fmt
.Sprintf("wanted %v, got %v", want
, list
))
92 testConditionalDefers(8)
95 func testConditionalDefers(n
int) {
96 doappend
:= func(i
int) {
97 list
= append(list
, i
)
109 panic("testConditional")
112 // Test that there is no compile-time or run-time error if an open-coded defer
113 // call is removed by constant propagation and dead-code elimination.
114 func TestDisappearingDefer(t
*testing
.T
) {
115 switch runtime
.GOOS
{
118 t
.Fatal("Defer shouldn't run")
123 // This tests an extra recursive panic behavior that is only specified in the
124 // code. Suppose a first panic P1 happens and starts processing defer calls. If a
125 // second panic P2 happens while processing defer call D in frame F, then defer
126 // call processing is restarted (with some potentially new defer calls created by
127 // D or its callees). If the defer processing reaches the started defer call D
128 // again in the defer stack, then the original panic P1 is aborted and cannot
129 // continue panic processing or be recovered. If the panic P2 does a recover at
130 // some point, it will naturally remove the original panic P1 from the stack
131 // (since the original panic had to be in frame F or a descendant of F).
132 func TestAbortedPanic(t
*testing
.T
) {
136 t
.Fatal(fmt
.Sprintf("wanted nil recover, got %v", r
))
142 t
.Fatal(fmt
.Sprintf("wanted %v, got %v", "panic2", r
))
151 // This tests that recover() does not succeed unless it is called directly from a
152 // defer function that is directly called by the panic. Here, we first call it
153 // from a defer function that is created by the defer function called directly by
155 func TestRecoverMatching(t
*testing
.T
) {
159 t
.Fatal(fmt
.Sprintf("wanted %v, got %v", "panic1", r
))
164 // Shouldn't succeed, even though it is called directly
165 // from a defer function, since this defer function was
166 // not directly called by the panic.
169 t
.Fatal(fmt
.Sprintf("wanted nil recover, got %v", r
))
176 type nonSSAable
[128]byte
178 type bigStruct
struct {
179 x
, y
, z
, w
, p
, q
int64
182 type containsBigStruct
struct {
186 func mknonSSAable() nonSSAable
{
188 return nonSSAable
{0, 0, 0, 0, 5}
191 var globint1
, globint2
, globint3
int
194 func sideeffect(n
int64) int64 {
199 func sideeffect2(in containsBigStruct
) containsBigStruct
{
204 // Test that nonSSAable arguments to defer are handled correctly and only evaluated once.
205 func TestNonSSAableArgs(t
*testing
.T
) {
216 t
.Fatal(fmt
.Sprintf("globint1: wanted: 1, got %v", globint1
))
219 t
.Fatal(fmt
.Sprintf("save1: wanted: 5, got %v", save1
))
222 t
.Fatal(fmt
.Sprintf("globint2: wanted: 1, got %v", globint2
))
225 t
.Fatal(fmt
.Sprintf("save2: wanted: 2, got %v", save2
))
228 t
.Fatal(fmt
.Sprintf("save3: wanted: 4, got %v", save3
))
231 t
.Fatal(fmt
.Sprintf("globint3: wanted: 1, got %v", globint3
))
234 t
.Fatal(fmt
.Sprintf("save1: wanted: 4, got %v", save4
))
238 // Test function returning a non-SSAable arg
239 defer func(n nonSSAable
) {
242 // Test composite literal that is not SSAable
243 defer func(b bigStruct
) {
245 }(bigStruct
{1, 2, 3, 4, 5, sideeffect(6)})
247 // Test struct field reference that is non-SSAable
248 foo
:= containsBigStruct
{}
250 defer func(element bigStruct
) {
253 defer func(element bigStruct
) {
255 }(sideeffect2(foo
).element
)
263 func TestDeferForFuncWithNoExit(t
*testing
.T
) {
267 t
.Fatal(fmt
.Sprintf("cond: wanted 2, got %v", cond
))
269 if recover() != "Test panic" {
270 t
.Fatal("Didn't find expected panic")
274 // Force a stack copy, to make sure that the &cond pointer passed to defer
275 // function is properly updated.
276 growStackIter(&x
, 1000)
280 // This function has no exit/return, since it ends with an infinite loop
285 // Test case approximating issue #37664, where a recursive function (interpreter)
286 // may do repeated recovers/re-panics until it reaches the frame where the panic
287 // can actually be handled. The recurseFnPanicRec() function is testing that there
288 // are no stale defer structs on the defer chain after the interpreter() sequence,
289 // by writing a bunch of 0xffffffffs into several recursive stack frames, and then
290 // doing a single panic-recover which would invoke any such stale defer structs.
291 func TestDeferWithRepeatedRepanics(t
*testing
.T
) {
293 recurseFnPanicRec(0, 10)
295 recurseFnPanicRec(0, 10)
297 recurseFnPanicRec(0, 10)
300 func interpreter(level
int, maxlevel
int, rec
int) {
306 if level
!= e
.(int) {
307 //fmt.Fprintln(os.Stderr, "re-panicing, level", level)
310 //fmt.Fprintln(os.Stderr, "Recovered, level", level)
312 if level
+1 < maxlevel
{
313 interpreter(level
+1, maxlevel
, rec
)
315 //fmt.Fprintln(os.Stderr, "Initiating panic")
320 func recurseFnPanicRec(level
int, maxlevel
int) {
324 recurseFn(level
, maxlevel
)
329 func recurseFn(level
int, maxlevel
int) {
330 a
:= [40]uint32{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}
331 if level
+1 < maxlevel
{
332 // Make sure a array is referenced, so it is not optimized away
334 recurseFn(level
+1, maxlevel
)
336 panic("recurseFn panic")
340 // Try to reproduce issue #37688, where a pointer to an open-coded defer struct is
341 // mistakenly held, and that struct keeps a pointer to a stack-allocated defer
342 // struct, and that stack-allocated struct gets overwritten or the stack gets
343 // moved, so a memory error happens on GC.
344 func TestIssue37688(t
*testing
.T
) {
345 for j
:= 0; j
< 10; j
++ {
355 func (f
*foo
) method1() {
359 func (f
*foo
) method2() {
365 // The loop forces this defer to be heap-allocated and the remaining two
366 // to be stack-allocated.
367 for i
:= 0; i
< 1; i
++ {
372 ff1(ap
, 1, 2, 3, 4, 5, 6, 7, 8, 9)
373 // Try to get the stack to be moved by growing it too large, so
374 // existing stack-allocated defer becomes invalid.
379 // Mix up the stack layout by adding in an extra function frame
383 var globstruct
struct {
384 a
, b
, c
, d
, e
, f
, g
, h
, i
int
387 func ff1(ap
*foo
, a
, b
, c
, d
, e
, f
, g
, h
, i
int) {
390 // Make a defer that has a very large set of args, hence big size for the
391 // defer record for the open-coded frame (which means it won't use the
393 defer func(ap
*foo
, a
, b
, c
, d
, e
, f
, g
, h
, i
int) {
394 if v
:= recover(); v
!= nil {
404 }(ap
, a
, b
, c
, d
, e
, f
, g
, h
, i
)
414 func TestIssue43921(t
*testing
.T
) {
416 expect(t
, 1, recover())
419 // Prevent open-coded defers
427 expect(t
, 4, recover())
436 func expect(t
*testing
.T
, n
int, err any
) {
438 t
.Fatalf("have %v, want %v", err
, n
)
442 func TestIssue43920(t
*testing
.T
) {
446 expect(t
, 1, recover())
451 expect(t
, 5, recover())
459 expect(t
, 3, recover())
464 defer step(t
, &steps
, 1)
469 func step(t
*testing
.T
, steps
*int, want
int) {
472 t
.Fatalf("have %v, want %v", *steps
, want
)
476 func TestIssue43941(t
*testing
.T
) {
480 expect(t
, 4, recover())
486 expect(t
, 3, recover())
492 expect(t
, 1, recover())
498 defer step(t
, &steps
, 10)
499 defer step(t
, &steps
, 9)
503 defer step(t
, &steps
, 13)
504 defer step(t
, &steps
, 12)
506 defer step(t
, &steps
, 11)
510 // Code below isn't executed,
511 // but removing it breaks the test case.
514 defer step(t
, &steps
, -1)
515 defer step(t
, &steps
, -1)