LEFT | RIGHT |
1 // errchk -0 $G -sm $D/$F.go | 1 // errchk -0 $G -sm $D/$F.go |
2 | 2 |
3 // Copyright 2010 The Go Authors. All rights reserved. | 3 // Copyright 2010 The Go Authors. All rights reserved. |
4 // Use of this source code is governed by a BSD-style | 4 // Use of this source code is governed by a BSD-style |
5 // license that can be found in the LICENSE file. | 5 // license that can be found in the LICENSE file. |
6 | 6 |
7 package foo | 7 package foo |
8 | 8 |
9 import "unsafe" | 9 import "unsafe" |
10 | 10 |
11 var gxx *int | 11 var gxx *int |
12 | 12 |
13 func foo1(x int) { // ERROR "moved to heap: NAME-x" | 13 func foo1(x int) { // ERROR "moved to heap: NAME-x" |
14 gxx = &x | 14 gxx = &x |
15 } | 15 } |
16 | 16 |
17 func foo2(yy *int) { // ERROR "leaking param: NAME-yy" | 17 func foo2(yy *int) { // ERROR "leaking param: NAME-yy" |
18 gxx = yy | 18 gxx = yy |
19 } | 19 } |
20 | 20 |
21 func foo3(x int) *int { // ERROR "moved to heap: NAME-x" | 21 func foo3(x int) *int { // ERROR "moved to heap: NAME-x" |
22 return &x | 22 return &x |
23 } | 23 } |
24 | 24 |
| 25 type T *T |
| 26 func foo3b(t T) { // ERROR "leaking param: NAME-t" |
| 27 *t = t |
| 28 } |
| 29 |
25 // xx isn't going anywhere, so use of yy is ok | 30 // xx isn't going anywhere, so use of yy is ok |
26 func foo4(xx, yy *int) { | 31 func foo4(xx, yy *int) { |
27 xx = yy | 32 xx = yy |
28 } | 33 } |
29 | 34 |
30 // xx isn't going anywhere, so taking address of yy is ok | 35 // xx isn't going anywhere, so taking address of yy is ok |
31 func foo5(xx **int, yy *int) { | 36 func foo5(xx **int, yy *int) { |
32 xx = &yy | 37 xx = &yy |
33 } | 38 } |
34 | 39 |
35 func foo6(xx **int, yy *int) { // ERROR "leaking param: NAME-yy" | 40 func foo6(xx **int, yy *int) { // ERROR "leaking param: NAME-yy" |
36 *xx = yy | 41 *xx = yy |
37 } | 42 } |
38 | 43 |
39 func foo7(xx **int, yy *int) { | 44 func foo7(xx **int, yy *int) { |
40 **xx = *yy | 45 **xx = *yy |
41 } | 46 } |
42 | 47 |
43 func foo8(xx, yy *int) int { | 48 func foo8(xx, yy *int) int { |
44 xx = yy | 49 xx = yy |
45 return *xx | 50 return *xx |
46 } | 51 } |
47 | 52 |
48 // also xx, but chkmsg takes only 1 | 53 func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-xx" "leaking param:
NAME-yy" |
49 func foo9(xx, yy *int) *int { // ERROR "leaking param: NAME-yy" | |
50 xx = yy | 54 xx = yy |
51 return xx | 55 return xx |
52 } | 56 } |
53 | 57 |
54 func foo10(xx, yy *int) { | 58 func foo10(xx, yy *int) { |
55 *xx = *yy | 59 *xx = *yy |
56 } | 60 } |
57 | 61 |
58 func foo11() int { | 62 func foo11() int { |
59 x, y := 0, 42 | 63 x, y := 0, 42 |
60 xx := &x | 64 xx := &x |
61 yy := &y | 65 yy := &y |
62 *xx = *yy | 66 *xx = *yy |
63 return x | 67 return x |
64 } | 68 } |
65 | 69 |
66 | 70 |
67 var xxx **int | 71 var xxx **int |
68 | 72 |
69 func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy" | 73 func foo12(yyy **int) { // ERROR "leaking param: NAME-yyy" |
70 xxx = yyy | 74 xxx = yyy |
71 } | 75 } |
72 | 76 |
73 // spurious | 77 func foo13(yyy **int) { |
74 func foo13(yyy **int) { // ERROR "leaking param: NAME-yyy" | |
75 *xxx = *yyy | 78 *xxx = *yyy |
76 } | 79 } |
77 | 80 |
78 // spurious | 81 func foo14(yyy **int) { |
79 func foo14(yyy **int) { // ERROR "leaking param: NAME-yyy" | |
80 **xxx = **yyy | 82 **xxx = **yyy |
81 } | 83 } |
82 | 84 |
83 func foo15(yy *int) { // ERROR "moved to heap: NAME-yy" | 85 func foo15(yy *int) { // ERROR "moved to heap: NAME-yy" |
84 xxx = &yy | 86 xxx = &yy |
85 } | 87 } |
86 | 88 |
87 func foo16(yy *int) { // ERROR "leaking param: NAME-yy" | 89 func foo16(yy *int) { // ERROR "leaking param: NAME-yy" |
88 *xxx = yy | 90 *xxx = yy |
89 } | 91 } |
(...skipping 12 matching lines...) Expand all Loading... |
102 | 104 |
103 type Bar struct { | 105 type Bar struct { |
104 i int | 106 i int |
105 ii *int | 107 ii *int |
106 } | 108 } |
107 | 109 |
108 func NewBar() *Bar { | 110 func NewBar() *Bar { |
109 return &Bar{ 42, nil } | 111 return &Bar{ 42, nil } |
110 } | 112 } |
111 | 113 |
112 // spurious | 114 func NewBarp(x *int) *Bar { // ERROR "leaking param: NAME-x" |
113 func (b *Bar) NoLeak() int { // ERROR "leaking param: NAME-b" | 115 » return &Bar{ 42, x } |
| 116 } |
| 117 |
| 118 func NewBarp2(x *int) *Bar { |
| 119 » return &Bar{ *x, nil } |
| 120 } |
| 121 |
| 122 func (b *Bar) NoLeak() int { |
114 return *(b.ii) | 123 return *(b.ii) |
115 } | 124 } |
116 | 125 |
117 // spurious | 126 func (b *Bar) AlsoNoLeak() *int { |
118 func (b *Bar) AlsoNoLeak() *int { // ERROR "leaking param: NAME-b" | |
119 return b.ii | 127 return b.ii |
120 } | 128 } |
121 | 129 |
122 type Bar2 struct { | 130 type Bar2 struct { |
123 i [12]int | 131 i [12]int |
124 ii []int | 132 ii []int |
125 } | 133 } |
126 | 134 |
127 func NewBar2() *Bar2 { | 135 func NewBar2() *Bar2 { |
128 return &Bar2{ [12]int{ 42 }, nil } | 136 return &Bar2{ [12]int{ 42 }, nil } |
129 } | 137 } |
130 | 138 |
131 func (b *Bar2) NoLeak() int { | 139 func (b *Bar2) NoLeak() int { |
132 return b.i[0] | 140 return b.i[0] |
133 } | 141 } |
134 | 142 |
135 func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b" | 143 func (b *Bar2) Leak() []int { // ERROR "leaking param: NAME-b" |
| 144 return b.i[:] |
| 145 } |
| 146 |
| 147 func (b *Bar2) AlsoNoLeak() []int { |
136 return b.ii[0:1] | 148 return b.ii[0:1] |
| 149 } |
| 150 |
| 151 func (b *Bar2) LeakSelf() { // ERROR "leaking param: NAME-b" |
| 152 b.ii = b.i[0:4] |
| 153 } |
| 154 |
| 155 func (b *Bar2) LeakSelf2() { // ERROR "leaking param: NAME-b" |
| 156 var buf []int |
| 157 buf = b.i[0:] |
| 158 b.ii = buf |
137 } | 159 } |
138 | 160 |
139 func foo21() func() int { | 161 func foo21() func() int { |
140 x := 42 // ERROR "moved to heap: NAME-x" | 162 x := 42 // ERROR "moved to heap: NAME-x" |
141 return func() int { | 163 return func() int { |
142 return x | 164 return x |
143 } | 165 } |
144 } | 166 } |
145 | 167 |
146 func foo22() int { | 168 func foo22() int { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 } | 209 } |
188 | 210 |
189 func foo31(x int) int { // ERROR "moved to heap: NAME-x" | 211 func foo31(x int) int { // ERROR "moved to heap: NAME-x" |
190 return fooleak(&x) | 212 return fooleak(&x) |
191 } | 213 } |
192 | 214 |
193 func foo32(x int) int { | 215 func foo32(x int) int { |
194 return foonoleak(&x) | 216 return foonoleak(&x) |
195 } | 217 } |
196 | 218 |
197 | |
198 type Foo struct { | 219 type Foo struct { |
199 xx *int | 220 xx *int |
200 x int | 221 x int |
201 } | 222 } |
202 | 223 |
203 var F Foo | 224 var F Foo |
| 225 var pf *Foo |
| 226 |
| 227 func (f *Foo) fooleak() { // ERROR "leaking param: NAME-f" |
| 228 pf = f |
| 229 } |
| 230 |
| 231 func (f *Foo) foonoleak() { |
| 232 F.x = f.x |
| 233 } |
| 234 |
| 235 func (f *Foo) Leak() { // ERROR "leaking param: NAME-f" |
| 236 f.fooleak() |
| 237 } |
| 238 |
| 239 func (f *Foo) NoLeak() { |
| 240 f.foonoleak() |
| 241 } |
| 242 |
204 | 243 |
205 func foo41(x int) { // ERROR "moved to heap: NAME-x" | 244 func foo41(x int) { // ERROR "moved to heap: NAME-x" |
206 F.xx = &x | 245 F.xx = &x |
207 } | 246 } |
208 | 247 |
209 func (f *Foo) foo42(x int) { // ERROR "moved to heap: NAME-x" | 248 func (f *Foo) foo42(x int) { // ERROR "moved to heap: NAME-x" |
210 f.xx = &x | 249 f.xx = &x |
211 } | 250 } |
212 | 251 |
213 func foo43(f *Foo, x int) { // ERROR "moved to heap: NAME-x" | 252 func foo43(f *Foo, x int) { // ERROR "moved to heap: NAME-x" |
214 f.xx = &x | 253 f.xx = &x |
215 } | 254 } |
216 | 255 |
217 func foo44(yy *int) { // ERROR "leaking param: NAME-yy" | 256 func foo44(yy *int) { // ERROR "leaking param: NAME-yy" |
218 F.xx = yy | 257 F.xx = yy |
219 } | 258 } |
220 | 259 |
221 func (f *Foo) foo45() { | 260 func (f *Foo) foo45() { |
222 F.x = f.x· | 261 F.x = f.x· |
223 } | 262 } |
224 | 263 |
225 // spurious | 264 func (f *Foo) foo46() { |
226 func (f *Foo) foo46() { // ERROR "leaking param: NAME-f" | |
227 F.xx = f.xx· | 265 F.xx = f.xx· |
228 } | 266 } |
229 | 267 |
230 func (f *Foo) foo47() { // ERROR "leaking param: NAME-f" | 268 func (f *Foo) foo47() { // ERROR "leaking param: NAME-f" |
231 f.xx = &f.x | 269 f.xx = &f.x |
232 } | 270 } |
233 | 271 |
234 | 272 |
235 var ptrSlice []*int | 273 var ptrSlice []*int |
236 | 274 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // track-losing dereference. | 382 // track-losing dereference. |
345 func foo62(i *int) *int { // ERROR "leaking param: NAME-i" | 383 func foo62(i *int) *int { // ERROR "leaking param: NAME-i" |
346 type S struct { | 384 type S struct { |
347 a,b *int | 385 a,b *int |
348 } | 386 } |
349 s := new(S) | 387 s := new(S) |
350 s.a = i | 388 s.a = i |
351 return nil // s.b | 389 return nil // s.b |
352 } | 390 } |
353 | 391 |
| 392 |
| 393 type M interface { M() } |
| 394 |
| 395 func foo63(m M) { |
| 396 } |
| 397 |
| 398 func foo64(m M) { // ERROR "leaking param: NAME-m" |
| 399 m.M() |
| 400 } |
| 401 |
| 402 type MV int |
| 403 func (MV) M() {} |
| 404 |
| 405 func foo65() { |
| 406 var mv MV |
| 407 foo63(&mv) |
| 408 } |
| 409 |
| 410 func foo66() { |
| 411 var mv MV // ERROR "moved to heap: NAME-mv" |
| 412 foo64(&mv) |
| 413 } |
| 414 |
| 415 func foo67() { |
| 416 var mv MV |
| 417 foo63(mv) |
| 418 } |
| 419 |
| 420 func foo68() { |
| 421 var mv MV |
| 422 foo64(mv) // escapes but it's an int so irrelevant |
| 423 } |
| 424 |
| 425 func foo69(m M) { // ERROR "leaking param: NAME-m" |
| 426 foo64(m) |
| 427 } |
| 428 |
| 429 func foo70(mv1 *MV, m M) { // ERROR "leaking param: NAME-mv1" "leaking param: N
AME-m" |
| 430 m = mv1 |
| 431 foo64(m) |
| 432 } |
| 433 |
| 434 func foo71(x *int) []*int { // ERROR "leaking param: NAME-x" |
| 435 var y []*int |
| 436 y = append(y, x) |
| 437 return y |
| 438 } |
| 439 |
| 440 func foo71a(x int) []*int { // ERROR "moved to heap: NAME-x" |
| 441 var y []*int |
| 442 y = append(y, &x) |
| 443 return y |
| 444 } |
| 445 |
| 446 func foo72() { |
| 447 var x int |
| 448 var y [1]*int |
| 449 y[0] = &x |
| 450 } |
| 451 |
| 452 func foo72aa() [10]*int { |
| 453 var x int // ERROR "moved to heap: NAME-x" |
| 454 var y [10]*int |
| 455 y[0] = &x |
| 456 return y |
| 457 } |
| 458 |
| 459 func foo72a() { |
| 460 var y [10]*int |
| 461 for i := 0; i < 10; i++ { |
| 462 x := i // not moved to heap b/c y goes nowhere |
| 463 y[i] = &x |
| 464 } |
| 465 return |
| 466 } |
| 467 |
| 468 func foo72b() [10]*int { |
| 469 var y [10]*int |
| 470 for i := 0; i < 10; i++ { |
| 471 x := i // ERROR "moved to heap: NAME-x" |
| 472 y[i] = &x |
| 473 } |
| 474 return y |
| 475 } |
| 476 |
| 477 |
| 478 // issue 2145 |
| 479 func foo73() { |
| 480 s := []int{3,2,1} |
| 481 for _, v := range s { |
| 482 vv := v // ERROR "moved to heap: NAME-vv" |
| 483 defer func() { // "func literal escapes its scope" "&vv escape
s its scope" |
| 484 println(vv) |
| 485 }() |
| 486 } |
| 487 } |
| 488 |
| 489 func foo74() { |
| 490 s := []int{3,2,1} |
| 491 for _, v := range s { |
| 492 vv := v // ERROR "moved to heap: NAME-vv" |
| 493 fn := func() { // "func literal escapes its scope" "&vv escape
s its scope" |
| 494 println(vv) |
| 495 } |
| 496 defer fn() |
| 497 } |
| 498 } |
| 499 |
| 500 func myprint(y *int, x ...interface{}) *int { // ERROR "leaking param: NAME-y" |
| 501 return y |
| 502 } |
| 503 |
| 504 func myprint1(y *int, x ...interface{}) *interface{} { // ERROR "leaking param:
NAME-x" |
| 505 return &x[0] |
| 506 } |
| 507 |
| 508 func foo75(z *int) { // ERROR "leaking param: NAME-z" |
| 509 myprint(z, 1, 2, 3) |
| 510 } |
| 511 |
| 512 func foo75a(z *int) { |
| 513 myprint1(z, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 514 } |
| 515 |
| 516 func foo76(z *int) { |
| 517 myprint(nil, z) |
| 518 } |
| 519 |
| 520 func foo76a(z *int) { // ERROR "leaking param: NAME-z" |
| 521 myprint1(nil, z) // "[.][.][.] argument escapes to heap" |
| 522 } |
| 523 |
| 524 func foo76b() { |
| 525 myprint(nil, 1, 2, 3) |
| 526 } |
| 527 |
| 528 func foo76c() { |
| 529 myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 530 } |
| 531 |
| 532 func foo76d() { |
| 533 defer myprint(nil, 1, 2, 3) |
| 534 } |
| 535 |
| 536 func foo76e() { |
| 537 defer myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to heap" |
| 538 } |
| 539 |
| 540 func foo76f() { |
| 541 for { |
| 542 defer myprint(nil, 1, 2, 3) // "[.][.][.] argument escapes its s
cope" |
| 543 } |
| 544 } |
| 545 |
| 546 func foo76g() { |
| 547 for { |
| 548 defer myprint1(nil, 1, 2, 3) // "[.][.][.] argument escapes to h
eap" |
| 549 } |
| 550 } |
| 551 |
| 552 func foo77(z []interface{}) { |
| 553 myprint(nil, z...) // z does not escape |
| 554 } |
| 555 |
| 556 func foo77a(z []interface{}) { // ERROR "leaking param: NAME-z" |
| 557 myprint1(nil, z...) |
| 558 } |
| 559 |
| 560 func foo78(z int) *int { // ERROR "moved to heap: NAME-z" |
| 561 return &z // "&z escapes" |
| 562 } |
| 563 |
| 564 func foo78a(z int) *int { // ERROR "moved to heap: NAME-z" |
| 565 y := &z |
| 566 x := &y |
| 567 return *x // really return y |
| 568 } |
| 569 |
| 570 func foo79() *int { |
| 571 return new(int) // "moved to heap: new[(]int[)]" |
| 572 } |
| 573 |
| 574 func foo80() *int { |
| 575 var z *int |
| 576 for { |
| 577 z = new(int) // "new[(]int[)] escapes its scope" |
| 578 } |
| 579 _ = z |
| 580 return nil |
| 581 } |
| 582 |
| 583 func foo81() *int { |
| 584 for { |
| 585 z := new(int) |
| 586 _ = z |
| 587 } |
| 588 return nil |
| 589 } |
| 590 |
| 591 type Fooer interface { |
| 592 Foo() |
| 593 } |
| 594 |
| 595 type LimitedFooer struct { |
| 596 Fooer |
| 597 N int64 |
| 598 } |
| 599 |
| 600 func LimitFooer(r Fooer, n int64) Fooer { // ERROR "leaking param: NAME-r" |
| 601 return &LimitedFooer{r, n} |
| 602 } |
| 603 |
| 604 func foo90(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" |
| 605 return map[*int]*int{ nil: x } |
| 606 } |
| 607 |
| 608 func foo91(x *int) map[*int]*int { // ERROR "leaking param: NAME-x" |
| 609 return map[*int]*int{ x:nil } |
| 610 } |
| 611 |
| 612 func foo92(x *int) [2]*int { // ERROR "leaking param: NAME-x" |
| 613 return [2]*int{ x, nil } |
| 614 } |
| 615 |
LEFT | RIGHT |