@@ -18,7 +18,7 @@ func init() {
1818 register ("copylocks" ,
1919 "check that locks are not passed by value" ,
2020 checkCopyLocks ,
21- funcDecl , rangeStmt , funcLit , assignStmt )
21+ funcDecl , rangeStmt , funcLit , assignStmt , genDecl , compositeLit )
2222}
2323
2424// checkCopyLocks checks whether node might
@@ -33,15 +33,47 @@ func checkCopyLocks(f *File, node ast.Node) {
3333 checkCopyLocksFunc (f , "func" , nil , node .Type )
3434 case * ast.AssignStmt :
3535 checkCopyLocksAssign (f , node )
36+ case * ast.GenDecl :
37+ checkCopyLocksGenDecl (f , node )
38+ case * ast.CompositeLit :
39+ checkCopyCompositeLit (f , node )
3640 }
3741}
3842
3943// checkCopyLocksAssign checks whether an assignment
4044// copies a lock.
4145func 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 )
4577 }
4678 }
4779}
@@ -132,6 +164,13 @@ func (path typePath) String() string {
132164 return buf .String ()
133165}
134166
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+
135174// lockPath returns a typePath describing the location of a lock value
136175// contained in typ. If there is no contained lock, it returns nil.
137176func lockPath (tpkg * types.Package , typ types.Type ) typePath {
0 commit comments