1// errorcheck -0 -l -d=wb 2 3// Copyright 2015 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7// Test where write barriers are and are not emitted. 8 9package p 10 11import "unsafe" 12 13func f(x **byte, y *byte) { 14 *x = y // no barrier (dead store) 15 16 z := y // no barrier 17 *x = z // ERROR "write barrier" 18} 19 20func f1(x *[]byte, y []byte) { 21 *x = y // no barrier (dead store) 22 23 z := y // no barrier 24 *x = z // ERROR "write barrier" 25} 26 27func f1a(x *[]byte, y *[]byte) { 28 *x = *y // ERROR "write barrier" 29 30 z := *y // no barrier 31 *x = z // ERROR "write barrier" 32} 33 34func f2(x *interface{}, y interface{}) { 35 *x = y // no barrier (dead store) 36 37 z := y // no barrier 38 *x = z // ERROR "write barrier" 39} 40 41func f2a(x *interface{}, y *interface{}) { 42 *x = *y // no barrier (dead store) 43 44 z := y // no barrier 45 *x = z // ERROR "write barrier" 46} 47 48func f3(x *string, y string) { 49 *x = y // no barrier (dead store) 50 51 z := y // no barrier 52 *x = z // ERROR "write barrier" 53} 54 55func f3a(x *string, y *string) { 56 *x = *y // ERROR "write barrier" 57 58 z := *y // no barrier 59 *x = z // ERROR "write barrier" 60} 61 62func f4(x *[2]string, y [2]string) { 63 *x = y // ERROR "write barrier" 64 65 z := y // no barrier 66 *x = z // ERROR "write barrier" 67} 68 69func f4a(x *[2]string, y *[2]string) { 70 *x = *y // ERROR "write barrier" 71 72 z := *y // no barrier 73 *x = z // ERROR "write barrier" 74} 75 76type T struct { 77 X *int 78 Y int 79 M map[int]int 80} 81 82func f5(t, u *T) { 83 t.X = &u.Y // ERROR "write barrier" 84} 85 86func f6(t *T) { 87 t.M = map[int]int{1: 2} // ERROR "write barrier" 88} 89 90func f7(x, y *int) []*int { 91 var z [3]*int 92 i := 0 93 z[i] = x // ERROR "write barrier" 94 i++ 95 z[i] = y // ERROR "write barrier" 96 i++ 97 return z[:i] 98} 99 100func f9(x *interface{}, v *byte) { 101 *x = v // ERROR "write barrier" 102} 103 104func f10(x *byte, f func(interface{})) { 105 f(x) 106} 107 108func f11(x *unsafe.Pointer, y unsafe.Pointer) { 109 *x = unsafe.Pointer(uintptr(y) + 1) // ERROR "write barrier" 110} 111 112func f12(x []*int, y *int) []*int { 113 // write barrier for storing y in x's underlying array 114 x = append(x, y) // ERROR "write barrier" 115 return x 116} 117 118func f12a(x []int, y int) []int { 119 // y not a pointer, so no write barriers in this function 120 x = append(x, y) 121 return x 122} 123 124func f13(x []int, y *[]int) { 125 *y = append(x, 1) // ERROR "write barrier" 126} 127 128func f14(y *[]int) { 129 *y = append(*y, 1) // ERROR "write barrier" 130} 131 132type T1 struct { 133 X *int 134} 135 136func f15(x []T1, y T1) []T1 { 137 return append(x, y) // ERROR "write barrier" 138} 139 140type T8 struct { 141 X [8]*int 142} 143 144func f16(x []T8, y T8) []T8 { 145 return append(x, y) // ERROR "write barrier" 146} 147 148func t1(i interface{}) **int { 149 // From issue 14306, make sure we have write barriers in a type switch 150 // where the assigned variable escapes. 151 switch x := i.(type) { 152 case *int: // ERROR "write barrier" 153 return &x 154 } 155 switch y := i.(type) { 156 case **int: // no write barrier here 157 return y 158 } 159 return nil 160} 161 162type T17 struct { 163 f func(*T17) 164} 165 166func f17(x *T17) { 167 // Originally from golang.org/issue/13901, but the hybrid 168 // barrier requires both to have barriers. 169 x.f = f17 // ERROR "write barrier" 170 x.f = func(y *T17) { *y = *x } // ERROR "write barrier" 171} 172 173type T18 struct { 174 a []int 175 s string 176} 177 178func f18(p *T18, x *[]int) { 179 p.a = p.a[:5] // no barrier 180 *x = (*x)[0:5] // no barrier 181 p.a = p.a[3:5] // ERROR "write barrier" 182 p.a = p.a[1:2:3] // ERROR "write barrier" 183 p.s = p.s[8:9] // ERROR "write barrier" 184 *x = (*x)[3:5] // ERROR "write barrier" 185} 186 187func f19(x, y *int, i int) int { 188 // Constructing a temporary slice on the stack should not 189 // require any write barriers. See issue 14263. 190 a := []*int{x, y} // no barrier 191 return *a[i] 192} 193 194func f20(x, y *int, i int) []*int { 195 // ... but if that temporary slice escapes, then the 196 // write barriers are necessary. 197 a := []*int{x, y} // ERROR "write barrier" 198 return a 199} 200 201var x21 *int 202var y21 struct { 203 x *int 204} 205var z21 int 206 207// f21x: Global -> heap pointer updates must have write barriers. 208func f21a(x *int) { 209 x21 = x // ERROR "write barrier" 210 y21.x = x // ERROR "write barrier" 211} 212 213func f21b(x *int) { 214 x21 = &z21 // ERROR "write barrier" 215 y21.x = &z21 // ERROR "write barrier" 216} 217 218func f21c(x *int) { 219 y21 = struct{ x *int }{x} // ERROR "write barrier" 220} 221 222func f22(x *int) (y *int) { 223 // pointer write on stack should have no write barrier. 224 // this is a case that the frontend failed to eliminate. 225 p := &y 226 *p = x // no barrier 227 return 228} 229 230type T23 struct { 231 p *int 232 a int 233} 234 235var t23 T23 236var i23 int 237 238// f23x: zeroing global needs write barrier for the hybrid barrier. 239func f23a() { 240 t23 = T23{} // ERROR "write barrier" 241} 242 243func f23b() { 244 // also test partial assignments 245 t23 = T23{a: 1} // ERROR "write barrier" 246} 247 248func f23c() { 249 t23 = T23{} // no barrier (dead store) 250 // also test partial assignments 251 t23 = T23{p: &i23} // ERROR "write barrier" 252} 253 254var g int 255 256func f24() **int { 257 p := new(*int) 258 *p = &g // no write barrier here 259 return p 260} 261func f25() []string { 262 return []string{"abc", "def", "ghi"} // no write barrier here 263} 264 265type T26 struct { 266 a, b, c int 267 d, e, f *int 268} 269 270var g26 int 271 272func f26(p *int) *T26 { // see issue 29573 273 return &T26{ 274 a: 5, 275 b: 6, 276 c: 7, 277 d: &g26, // no write barrier: global ptr 278 e: nil, // no write barrier: nil ptr 279 f: p, // ERROR "write barrier" 280 } 281} 282 283func f27(p *int) []interface{} { 284 return []interface{}{ 285 nil, // no write barrier: zeroed memory, nil ptr 286 (*T26)(nil), // no write barrier: zeroed memory, type ptr & nil ptr 287 &g26, // no write barrier: zeroed memory, type ptr & global ptr 288 7, // no write barrier: zeroed memory, type ptr & global ptr 289 p, // ERROR "write barrier" 290 } 291} 292 293var g28 [256]uint64 294 295func f28() []interface{} { 296 return []interface{}{ 297 false, // no write barrier 298 true, // no write barrier 299 0, // no write barrier 300 1, // no write barrier 301 uint8(127), // no write barrier 302 int8(-4), // no write barrier 303 &g28[5], // no write barrier 304 } 305} 306