GoPLS Viewer

Home|gopls/go/analysis/passes/copylock/testdata/src/a/copylock_func.go
1// Copyright 2013 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// This file contains tests for the copylock checker's
6// function declaration analysis.
7
8package a
9
10import "sync"
11
12func OkFunc(*sync.Mutex) {}
13func BadFunc(sync.Mutex) {} // want "BadFunc passes lock by value: sync.Mutex"
14func BadFunc2(sync.Map)  {} // want "BadFunc2 passes lock by value: sync.Map contains sync.Mutex"
15func OkRet() *sync.Mutex {}
16func BadRet() sync.Mutex {} // Don't warn about results
17
18var (
19    OkClosure   = func(*sync.Mutex) {}
20    BadClosure  = func(sync.Mutex) {} // want "func passes lock by value: sync.Mutex"
21    BadClosure2 = func(sync.Map) {}   // want "func passes lock by value: sync.Map contains sync.Mutex"
22)
23
24type EmbeddedRWMutex struct {
25    sync.RWMutex
26}
27
28func (*EmbeddedRWMutexOkMeth() {}
29func (EmbeddedRWMutexBadMeth() {} // want "BadMeth passes lock by value: a.EmbeddedRWMutex"
30func OkFunc(e *EmbeddedRWMutex)  {}
31func BadFunc(EmbeddedRWMutex)    {} // want "BadFunc passes lock by value: a.EmbeddedRWMutex"
32func OkRet() *EmbeddedRWMutex    {}
33func BadRet() EmbeddedRWMutex    {} // Don't warn about results
34
35type FieldMutex struct {
36    s sync.Mutex
37}
38
39func (*FieldMutexOkMeth()   {}
40func (FieldMutexBadMeth()   {} // want "BadMeth passes lock by value: a.FieldMutex contains sync.Mutex"
41func OkFunc(*FieldMutex)      {}
42func BadFunc(FieldMutexint) {} // want "BadFunc passes lock by value: a.FieldMutex contains sync.Mutex"
43
44type L0 struct {
45    L1
46}
47
48type L1 struct {
49    l L2
50}
51
52type L2 struct {
53    sync.Mutex
54}
55
56func (*L0Ok() {}
57func (L0Bad() {} // want "Bad passes lock by value: a.L0 contains a.L1 contains a.L2"
58
59type EmbeddedMutexPointer struct {
60    s *sync.Mutex // safe to copy this pointer
61}
62
63func (*EmbeddedMutexPointerOk()      {}
64func (EmbeddedMutexPointerAlsoOk()   {}
65func StillOk(EmbeddedMutexPointer)     {}
66func LookinGood() EmbeddedMutexPointer {}
67
68type EmbeddedLocker struct {
69    sync.Locker // safe to copy interface values
70}
71
72func (*EmbeddedLockerOk()    {}
73func (EmbeddedLockerAlsoOk() {}
74
75type CustomLock struct{}
76
77func (*CustomLockLock()   {}
78func (*CustomLockUnlock() {}
79
80func Ok(*CustomLock) {}
81func Bad(CustomLock) {} // want "Bad passes lock by value: a.CustomLock"
82
83// Passing lock values into interface function arguments
84func FuncCallInterfaceArg(f func(a intb interface{})) {
85    var m sync.Mutex
86    var t struct{ lock sync.Mutex }
87
88    f(1"foo")
89    f(2, &t)
90    f(3, &sync.Mutex{})
91    f(4m// want "call of f copies lock value: sync.Mutex"
92    f(5t// want "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
93    var fntab []func(t)
94    fntab[0](t// want "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
95}
96
97// Returning lock via interface value
98func ReturnViaInterface(x int) (int, interface{}) {
99    var m sync.Mutex
100    var t struct{ lock sync.Mutex }
101
102    switch x % 4 {
103    case 0:
104        return 0"qwe"
105    case 1:
106        return 1, &sync.Mutex{}
107    case 2:
108        return 2m // want "return copies lock value: sync.Mutex"
109    default:
110        return 3t // want "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
111    }
112}
113
114// Some cases that we don't warn about.
115
116func AcceptedCases() {
117    x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
118    x = BadRet()           // function call on RHS is OK (#16227)
119    x = *OKRet()           // indirection of function call on RHS is OK (#16227)
120}
121
122// TODO: Unfortunate cases
123
124// Non-ideal error message:
125// Since we're looking for Lock methods, sync.Once's underlying
126// sync.Mutex gets called out, but without any reference to the sync.Once.
127type LocalOnce sync.Once
128
129func (LocalOnceBad() {} // want `Bad passes lock by value: a.LocalOnce contains sync.\b.*`
130
131// False negative:
132// LocalMutex doesn't have a Lock method.
133// Nevertheless, it is probably a bad idea to pass it by value.
134type LocalMutex sync.Mutex
135
136func (LocalMutexBad() {} // WANTED: An error here :(
137
MembersX
FieldMutex.s
L0.Bad
EmbeddedLocker.AlsoOk
CustomLock.Unlock
FuncCallInterfaceArg
OkFunc.e
EmbeddedMutexPointer
EmbeddedMutexPointer.Ok
EmbeddedMutexPointer.AlsoOk
AcceptedCases.x
LocalMutex
OkRet
EmbeddedRWMutex
FieldMutex
L1
EmbeddedLocker.Ok
CustomLock
Bad
BadRet
FieldMutex.OkMeth
L2
LookinGood
FuncCallInterfaceArg.f
ReturnViaInterface
LocalMutex.Bad
EmbeddedMutexPointer.s
Ok
AcceptedCases
LocalOnce.Bad
EmbeddedRWMutex.OkMeth
ReturnViaInterface.m
LocalOnce
BadFunc2
EmbeddedRWMutex.BadMeth
FieldMutex.BadMeth
L0
StillOk
EmbeddedLocker
CustomLock.Lock
L1.l
L0.Ok
FuncCallInterfaceArg.m
ReturnViaInterface.x
Members
X