1// errorcheckwithauto -0 -l -live -wb=0 -d=ssa/insert_resched_checks/off
2
3//go:build (amd64 && goexperiment.regabiargs) || (arm64 && goexperiment.regabiargs)
4
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
14import "runtime"
15
16func 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
145	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
147	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\]runtime.scase$"
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\]runtime.scase$"
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\]runtime.scase$"
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 {
458		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$"
459			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 {
504		h31(g18()) // ERROR "live at call to convT: .autotmp_[0-9]+$" "live at call to newobject: .autotmp_[0-9]+$"
505	}
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\]runtime.scase$"
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()
607		case *fi38(3), *fb38() = <-fc38(): // ERROR "stack object .autotmp_[0-9]+ string$" "live at call to f[ibc]38:( .autotmp_[0-9]+)+$"
608			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$"
667	ret.m = make(map[int]int) // ERROR "live at call to rand32: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ runtime.hmap$"
668	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
689type R struct{ *T }
690
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	}()
698	printint(0) // ERROR "live at call to printint: .autotmp_[0-9]+ q r$"
699	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	}
719	ret := T{} // ERROR "stack object ret T"
720	ret.s[0] = f()
721	return ret
722}
723
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}
743