blob: 35f874ecc365f679bf0723920026eedba498c977 [file] [log] [blame]
Cherry Zhanga9c244a2021-04-17 00:46:53 -04001// errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
Dmitri Shuralyovb2fd76a2023-10-17 15:07:58 -04002
Matthew Dempskyf7513192022-06-29 17:15:08 -07003//go: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 {
Matthew Dempskyfecf5172023-08-21 14:08:46 -0700167 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400168 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!
Matthew Dempskyfecf5172023-08-21 14:08:46 -0700182 select { // ERROR "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400183 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$"
Matthew Dempskyfecf5172023-08-21 14:08:46 -0700202 select { // ERROR "live at call to selectgo: p$" "stack object .autotmp_[0-9]+ \[2\]runtime.scase$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400203 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
Michael Prattf782e162024-09-19 16:06:40 -0400264var m2s map[string]*byte
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400265var 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
Michael Prattf782e162024-09-19 16:06:40 -0400277func 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 }
283 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
284 m2s[str()] = p // ERROR "live at call to mapassign_faststr: p$" "live at call to str: p$"
285}
286
287func f17c() {
288 // key and value temporaries
289 if b {
290 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
291 }
292 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
293 m2s[str()] = f17d() // ERROR "live at call to f17d: .autotmp_[0-9]+$" "live at call to mapassign_faststr: .autotmp_[0-9]+$"
294}
295
296func f17d() *byte
297
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400298func g18() [2]string
299
300func f18() {
301 // key temporary for mapaccess.
302 // temporary introduced by orderexpr.
303 var z *byte
304 if b {
305 z = m2[g18()] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
306 }
307 z = m2[g18()]
308 z = m2[g18()]
309 printbytepointer(z)
310}
311
312var ch chan *byte
313
314// byteptr is used to ensure that a temp is required for runtime calls below.
315func byteptr() *byte
316
317func f19() {
318 // dest temporary for channel receive.
319 var z *byte
320
321 if b {
322 z = <-ch // ERROR "stack object .autotmp_[0-9]+ \*byte$"
323 }
324 z = <-ch
325 z = <-ch // ERROR "live at call to chanrecv1: .autotmp_[0-9]+$"
326 printbytepointer(z)
327}
328
329func f20() {
330 // src temporary for channel send
331 if b {
332 ch <- byteptr() // ERROR "stack object .autotmp_[0-9]+ \*byte$"
333 }
334 ch <- byteptr()
335 ch <- byteptr()
336}
337
338func f21() {
339 // key temporary for mapaccess using array literal key.
340 var z *byte
341 if b {
342 z = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
343 }
344 z = m2[[2]string{"x", "y"}]
345 z = m2[[2]string{"x", "y"}]
346 printbytepointer(z)
347}
348
349func f23() {
350 // key temporary for two-result map access using array literal key.
351 var z *byte
352 var ok bool
353 if b {
354 z, ok = m2[[2]string{"x", "y"}] // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
355 }
356 z, ok = m2[[2]string{"x", "y"}]
357 z, ok = m2[[2]string{"x", "y"}]
358 printbytepointer(z)
359 print(ok)
360}
361
362func f24() {
363 // key temporary for map access using array literal key.
364 // value temporary too.
365 if b {
366 m2[[2]string{"x", "y"}] = nil // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
367 }
368 m2[[2]string{"x", "y"}] = nil
369 m2[[2]string{"x", "y"}] = nil
370}
371
372// Non-open-coded defers should not cause autotmps. (Open-coded defers do create extra autotmps).
373func f25(b bool) {
374 for i := 0; i < 2; i++ {
375 // Put in loop to make sure defer is not open-coded
376 defer g25()
377 }
378 if b {
379 return
380 }
381 var x string
382 x = g14()
383 printstring(x)
384 return
385}
386
387func g25()
388
389// non-escaping ... slices passed to function call should die on return,
390// so that the temporaries do not stack and do not cause ambiguously
391// live variables.
392
393func f26(b bool) {
394 if b {
395 print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "stack object .autotmp_[0-9]+ \[3\]interface \{\}$"
396 }
397 print26((*int)(nil), (*int)(nil), (*int)(nil))
398 print26((*int)(nil), (*int)(nil), (*int)(nil))
399 printnl()
400}
401
402//go:noescape
403func print26(...interface{})
404
405// non-escaping closures passed to function call should die on return
406
407func f27(b bool) {
408 x := 0
409 if b {
410 call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
411 }
412 call27(func() { x++ })
413 call27(func() { x++ })
414 printnl()
415}
416
417// but defer does escape to later execution in the function
418
419func f27defer(b bool) {
420 x := 0
421 if b {
422 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
423 }
424 defer call27(func() { x++ }) // ERROR "stack object .autotmp_[0-9]+ struct \{"
425 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+ .autotmp_[0-9]+"
426 return // ERROR "live at indirect call: .autotmp_[0-9]+"
427}
428
429// and newproc (go) escapes to the heap
430
431func f27go(b bool) {
432 x := 0
433 if b {
434 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
435 }
436 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
437 printnl()
438}
439
440//go:noescape
441func call27(func())
442
443// concatstring slice should die on return
444
445var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
446
447func f28(b bool) {
448 if b {
449 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "stack object .autotmp_[0-9]+ \[10\]string$"
450 }
451 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
452 printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10)
453}
454
455// map iterator should die on end of range loop
456
457func f29(b bool) {
458 if b {
Michael Pratt78e6f2a2025-01-24 13:34:26 -0500459 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hiter|internal/runtime/maps.Iter)$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400460 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
461 }
462 }
Michael Pratt78e6f2a2025-01-24 13:34:26 -0500463 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400464 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
465 }
Michael Pratt78e6f2a2025-01-24 13:34:26 -0500466 for k := range m { // ERROR "live at call to (mapiterinit|mapIterStart): .autotmp_[0-9]+$" "live at call to (mapiternext|mapIterNext): .autotmp_[0-9]+$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400467 printstring(k) // ERROR "live at call to printstring: .autotmp_[0-9]+$"
468 }
469}
470
471// copy of array of pointers should die at end of range loop
472var pstructarr [10]pstruct
473
474// Struct size chosen to make pointer to element in pstructarr
475// not computable by strength reduction.
476type pstruct struct {
477 intp *int
478 _ [8]byte
479}
480
481func f30(b bool) {
482 // live temp during printintpointer(p):
483 // the internal iterator pointer if a pointer to pstruct in pstructarr
484 // can not be easily computed by strength reduction.
485 if b {
486 for _, p := range pstructarr { // ERROR "stack object .autotmp_[0-9]+ \[10\]pstruct$"
487 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
488 }
489 }
490 for _, p := range pstructarr {
491 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
492 }
493 for _, p := range pstructarr {
494 printintpointer(p.intp) // ERROR "live at call to printintpointer: .autotmp_[0-9]+$"
495 }
496}
497
498// conversion to interface should not leave temporary behind
499
500func f31(b1, b2, b3 bool) {
501 if b1 {
502 g31(g18()) // ERROR "stack object .autotmp_[0-9]+ \[2\]string$"
503 }
504 if b2 {
Keith Randall57668b82021-08-04 22:18:23 -0700505 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 -0400506 }
507 if b3 {
508 panic(g18())
509 }
510 print(b3)
511}
512
513func g31(interface{})
514func h31(...interface{})
515
516// non-escaping partial functions passed to function call should die on return
517
518type T32 int
519
520func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$"
521 *t++
522}
523
524var t32 T32
525
526func f32(b bool) {
527 if b {
528 call32(t32.Inc) // ERROR "stack object .autotmp_[0-9]+ struct \{"
529 }
530 call32(t32.Inc)
531 call32(t32.Inc)
532}
533
534//go:noescape
535func call32(func())
536
537// temporaries introduced during if conditions and && || expressions
538// should die once the condition has been acted upon.
539
540var m33 map[interface{}]int
541
542func f33() {
543 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
544 printnl()
545 return
546 } else {
547 printnl()
548 }
549 printnl()
550}
551
552func f34() {
553 if m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}$"
554 printnl()
555 return
556 }
557 printnl()
558}
559
560func f35() {
561 if m33[byteptr()] == 0 && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
562 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
563 printnl()
564 return
565 }
566 printnl()
567}
568
569func f36() {
570 if m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
571 m33[byteptr()] == 0 { // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
572 printnl()
573 return
574 }
575 printnl()
576}
577
578func f37() {
579 if (m33[byteptr()] == 0 || // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
580 m33[byteptr()] == 0) && // ERROR "stack object .autotmp_[0-9]+ interface \{\}"
581 m33[byteptr()] == 0 {
582 printnl()
583 return
584 }
585 printnl()
586}
587
588// select temps should disappear in the case bodies
589
590var c38 chan string
591
592func fc38() chan string
593func fi38(int) *string
594func fb38() *bool
595
596func f38(b bool) {
597 // we don't care what temps are printed on the lines with output.
598 // we care that the println lines have no live variables
599 // and therefore no output.
600 if b {
Matthew Dempskyfecf5172023-08-21 14:08:46 -0700601 select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$" "stack object .autotmp_[0-9]+ \[4\]runtime.scase$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400602 case <-fc38():
603 printnl()
604 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$"
605 printnl()
606 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$"
607 printnl()
Matthew Dempskyf7513192022-06-29 17:15:08 -0700608 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 -0400609 printnl()
610 }
611 printnl()
612 }
613 printnl()
614}
615
616// issue 8097: mishandling of x = x during return.
617
618func f39() (x []int) {
619 x = []int{1}
620 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
621 return x
622}
623
624func f39a() (x []int) {
625 x = []int{1}
626 printnl() // ERROR "live at call to printnl: .autotmp_[0-9]+$"
627 return
628}
629
630func f39b() (x [10]*int) {
631 x = [10]*int{}
632 x[0] = new(int) // ERROR "live at call to newobject: x$"
633 printnl() // ERROR "live at call to printnl: x$"
634 return x
635}
636
637func f39c() (x [10]*int) {
638 x = [10]*int{}
639 x[0] = new(int) // ERROR "live at call to newobject: x$"
640 printnl() // ERROR "live at call to printnl: x$"
641 return
642}
643
644// issue 8142: lost 'addrtaken' bit on inlined variables.
645// no inlining in this test, so just checking that non-inlined works.
646
647type T40 struct {
648 m map[int]int
649}
650
651//go:noescape
652func useT40(*T40)
653
654func newT40() *T40 {
655 ret := T40{}
656 ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: &ret$"
657 return &ret
658}
659
Michael Pratt63ba2b92024-10-25 15:08:54 -0400660func good40() {
661 ret := T40{} // ERROR "stack object ret T40$"
662 ret.m = make(map[int]int) // ERROR "live at call to rand(32)?: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ (runtime.hmap|internal/runtime/maps.Map)$"
663 t := &ret
664 printnl() // ERROR "live at call to printnl: ret$"
665 // Note: ret is live at the printnl because the compiler moves &ret
666 // from before the printnl to after.
667 useT40(t)
668}
669
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400670func bad40() {
671 t := newT40()
672 _ = t
673 printnl()
674}
675
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400676func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$"
677 ddd2(x, y) // ERROR "stack object .autotmp_[0-9]+ \[2\]\*int$"
678 printnl()
679 // Note: no .?autotmp live at printnl. See issue 16996.
680}
681func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$"
682 sink = a[0]
683}
684
685// issue 16016: autogenerated wrapper should have arguments live
686type T struct{}
687
688func (*T) Foo(ptr *int) {}
689
Matthew Dempsky808dca32021-06-24 12:57:20 -0700690type R struct{ *T }
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400691
692// issue 18860: output arguments must be live all the time if there is a defer.
693// In particular, at printint r must be live.
694func f41(p, q *int) (r *int) { // ERROR "live at entry to f41: p q$"
695 r = p
696 defer func() {
697 recover()
698 }()
Keith Randall4ff07492023-01-20 13:36:51 -0800699 printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400700 r = q
701 return // ERROR "live at call to f41.func1: .autotmp_[0-9]+ r$"
702}
703
704func f42() {
705 var p, q, r int
706 f43([]*int{&p, &q, &r}) // ERROR "stack object .autotmp_[0-9]+ \[3\]\*int$"
707 f43([]*int{&p, &r, &q})
708 f43([]*int{&q, &p, &r})
709}
710
711//go:noescape
712func f43(a []*int)
713
714// Assigning to a sub-element that makes up an entire local variable
715// should clobber that variable.
716func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
717 type T struct {
718 s [1][2]*int
719 }
Keith Randall908499a2022-07-22 14:58:40 -0700720 ret := T{} // ERROR "stack object ret T"
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400721 ret.s[0] = f()
Keith Randall908499a2022-07-22 14:58:40 -0700722 return ret
Cherry Zhanga9c244a2021-04-17 00:46:53 -0400723}
Keith Randallba913772023-01-20 13:54:36 -0800724
725func 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"
726 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"
727 runtime.KeepAlive(a)
728 runtime.KeepAlive(b)
729 runtime.KeepAlive(c)
730 runtime.KeepAlive(d)
731 runtime.KeepAlive(e)
732 runtime.KeepAlive(f)
733 runtime.KeepAlive(g)
734 runtime.KeepAlive(h)
735 runtime.KeepAlive(i)
736 runtime.KeepAlive(j)
737 runtime.KeepAlive(k)
738 runtime.KeepAlive(l)
739}
740
741//go:noinline
742func f46(a, b, c, d, e, f, g, h, i, j, k, l *byte) {
743}