blob: 7ae84891e4a90a4d972bdc8849b11e2be5b5d8fa [file] [log] [blame]
Cherry Zhanga9c244a2021-04-17 00:46:53 -04001// errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
Matthew Dempskyf7513192022-06-29 17:15:08 -07002//go:build (amd64 && goexperiment.regabiargs) || (arm64 && goexperiment.regabiargs)
Cuong Manh Lef67e31d2021-08-19 21:02:49 +07003// +build amd64,goexperiment.regabiargs arm64,goexperiment.regabiargs
Cherry Zhanga9c244a2021-04-17 00:46:53 -04004
5// Copyright 2014 The Go Authors. All rights reserved.
6// Use of this source code is governed by a BSD-style
7// license that can be found in the LICENSE file.
8
9// liveness tests with inlining disabled.
10// see also live2.go.
11
12package main
13
Keith Randallba913772023-01-20 13:54:36 -080014import "runtime"
15
Cherry Zhanga9c244a2021-04-17 00:46:53 -040016func printnl()
17
18//go:noescape
19func printpointer(**int)
20
21//go:noescape
22func printintpointer(*int)
23
24//go:noescape
25func printstringpointer(*string)
26
27//go:noescape
28func printstring(string)
29
30//go:noescape
31func printbytepointer(*byte)
32
33func printint(int)
34
35func f1() {
36 var x *int // ERROR "stack object x \*int$"
37 printpointer(&x) // ERROR "live at call to printpointer: x$"
38 printpointer(&x)
39}
40
41func f2(b bool) {
42 if b {
43 printint(0) // nothing live here
44 return
45 }
46 var x *int // ERROR "stack object x \*int$"
47 printpointer(&x) // ERROR "live at call to printpointer: x$"
48 printpointer(&x)
49}
50
51func f3(b1, b2 bool) {
52 // Here x and y are ambiguously live. In previous go versions they
53 // were marked as live throughout the function to avoid being
54 // poisoned in GODEBUG=gcdead=1 mode; this is now no longer the
55 // case.
56
57 printint(0)
58 if b1 == false {
59 printint(0)
60 return
61 }
62
63 if b2 {
64 var x *int // ERROR "stack object x \*int$"
65 printpointer(&x) // ERROR "live at call to printpointer: x$"
66 printpointer(&x)
67 } else {
68 var y *int // ERROR "stack object y \*int$"
69 printpointer(&y) // ERROR "live at call to printpointer: y$"
70 printpointer(&y)
71 }
72 printint(0) // nothing is live here
73}
74
75// The old algorithm treated x as live on all code that
76// could flow to a return statement, so it included the
77// function entry and code above the declaration of x
78// but would not include an indirect use of x in an infinite loop.
79// Check that these cases are handled correctly.
80
81func f4(b1, b2 bool) { // x not live here
82 if b2 {
83 printint(0) // x not live here
84 return
85 }
86 var z **int
87 x := new(int) // ERROR "stack object x \*int$"
88 *x = 42
89 z = &x
90 printint(**z) // ERROR "live at call to printint: x$"
91 if b2 {
92 printint(1) // x not live here
93 return
94 }
95 for {
96 printint(**z) // ERROR "live at call to printint: x$"
97 }
98}
99
100func f5(b1 bool) {
101 var z **int
102 if b1 {
103 x := new(int) // ERROR "stack object x \*int$"
104 *x = 42
105 z = &x
106 } else {
107 y := new(int) // ERROR "stack object y \*int$"
108 *y = 54
109 z = &y
110 }
111 printint(**z) // nothing live here
112}
113
114// confusion about the _ result used to cause spurious "live at entry to f6: _".
115
116func f6() (_, y string) {
117 y = "hello"
118 return
119}
120
121// confusion about addressed results used to cause "live at entry to f7: x".
122
123func f7() (x string) { // ERROR "stack object x string"
124 _ = &x
125 x = "hello"
126 return
127}
128
129// ignoring block returns used to cause "live at entry to f8: x, y".
130
131func f8() (x, y string) {
132 return g8()
133}
134
135func g8() (string, string)
136
137// ignoring block assignments used to cause "live at entry to f9: x"
138// issue 7205
139
140var i9 interface{}
141
142func f9() bool {
143 g8()
144 x := i9
Keith Randall57668b82021-08-04 22:18:23 -0700145 y := interface{}(g18()) // ERROR "live at call to convT: x.data$" "live at call to g18: x.data$" "stack object .autotmp_[0-9]+ \[2\]string$"
146 i9 = y // make y escape so the line above has to call convT
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400147 return x != y
148}
149
150// liveness formerly confused by UNDEF followed by RET,
151// leading to "live at entry to f10: ~r1" (unnamed result).
152
153func f10() string {
154 panic(1)
155}
156
157// liveness formerly confused by select, thinking runtime.selectgo
158// can return to next instruction; it always jumps elsewhere.
159// note that you have to use at least two cases in the select
160// to get a true select; smaller selects compile to optimized helper functions.
161
162var c chan *int
163var b bool
164
165// this used to have a spurious "live at entry to f11a: ~r0"
166func f11a() *int {
167 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]struct"
168 case <-c:
169 return nil
170 case <-c:
171 return nil
172 }
173}
174
175func f11b() *int {
176 p := new(int)
177 if b {
178 // At this point p is dead: the code here cannot
179 // get to the bottom of the function.
180 // This used to have a spurious "live at call to printint: p".
181 printint(1) // nothing live here!
182 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]struct"
183 case <-c:
184 return nil
185 case <-c:
186 return nil
187 }
188 }
189 println(*p)
190 return nil
191}
192
193var sink *int
194
195func f11c() *int {
196 p := new(int)
197 sink = p // prevent stack allocation, otherwise p is rematerializeable
198 if b {
199 // Unlike previous, the cases in this select fall through,
200 // so we can get to the println, so p is not dead.
201 printint(1) // ERROR "live at call to printint: p$"
202 select { // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]struct"
203 case <-c:
204 case <-c:
205 }
206 }
207 println(*p)
208 return nil
209}
210
211// similarly, select{} does not fall through.
212// this used to have a spurious "live at entry to f12: ~r0".
213
214func f12() *int {
215 if b {
216 select {}
217 } else {
218 return nil
219 }
220}
221
222// incorrectly placed VARDEF annotations can cause missing liveness annotations.
223// this used to be missing the fact that s is live during the call to g13 (because it is
224// needed for the call to h13).
225
226func f13() {
227 s := g14()
228 s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$"
229}
230
231func g13(string) string
232func h13(string, string) string
233
234// more incorrectly placed VARDEF.
235
236func f14() {
237 x := g14() // ERROR "stack object x string$"
238 printstringpointer(&x)
239}
240
241func g14() string
242
243// Checking that various temporaries do not persist or cause
244// ambiguously live values that must be zeroed.
245// The exact temporary names are inconsequential but we are
246// trying to check that there is only one at any given site,
247// and also that none show up in "ambiguously live" messages.
248
249var m map[string]int
250var mi map[interface{}]int
251
252// str and iface are used to ensure that a temp is required for runtime calls below.
253func str() string
254func iface() interface{}
255
256func f16() {
257 if b {
258 delete(mi, iface()) // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
259 }
260 delete(mi, iface())
261 delete(mi, iface())
262}
263
264var m2s map[string]*byte
265var m2 map[[2]string]*byte
266var x2 [2]string
267var bp *byte
268
269func f17a(p *byte) { // ERROR "live at entry to f17a: p$"
270 if b {
271 m2[x2] = p // ERROR "live at call to mapassign: p$"
272 }
273 m2[x2] = p // ERROR "live at call to mapassign: p$"
274 m2[x2] = p // ERROR "live at call to mapassign: p$"
275}
276
277func f17b(p *byte) { // ERROR "live at entry to f17b: p$"
278 // key temporary
279 if b {
280 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
281 }
282 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
283 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
284}
285
286func f17c() {
287 // key and value temporaries
288 if b {
289 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
290 }
291 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
292 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
293}
294
295func f17d() *byte
296
297func g18() [2]string
298
299func f18() {
300 // key temporary for mapaccess.
301 // temporary introduced by orderexpr.
302 var z *byte
303 if b {
304 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
305 }
306 z = m2[g18()]
307 z = m2[g18()]
308 printbytepointer(z)
309}
310
311var ch chan *byte
312
313// byteptr is used to ensure that a temp is required for runtime calls below.
314func byteptr() *byte
315
316func f19() {
317 // dest temporary for channel receive.
318 var z *byte
319
320 if b {
321 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$"
322 }
323 z = <-ch
324 z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$"
325 printbytepointer(z)
326}
327
328func f20() {
329 // src temporary for channel send
330 if b {
331 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$"
332 }
333 ch <- byteptr()
334 ch <- byteptr()
335}
336
337func f21() {
338 // key temporary for mapaccess using array literal key.
339 var z *byte
340 if b {
341 z = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
342 }
343 z = m2[[2]string{"x", "y"}]
344 z = m2[[2]string{"x", "y"}]
345 printbytepointer(z)
346}
347
348func f23() {
349 // key temporary for two-result map access using array literal key.
350 var z *byte
351 var ok bool
352 if b {
353 z, ok = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
354 }
355 z, ok = m2[[2]string{"x", "y"}]
356 z, ok = m2[[2]string{"x", "y"}]
357 printbytepointer(z)
358 print(ok)
359}
360
361func f24() {
362 // key temporary for map access using array literal key.
363 // value temporary too.
364 if b {
365 m2[[2]string{"x", "y"}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
366 }
367 m2[[2]string{"x", "y"}] = nil
368 m2[[2]string{"x", "y"}] = nil
369}
370
371// Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps).
372func f25(b bool) {
373 for i := 0; i < 2; i++ {
374 // Put in loop to make sure defer is not open-coded
375 defer g25()
376 }
377 if b {
378 return
379 }
380 var x string
381 x = g14()
382 printstring(x)
383 return
384}
385
386func g25()
387
388// non-escaping ... slices passed to function call should die on return,
389// so that the temporaries do not stack and do not cause ambiguously
390// live variables.
391
392func f26(b bool) {
393 if b {
394 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$"
395 }
396 print26((*int)(nil), (*int)(nil), (*int)(nil))
397 print26((*int)(nil), (*int)(nil), (*int)(nil))
398 printnl()
399}
400
401//go:noescape
402func print26(...interface{})
403
404// non-escaping closures passed to function call should die on return
405
406func f27(b bool) {
407 x := 0
408 if b {
409 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
410 }
411 call27(func() { x++ })
412 call27(func() { x++ })
413 printnl()
414}
415
416// but defer does escape to later execution in the function
417
418func f27defer(b bool) {
419 x := 0
420 if b {
421 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
422 }
423 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
424 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+"
425 return // ERROR "live at indirect call: .autotmp_[0-9]+"
426}
427
428// and newproc (go) escapes to the heap
429
430func f27go(b bool) {
431 x := 0
432 if b {
433 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: &x .autotmp_[0-9]+$" "live at call to newproc: &x$" // allocate two closures, the func literal, and the wrapper for go
434 }
435 go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newobject: .autotmp_[0-9]+$" // allocate two closures, the func literal, and the wrapper for go
436 printnl()
437}
438
439//go:noescape
440func call27(func())
441
442// concatstring slice should die on return
443
444var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
445
446func f28(b bool) {
447 if b {
448 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$"
449 }
450 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
451 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
452}
453
454// map iterator should die on end of range loop
455
456func f29(b bool) {
457 if b {
Matthew Dempsky42f4ccb2023-08-21 11:26:15 -0700458 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hiter$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400459 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
460 }
461 }
462 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$"
463 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
464 }
465 for k := range m { // ERROR "live at call to mapiterinit: .autotmp_[0-9]+$" "live at call to mapiternext: .autotmp_[0-9]+$"
466 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
467 }
468}
469
470// copy of array of pointers should die at end of range loop
471var pstructarr [10]pstruct
472
473// Struct size chosen to make pointer to element in pstructarr
474// not computable by strength reduction.
475type pstruct struct {
476 intp *int
477 _ [8]byte
478}
479
480func f30(b bool) {
481 // live temp during printintpointer(p):
482 // the internal iterator pointer if a pointer to pstruct in pstructarr
483 // can not be easily computed by strength reduction.
484 if b {
485 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$"
486 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
487 }
488 }
489 for _, p := range pstructarr {
490 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
491 }
492 for _, p := range pstructarr {
493 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
494 }
495}
496
497// conversion to interface should not leave temporary behind
498
499func f31(b1, b2, b3 bool) {
500 if b1 {
501 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
502 }
503 if b2 {
Keith Randall57668b82021-08-04 22:18:23 -0700504 h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400505 }
506 if b3 {
507 panic(g18())
508 }
509 print(b3)
510}
511
512func g31(interface{})
513func h31(...interface{})
514
515// non-escaping partial functions passed to function call should die on return
516
517type T32 int
518
519func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$"
520 *t++
521}
522
523var t32 T32
524
525func f32(b bool) {
526 if b {
527 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{"
528 }
529 call32(t32.Inc)
530 call32(t32.Inc)
531}
532
533//go:noescape
534func call32(func())
535
536// temporaries introduced during if conditions and && || expressions
537// should die once the condition has been acted upon.
538
539var m33 map[interface{}]int
540
541func f33() {
542 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
543 printnl()
544 return
545 } else {
546 printnl()
547 }
548 printnl()
549}
550
551func f34() {
552 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
553 printnl()
554 return
555 }
556 printnl()
557}
558
559func f35() {
560 if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
561 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
562 printnl()
563 return
564 }
565 printnl()
566}
567
568func f36() {
569 if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
570 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
571 printnl()
572 return
573 }
574 printnl()
575}
576
577func f37() {
578 if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
579 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
580 m33[byteptr()] == 0 {
581 printnl()
582 return
583 }
584 printnl()
585}
586
587// select temps should disappear in the case bodies
588
589var c38 chan string
590
591func fc38() chan string
592func fi38(int) *string
593func fb38() *bool
594
595func f38(b bool) {
596 // we don't care what temps are printed on the lines with output.
597 // we care that the println lines have no live variables
598 // and therefore no output.
599 if b {
600 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]struct \{"
601 case <-fc38():
602 printnl()
603 case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
604 printnl()
605 case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ string$"
606 printnl()
Matthew Dempskyf7513192022-06-29 17:15:08 -0700607 case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400608 printnl()
609 }
610 printnl()
611 }
612 printnl()
613}
614
615// issue 8097: mishandling of x = x during return.
616
617func f39() (x []int) {
618 x = []int{1}
619 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
620 return x
621}
622
623func f39a() (x []int) {
624 x = []int{1}
625 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
626 return
627}
628
629func f39b() (x [10]*int) {
630 x = [10]*int{}
631 x[0] = new(int) // ERROR "live at call to newobject: x$"
632 printnl() // ERROR "live at call to printnl: x$"
633 return x
634}
635
636func f39c() (x [10]*int) {
637 x = [10]*int{}
638 x[0] = new(int) // ERROR "live at call to newobject: x$"
639 printnl() // ERROR "live at call to printnl: x$"
640 return
641}
642
643// issue 8142: lost 'addrtaken' bit on inlined variables.
644// no inlining in this test, so just checking that non-inlined works.
645
646type T40 struct {
647 m map[int]int
648}
649
650//go:noescape
651func useT40(*T40)
652
653func newT40() *T40 {
654 ret := T40{}
655 ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$"
656 return &ret
657}
658
659func bad40() {
660 t := newT40()
661 _ = t
662 printnl()
663}
664
665func good40() {
666 ret := T40{} // ERROR "stack object ret T40$"
Matthew Dempsky42f4ccb2023-08-21 11:26:15 -0700667 ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hmap$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400668 t := &ret
669 printnl() // ERROR "live at call to printnl: ret$"
670 // Note: ret is live at the printnl because the compiler moves &ret
671 // from before the printnl to after.
672 useT40(t)
673}
674
675func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$"
676 ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$"
677 printnl()
678 // Note: no .?autotmp live at printnl. See issue 16996.
679}
680func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$"
681 sink = a[0]
682}
683
684// issue 16016: autogenerated wrapper should have arguments live
685type T struct{}
686
687func (*T) Foo(ptr *int) {}
688
Matthew Dempsky808dca32021-06-24 12:57:20 -0700689type R struct{ *T }
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400690
691// issue 18860: output arguments must be live all the time if there is a defer.
692// In particular, at printint r must be live.
693func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$"
694 r = p
695 defer func() {
696 recover()
697 }()
Keith Randall4ff07492023-01-20 13:36:51 -0800698 printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400699 r = q
700 return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$"
701}
702
703func f42() {
704 var p, q, r int
705 f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$"
706 f43([]*int{&p, &r, &q})
707 f43([]*int{&q, &p, &r})
708}
709
710//go:noescape
711func f43(a []*int)
712
713// Assigning to a sub-element that makes up an entire local variable
714// should clobber that variable.
715func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
716 type T struct {
717 s [1][2]*int
718 }
Keith Randall908499a2022-07-22 14:58:40 -0700719 ret := T{} // ERROR "stack object ret T"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400720 ret.s[0] = f()
Keith Randall908499a2022-07-22 14:58:40 -0700721 return ret
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400722}
Keith Randallba913772023-01-20 13:54:36 -0800723
724func f45(a, b, c, d, e, f, g, h, i, j, k, l *byte) { // ERROR "live at entry to f45: a b c d e f g h i j k l"
725 f46(a, b, c, d, e, f, g, h, i, j, k, l) // ERROR "live at call to f46: a b c d e f g h i j k l"
726 runtime.KeepAlive(a)
727 runtime.KeepAlive(b)
728 runtime.KeepAlive(c)
729 runtime.KeepAlive(d)
730 runtime.KeepAlive(e)
731 runtime.KeepAlive(f)
732 runtime.KeepAlive(g)
733 runtime.KeepAlive(h)
734 runtime.KeepAlive(i)
735 runtime.KeepAlive(j)
736 runtime.KeepAlive(k)
737 runtime.KeepAlive(l)
738}
739
740//go:noinline
741func f46(a, b, c, d, e, f, g, h, i, j, k, l *byte) {
742}