github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/vet/atomic.go (about) 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 package main 6 7 import ( 8 "go/ast" 9 "go/token" 10 ) 11 12 // checkAtomicAssignment walks the assignment statement checking for common 13 // mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1) 14 func (f *File) checkAtomicAssignment(n *ast.AssignStmt) { 15 if !vet("atomic") { 16 return 17 } 18 19 if len(n.Lhs) != len(n.Rhs) { 20 return 21 } 22 23 for i, right := range n.Rhs { 24 call, ok := right.(*ast.CallExpr) 25 if !ok { 26 continue 27 } 28 sel, ok := call.Fun.(*ast.SelectorExpr) 29 if !ok { 30 continue 31 } 32 pkg, ok := sel.X.(*ast.Ident) 33 if !ok || pkg.Name != "atomic" { 34 continue 35 } 36 37 switch sel.Sel.Name { 38 case "AddInt32", "AddInt64", "AddUint32", "AddUint64", "AddUintptr": 39 f.checkAtomicAddAssignment(n.Lhs[i], call) 40 } 41 } 42 } 43 44 // checkAtomicAddAssignment walks the atomic.Add* method calls checking for assigning the return value 45 // to the same variable being used in the operation 46 func (f *File) checkAtomicAddAssignment(left ast.Expr, call *ast.CallExpr) { 47 arg := call.Args[0] 48 broken := false 49 50 if uarg, ok := arg.(*ast.UnaryExpr); ok && uarg.Op == token.AND { 51 broken = f.gofmt(left) == f.gofmt(uarg.X) 52 } else if star, ok := left.(*ast.StarExpr); ok { 53 broken = f.gofmt(star.X) == f.gofmt(arg) 54 } 55 56 if broken { 57 f.Warn(left.Pos(), "direct assignment to atomic value") 58 } 59 }