1// Copyright 2012 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.
4
5// Code patterns that caused problems in the past.
6
7package race_test
8
9import (
10	"testing"
11)
12
13type LogImpl struct {
14	x int
15}
16
17func NewLog() (l LogImpl) {
18	c := make(chan bool)
19	go func() {
20		_ = l
21		c <- true
22	}()
23	l = LogImpl{}
24	<-c
25	return
26}
27
28var _ LogImpl = NewLog()
29
30func MakeMap() map[int]int {
31	return make(map[int]int)
32}
33
34func InstrumentMapLen() {
35	_ = len(MakeMap())
36}
37
38func InstrumentMapLen2() {
39	m := make(map[int]map[int]int)
40	_ = len(m[0])
41}
42
43func InstrumentMapLen3() {
44	m := make(map[int]*map[int]int)
45	_ = len(*m[0])
46}
47
48func TestRaceUnaddressableMapLen(t *testing.T) {
49	m := make(map[int]map[int]int)
50	ch := make(chan int, 1)
51	m[0] = make(map[int]int)
52	go func() {
53		_ = len(m[0])
54		ch <- 0
55	}()
56	m[0][0] = 1
57	<-ch
58}
59
60type Rect struct {
61	x, y int
62}
63
64type Image struct {
65	min, max Rect
66}
67
68//go:noinline
69func NewImage() Image {
70	return Image{}
71}
72
73func AddrOfTemp() {
74	_ = NewImage().min
75}
76
77type TypeID int
78
79func (t *TypeID) encodeType(x int) (tt TypeID, err error) {
80	switch x {
81	case 0:
82		return t.encodeType(x * x)
83	}
84	return 0, nil
85}
86
87type stack []int
88
89func (s *stack) push(x int) {
90	*s = append(*s, x)
91}
92
93func (s *stack) pop() int {
94	i := len(*s)
95	n := (*s)[i-1]
96	*s = (*s)[:i-1]
97	return n
98}
99
100func TestNoRaceStackPushPop(t *testing.T) {
101	var s stack
102	go func(s *stack) {}(&s)
103	s.push(1)
104	x := s.pop()
105	_ = x
106}
107
108type RpcChan struct {
109	c chan bool
110}
111
112var makeChanCalls int
113
114//go:noinline
115func makeChan() *RpcChan {
116	makeChanCalls++
117	c := &RpcChan{make(chan bool, 1)}
118	c.c <- true
119	return c
120}
121
122func call() bool {
123	x := <-makeChan().c
124	return x
125}
126
127func TestNoRaceRpcChan(t *testing.T) {
128	makeChanCalls = 0
129	_ = call()
130	if makeChanCalls != 1 {
131		t.Fatalf("makeChanCalls %d, expected 1\n", makeChanCalls)
132	}
133}
134
135func divInSlice() {
136	v := make([]int64, 10)
137	i := 1
138	_ = v[(i*4)/3]
139}
140
141func TestNoRaceReturn(t *testing.T) {
142	c := make(chan int)
143	noRaceReturn(c)
144	<-c
145}
146
147// Return used to do an implicit a = a, causing a read/write race
148// with the goroutine. Compiler has an optimization to avoid that now.
149// See issue 4014.
150func noRaceReturn(c chan int) (a, b int) {
151	a = 42
152	go func() {
153		_ = a
154		c <- 1
155	}()
156	return a, 10
157}
158
159func issue5431() {
160	var p **inltype
161	if inlinetest(p).x && inlinetest(p).y {
162	} else if inlinetest(p).x || inlinetest(p).y {
163	}
164}
165
166type inltype struct {
167	x, y bool
168}
169
170func inlinetest(p **inltype) *inltype {
171	return *p
172}
173
174type iface interface {
175	Foo() *struct{ b bool }
176}
177
178type Int int
179
180func (i Int) Foo() *struct{ b bool } {
181	return &struct{ b bool }{false}
182}
183
184func TestNoRaceForInfiniteLoop(t *testing.T) {
185	var x Int
186	// interface conversion causes nodes to be put on init list
187	for iface(x).Foo().b {
188	}
189}
190