Revert "[PATCH 7/7] RISC-V: Disable by pieces for vector setmem length > UNITS_PER_WORD"
[official-gcc.git] / libgo / go / runtime / defer_test.go
blob3a54951c318a58744735a1e4958d02b289f5fe2a
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.
5 package runtime_test
7 import (
8 "fmt"
9 "reflect"
10 "runtime"
11 "testing"
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) {
17 defer func() {
18 if recover() != "testUnconditional" {
19 t.Fatal("expected unconditional panic")
21 }()
22 panic("testUnconditional")
25 var glob int = 3
27 // Test an open-coded defer and non-open-coded defer - make sure both defers run
28 // and call recover()
29 func TestOpenAndNonOpenDefers(t *testing.T) {
30 for {
31 // Non-open defer because in a loop
32 defer func(n int) {
33 if recover() != "testNonOpenDefer" {
34 t.Fatal("expected testNonOpen panic")
36 }(3)
37 if glob > 2 {
38 break
41 testOpen(t, 47)
42 panic("testNonOpenDefer")
45 //go:noinline
46 func testOpen(t *testing.T, arg int) {
47 defer func(n int) {
48 if recover() != "testOpenDefer" {
49 t.Fatal("expected testOpen panic")
51 }(4)
52 if arg > 2 {
53 panic("testOpenDefer")
57 // Test a non-open-coded defer and an open-coded defer - make sure both defers run
58 // and call recover()
59 func TestNonOpenAndOpenDefers(t *testing.T) {
60 testOpen(t, 47)
61 for {
62 // Non-open defer because in a loop
63 defer func(n int) {
64 if recover() != "testNonOpenDefer" {
65 t.Fatal("expected testNonOpen panic")
67 }(3)
68 if glob > 2 {
69 break
72 panic("testNonOpenDefer")
75 var list []int
77 // Make sure that conditional open-coded defers are activated correctly and run in
78 // the correct order.
79 func TestConditionalDefers(t *testing.T) {
80 list = make([]int, 0, 10)
82 defer func() {
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))
91 }()
92 testConditionalDefers(8)
95 func testConditionalDefers(n int) {
96 doappend := func(i int) {
97 list = append(list, i)
100 defer doappend(1)
101 if n > 5 {
102 defer doappend(2)
103 if n > 8 {
104 defer doappend(3)
105 } else {
106 defer doappend(4)
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 {
116 case "invalidOS":
117 defer func() {
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) {
133 defer func() {
134 r := recover()
135 if r != nil {
136 t.Fatal(fmt.Sprintf("wanted nil recover, got %v", r))
139 defer func() {
140 r := recover()
141 if r != "panic2" {
142 t.Fatal(fmt.Sprintf("wanted %v, got %v", "panic2", r))
145 defer func() {
146 panic("panic2")
148 panic("panic1")
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
154 // the panic. In
155 func TestRecoverMatching(t *testing.T) {
156 defer func() {
157 r := recover()
158 if r != "panic1" {
159 t.Fatal(fmt.Sprintf("wanted %v, got %v", "panic1", r))
162 defer func() {
163 defer func() {
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.
167 r := recover()
168 if r != nil {
169 t.Fatal(fmt.Sprintf("wanted nil recover, got %v", r))
173 panic("panic1")
176 type nonSSAable [128]byte
178 type bigStruct struct {
179 x, y, z, w, p, q int64
182 type containsBigStruct struct {
183 element bigStruct
186 func mknonSSAable() nonSSAable {
187 globint1++
188 return nonSSAable{0, 0, 0, 0, 5}
191 var globint1, globint2, globint3 int
193 //go:noinline
194 func sideeffect(n int64) int64 {
195 globint2++
196 return n
199 func sideeffect2(in containsBigStruct) containsBigStruct {
200 globint3++
201 return in
204 // Test that nonSSAable arguments to defer are handled correctly and only evaluated once.
205 func TestNonSSAableArgs(t *testing.T) {
206 globint1 = 0
207 globint2 = 0
208 globint3 = 0
209 var save1 byte
210 var save2 int64
211 var save3 int64
212 var save4 int64
214 defer func() {
215 if globint1 != 1 {
216 t.Fatal(fmt.Sprintf("globint1: wanted: 1, got %v", globint1))
218 if save1 != 5 {
219 t.Fatal(fmt.Sprintf("save1: wanted: 5, got %v", save1))
221 if globint2 != 1 {
222 t.Fatal(fmt.Sprintf("globint2: wanted: 1, got %v", globint2))
224 if save2 != 2 {
225 t.Fatal(fmt.Sprintf("save2: wanted: 2, got %v", save2))
227 if save3 != 4 {
228 t.Fatal(fmt.Sprintf("save3: wanted: 4, got %v", save3))
230 if globint3 != 1 {
231 t.Fatal(fmt.Sprintf("globint3: wanted: 1, got %v", globint3))
233 if save4 != 4 {
234 t.Fatal(fmt.Sprintf("save1: wanted: 4, got %v", save4))
238 // Test function returning a non-SSAable arg
239 defer func(n nonSSAable) {
240 save1 = n[4]
241 }(mknonSSAable())
242 // Test composite literal that is not SSAable
243 defer func(b bigStruct) {
244 save2 = b.y
245 }(bigStruct{1, 2, 3, 4, 5, sideeffect(6)})
247 // Test struct field reference that is non-SSAable
248 foo := containsBigStruct{}
249 foo.element.z = 4
250 defer func(element bigStruct) {
251 save3 = element.z
252 }(foo.element)
253 defer func(element bigStruct) {
254 save4 = element.z
255 }(sideeffect2(foo).element)
258 //go:noinline
259 func doPanic() {
260 panic("Test panic")
263 func TestDeferForFuncWithNoExit(t *testing.T) {
264 cond := 1
265 defer func() {
266 if cond != 2 {
267 t.Fatal(fmt.Sprintf("cond: wanted 2, got %v", cond))
269 if recover() != "Test panic" {
270 t.Fatal("Didn't find expected panic")
273 x := 0
274 // Force a stack copy, to make sure that the &cond pointer passed to defer
275 // function is properly updated.
276 growStackIter(&x, 1000)
277 cond = 2
278 doPanic()
280 // This function has no exit/return, since it ends with an infinite loop
281 for {
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) {
292 interpreter(0, 6, 2)
293 recurseFnPanicRec(0, 10)
294 interpreter(0, 5, 1)
295 recurseFnPanicRec(0, 10)
296 interpreter(0, 6, 3)
297 recurseFnPanicRec(0, 10)
300 func interpreter(level int, maxlevel int, rec int) {
301 defer func() {
302 e := recover()
303 if e == nil {
304 return
306 if level != e.(int) {
307 //fmt.Fprintln(os.Stderr, "re-panicing, level", level)
308 panic(e)
310 //fmt.Fprintln(os.Stderr, "Recovered, level", level)
312 if level+1 < maxlevel {
313 interpreter(level+1, maxlevel, rec)
314 } else {
315 //fmt.Fprintln(os.Stderr, "Initiating panic")
316 panic(rec)
320 func recurseFnPanicRec(level int, maxlevel int) {
321 defer func() {
322 recover()
324 recurseFn(level, maxlevel)
327 var saveInt uint32
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
333 saveInt = a[4]
334 recurseFn(level+1, maxlevel)
335 } else {
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++ {
346 g2()
347 g3()
351 type foo struct {
354 //go:noinline
355 func (f *foo) method1() {
358 //go:noinline
359 func (f *foo) method2() {
362 func g2() {
363 var a foo
364 ap := &a
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++ {
368 defer ap.method1()
370 defer ap.method2()
371 defer ap.method1()
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.
375 rec1(2000)
378 func g3() {
379 // Mix up the stack layout by adding in an extra function frame
380 g2()
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) {
388 defer ap.method1()
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
392 // defer pool)
393 defer func(ap *foo, a, b, c, d, e, f, g, h, i int) {
394 if v := recover(); v != nil {
396 globstruct.a = a
397 globstruct.b = b
398 globstruct.c = c
399 globstruct.d = d
400 globstruct.e = e
401 globstruct.f = f
402 globstruct.g = g
403 globstruct.h = h
404 }(ap, a, b, c, d, e, f, g, h, i)
405 panic("ff1 panic")
408 func rec1(max int) {
409 if max > 0 {
410 rec1(max - 1)
414 func TestIssue43921(t *testing.T) {
415 defer func() {
416 expect(t, 1, recover())
418 func() {
419 // Prevent open-coded defers
420 for {
421 defer func() {}()
422 break
425 defer func() {
426 defer func() {
427 expect(t, 4, recover())
429 panic(4)
431 panic(1)
436 func expect(t *testing.T, n int, err any) {
437 if n != err {
438 t.Fatalf("have %v, want %v", err, n)
442 func TestIssue43920(t *testing.T) {
443 var steps int
445 defer func() {
446 expect(t, 1, recover())
448 defer func() {
449 defer func() {
450 defer func() {
451 expect(t, 5, recover())
453 defer panic(5)
454 func() {
455 panic(4)
458 defer func() {
459 expect(t, 3, recover())
461 defer panic(3)
463 func() {
464 defer step(t, &steps, 1)
465 panic(1)
469 func step(t *testing.T, steps *int, want int) {
470 *steps++
471 if *steps != want {
472 t.Fatalf("have %v, want %v", *steps, want)
476 func TestIssue43941(t *testing.T) {
477 var steps int = 7
478 defer func() {
479 step(t, &steps, 14)
480 expect(t, 4, recover())
482 func() {
483 func() {
484 defer func() {
485 defer func() {
486 expect(t, 3, recover())
488 defer panic(3)
489 panic(2)
491 defer func() {
492 expect(t, 1, recover())
494 defer panic(1)
496 defer func() {}()
497 defer func() {}()
498 defer step(t, &steps, 10)
499 defer step(t, &steps, 9)
500 step(t, &steps, 8)
502 func() {
503 defer step(t, &steps, 13)
504 defer step(t, &steps, 12)
505 func() {
506 defer step(t, &steps, 11)
507 panic(4)
510 // Code below isn't executed,
511 // but removing it breaks the test case.
512 defer func() {}()
513 defer panic(-1)
514 defer step(t, &steps, -1)
515 defer step(t, &steps, -1)
516 defer func() {}()