@@ -18,7 +18,7 @@ func init() {
18
18
register ("copylocks" ,
19
19
"check that locks are not passed by value" ,
20
20
checkCopyLocks ,
21
- funcDecl , rangeStmt , funcLit , assignStmt )
21
+ funcDecl , rangeStmt , funcLit , assignStmt , genDecl , compositeLit )
22
22
}
23
23
24
24
// checkCopyLocks checks whether node might
@@ -33,15 +33,47 @@ func checkCopyLocks(f *File, node ast.Node) {
33
33
checkCopyLocksFunc (f , "func" , nil , node .Type )
34
34
case * ast.AssignStmt :
35
35
checkCopyLocksAssign (f , node )
36
+ case * ast.GenDecl :
37
+ checkCopyLocksGenDecl (f , node )
38
+ case * ast.CompositeLit :
39
+ checkCopyCompositeLit (f , node )
36
40
}
37
41
}
38
42
39
43
// checkCopyLocksAssign checks whether an assignment
40
44
// copies a lock.
41
45
func checkCopyLocksAssign (f * File , as * ast.AssignStmt ) {
42
- for _ , x := range as .Lhs {
43
- if path := lockPath (f .pkg .typesPkg , f .pkg .types [x ].Type ); path != nil {
44
- f .Badf (x .Pos (), "assignment copies lock value to %v: %v" , f .gofmt (x ), path )
46
+ for i , x := range as .Rhs {
47
+ if path := lockPathRhs (f , x ); path != nil {
48
+ f .Badf (x .Pos (), "assignment copies lock value to %v: %v" , f .gofmt (as .Lhs [i ]), path )
49
+ }
50
+ }
51
+ }
52
+
53
+ // checkCopyLocksGenDecl checks whether lock is copied
54
+ // in variable declaration.
55
+ func checkCopyLocksGenDecl (f * File , gd * ast.GenDecl ) {
56
+ if gd .Tok != token .VAR {
57
+ return
58
+ }
59
+ for _ , spec := range gd .Specs {
60
+ valueSpec := spec .(* ast.ValueSpec )
61
+ for i , x := range valueSpec .Values {
62
+ if path := lockPathRhs (f , x ); path != nil {
63
+ f .Badf (x .Pos (), "variable declaration copies lock value to %v: %v" , valueSpec .Names [i ].Name , path )
64
+ }
65
+ }
66
+ }
67
+ }
68
+
69
+ // checkCopyCompositeLit detects lock copy inside a composite literal
70
+ func checkCopyCompositeLit (f * File , cl * ast.CompositeLit ) {
71
+ for _ , x := range cl .Elts {
72
+ if node , ok := x .(* ast.KeyValueExpr ); ok {
73
+ x = node .Value
74
+ }
75
+ if path := lockPathRhs (f , x ); path != nil {
76
+ f .Badf (x .Pos (), "literal copies lock value from %v: %v" , f .gofmt (x ), path )
45
77
}
46
78
}
47
79
}
@@ -132,6 +164,13 @@ func (path typePath) String() string {
132
164
return buf .String ()
133
165
}
134
166
167
+ func lockPathRhs (f * File , x ast.Expr ) typePath {
168
+ if _ , ok := x .(* ast.CompositeLit ); ok {
169
+ return nil
170
+ }
171
+ return lockPath (f .pkg .typesPkg , f .pkg .types [x ].Type )
172
+ }
173
+
135
174
// lockPath returns a typePath describing the location of a lock value
136
175
// contained in typ. If there is no contained lock, it returns nil.
137
176
func lockPath (tpkg * types.Package , typ types.Type ) typePath {
0 commit comments