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.
13 // Make sure open-coded defer exit code is not lost, even when there is an
14 // unconditional panic (hence no return from the function)
15 func TestUnconditionalPanic(t *testing.T) {
17 if recover() != "testUnconditional" {
18 t.Fatal("expected unconditional panic")
21 panic("testUnconditional")
26 // Test an open-coded defer and non-open-coded defer - make sure both defers run
28 func TestOpenAndNonOpenDefers(t *testing.T) {
30 // Non-open defer because in a loop
32 if recover() != "testNonOpenDefer" {
33 t.Fatal("expected testNonOpen panic")
41 panic("testNonOpenDefer")
45 func testOpen(t *testing.T, arg int) {
47 if recover() != "testOpenDefer" {
48 t.Fatal("expected testOpen panic")
52 panic("testOpenDefer")
56 // Test a non-open-coded defer and an open-coded defer - make sure both defers run
58 func TestNonOpenAndOpenDefers(t *testing.T) {
61 // Non-open defer because in a loop
63 if recover() != "testNonOpenDefer" {
64 t.Fatal("expected testNonOpen panic")
71 panic("testNonOpenDefer")
76 // Make sure that conditional open-coded defers are activated correctly and run in
78 func TestConditionalDefers(t *testing.T) {
79 list = make([]int, 0, 10)
82 if recover() != "testConditional" {
83 t.Fatal("expected panic")
85 want := []int{4, 2, 1}
86 if !reflect.DeepEqual(want, list) {
87 t.Fatalf("wanted %v, got %v", want, list)
91 testConditionalDefers(8)
94 func testConditionalDefers(n int) {
95 doappend := func(i int) {
96 list = append(list, i)
108 panic("testConditional")
111 // Test that there is no compile-time or run-time error if an open-coded defer
112 // call is removed by constant propagation and dead-code elimination.
113 func TestDisappearingDefer(t *testing.T) {
114 switch runtime.GOOS {
117 t.Fatal("Defer shouldn't run")
122 // This tests an extra recursive panic behavior that is only specified in the
123 // code. Suppose a first panic P1 happens and starts processing defer calls. If a
124 // second panic P2 happens while processing defer call D in frame F, then defer
125 // call processing is restarted (with some potentially new defer calls created by
126 // D or its callees). If the defer processing reaches the started defer call D
127 // again in the defer stack, then the original panic P1 is aborted and cannot
128 // continue panic processing or be recovered. If the panic P2 does a recover at
129 // some point, it will naturally remove the original panic P1 from the stack
130 // (since the original panic had to be in frame F or a descendant of F).
131 func TestAbortedPanic(t *testing.T) {
135 t.Fatalf("wanted nil recover, got %v", r)
141 t.Fatalf("wanted %v, got %v", "panic2", r)
150 // This tests that recover() does not succeed unless it is called directly from a
151 // defer function that is directly called by the panic. Here, we first call it
152 // from a defer function that is created by the defer function called directly by
154 func TestRecoverMatching(t *testing.T) {
158 t.Fatalf("wanted %v, got %v", "panic1", r)
163 // Shouldn't succeed, even though it is called directly
164 // from a defer function, since this defer function was
165 // not directly called by the panic.
168 t.Fatalf("wanted nil recover, got %v", r)
175 type nonSSAable [128]byte
177 type bigStruct struct {
178 x, y, z, w, p, q int64
181 type containsBigStruct struct {
185 func mknonSSAable() nonSSAable {
187 return nonSSAable{0, 0, 0, 0, 5}
190 var globint1, globint2, globint3 int
193 func sideeffect(n int64) int64 {
198 func sideeffect2(in containsBigStruct) containsBigStruct {
203 // Test that nonSSAable arguments to defer are handled correctly and only evaluated once.
204 func TestNonSSAableArgs(t *testing.T) {
215 t.Fatalf("globint1: wanted: 1, got %v", globint1)
218 t.Fatalf("save1: wanted: 5, got %v", save1)
221 t.Fatalf("globint2: wanted: 1, got %v", globint2)
224 t.Fatalf("save2: wanted: 2, got %v", save2)
227 t.Fatalf("save3: wanted: 4, got %v", save3)
230 t.Fatalf("globint3: wanted: 1, got %v", globint3)
233 t.Fatalf("save1: wanted: 4, got %v", save4)
237 // Test function returning a non-SSAable arg
238 defer func(n nonSSAable) {
241 // Test composite literal that is not SSAable
242 defer func(b bigStruct) {
244 }(bigStruct{1, 2, 3, 4, 5, sideeffect(6)})
246 // Test struct field reference that is non-SSAable
247 foo := containsBigStruct{}
249 defer func(element bigStruct) {
252 defer func(element bigStruct) {
254 }(sideeffect2(foo).element)
262 func TestDeferForFuncWithNoExit(t *testing.T) {
266 t.Fatalf("cond: wanted 2, got %v", cond)
268 if recover() != "Test panic" {
269 t.Fatal("Didn't find expected panic")
273 // Force a stack copy, to make sure that the &cond pointer passed to defer
274 // function is properly updated.
275 growStackIter(&x, 1000)
279 // This function has no exit/return, since it ends with an infinite loop
284 // Test case approximating issue #37664, where a recursive function (interpreter)
285 // may do repeated recovers/re-panics until it reaches the frame where the panic
286 // can actually be handled. The recurseFnPanicRec() function is testing that there
287 // are no stale defer structs on the defer chain after the interpreter() sequence,
288 // by writing a bunch of 0xffffffffs into several recursive stack frames, and then
289 // doing a single panic-recover which would invoke any such stale defer structs.
290 func TestDeferWithRepeatedRepanics(t *testing.T) {
292 recurseFnPanicRec(0, 10)
294 recurseFnPanicRec(0, 10)
296 recurseFnPanicRec(0, 10)
299 func interpreter(level int, maxlevel int, rec int) {
305 if level != e.(int) {
306 //fmt.Fprintln(os.Stderr, "re-panicing, level", level)
309 //fmt.Fprintln(os.Stderr, "Recovered, level", level)
311 if level+1 < maxlevel {
312 interpreter(level+1, maxlevel, rec)
314 //fmt.Fprintln(os.Stderr, "Initiating panic")
319 func recurseFnPanicRec(level int, maxlevel int) {
323 recurseFn(level, maxlevel)
328 func recurseFn(level int, maxlevel int) {
329 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}
330 if level+1 < maxlevel {
331 // Make sure a array is referenced, so it is not optimized away
333 recurseFn(level+1, maxlevel)
335 panic("recurseFn panic")
339 // Try to reproduce issue #37688, where a pointer to an open-coded defer struct is
340 // mistakenly held, and that struct keeps a pointer to a stack-allocated defer
341 // struct, and that stack-allocated struct gets overwritten or the stack gets
342 // moved, so a memory error happens on GC.
343 func TestIssue37688(t *testing.T) {
344 for j := 0; j < 10; j++ {
354 func (f *foo) method1() {
358 func (f *foo) method2() {
364 // The loop forces this defer to be heap-allocated and the remaining two
365 // to be stack-allocated.
366 for i := 0; i < 1; i++ {
371 ff1(ap, 1, 2, 3, 4, 5, 6, 7, 8, 9)
372 // Try to get the stack to be moved by growing it too large, so
373 // existing stack-allocated defer becomes invalid.
378 // Mix up the stack layout by adding in an extra function frame
382 var globstruct struct {
383 a, b, c, d, e, f, g, h, i int
386 func ff1(ap *foo, a, b, c, d, e, f, g, h, i int) {
389 // Make a defer that has a very large set of args, hence big size for the
390 // defer record for the open-coded frame (which means it won't use the
392 defer func(ap *foo, a, b, c, d, e, f, g, h, i int) {
393 if v := recover(); v != nil {
403 }(ap, a, b, c, d, e, f, g, h, i)
413 func TestIssue43921(t *testing.T) {
415 expect(t, 1, recover())
418 // Prevent open-coded defers
426 expect(t, 4, recover())
435 func expect(t *testing.T, n int, err any) {
437 t.Fatalf("have %v, want %v", err, n)
441 func TestIssue43920(t *testing.T) {
445 expect(t, 1, recover())
450 expect(t, 5, recover())
458 expect(t, 3, recover())
463 defer step(t, &steps, 1)
468 func step(t *testing.T, steps *int, want int) {
471 t.Fatalf("have %v, want %v", *steps, want)
475 func TestIssue43941(t *testing.T) {
479 expect(t, 4, recover())
485 expect(t, 3, recover())
491 expect(t, 1, recover())
497 defer step(t, &steps, 10)
498 defer step(t, &steps, 9)
502 defer step(t, &steps, 13)
503 defer step(t, &steps, 12)
505 defer step(t, &steps, 11)
509 // Code below isn't executed,
510 // but removing it breaks the test case.
513 defer step(t, &steps, -1)
514 defer step(t, &steps, -1)