mirror of
https://github.com/golang/go
synced 2024-11-18 20:14:43 -07:00
go/analysis/passes/atomicalign: handle pointers to struct
The atomicalign checker detects non-64-bit aligned struct field arguments to sync/atomic functions but currently misses out cases where the struct variable identifier is a pointer to struct. This is very common as it happens when the 64-bit field is accessed in a method with pointer receiver, where the struct is itself the method receiver. Add some tests to cover that new case. While I'm at it, fix some typos. Change-Id: I582cf5b7286b11285010f085045f58dc636ef3ee Reviewed-on: https://go-review.googlesource.com/c/158999 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
bb1329dc71
commit
8dbcc66f33
@ -21,7 +21,7 @@ import (
|
|||||||
|
|
||||||
var Analyzer = &analysis.Analyzer{
|
var Analyzer = &analysis.Analyzer{
|
||||||
Name: "atomicalign",
|
Name: "atomicalign",
|
||||||
Doc: "check for non-64-bits-aligned arguments to sync/atomic functions",
|
Doc: "check for non-64-bit-aligned arguments to sync/atomic functions",
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
Run: run,
|
Run: run,
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func check64BitAlignment(pass *analysis.Pass, funcName string, arg ast.Expr) {
|
func check64BitAlignment(pass *analysis.Pass, funcName string, arg ast.Expr) {
|
||||||
// Checks the argument is made of the address operator (&) applied to
|
// Checks the argument is made of the address operator (&) applied
|
||||||
// to a struct field (as opposed to a variable as the first word of
|
// to a struct field (as opposed to a variable as the first word of
|
||||||
// uint64 and int64 variables can be relied upon to be 64-bit aligned.
|
// uint64 and int64 variables can be relied upon to be 64-bit aligned.
|
||||||
unary, ok := arg.(*ast.UnaryExpr)
|
unary, ok := arg.(*ast.UnaryExpr)
|
||||||
@ -80,16 +80,18 @@ func check64BitAlignment(pass *analysis.Pass, funcName string, arg ast.Expr) {
|
|||||||
|
|
||||||
// Retrieve the types.Struct in order to get the offset of the
|
// Retrieve the types.Struct in order to get the offset of the
|
||||||
// atomically accessed field.
|
// atomically accessed field.
|
||||||
sel, ok := unary.X.(*ast.SelectorExpr)
|
selector, ok := unary.X.(*ast.SelectorExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tvar, ok := pass.TypesInfo.Selections[sel].Obj().(*types.Var)
|
|
||||||
|
sel := pass.TypesInfo.Selections[selector]
|
||||||
|
tvar, ok := sel.Obj().(*types.Var)
|
||||||
if !ok || !tvar.IsField() {
|
if !ok || !tvar.IsField() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
stype, ok := pass.TypesInfo.Types[sel.X].Type.Underlying().(*types.Struct)
|
stype, ok := sel.Recv().Underlying().(*types.Struct)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -228,3 +228,22 @@ func embeddedStructFields() {
|
|||||||
atomic.AddUint64(&s1.b, 9) // want "address of non 64-bit aligned field .b passed to atomic.AddUint64"
|
atomic.AddUint64(&s1.b, 9) // want "address of non 64-bit aligned field .b passed to atomic.AddUint64"
|
||||||
atomic.AddInt64(&s1.c, 9)
|
atomic.AddInt64(&s1.c, 9)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type t struct {
|
||||||
|
_ int32
|
||||||
|
a int64
|
||||||
|
_ int16
|
||||||
|
_ int16
|
||||||
|
b uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *t) structPointerReceiver() {
|
||||||
|
atomic.LoadInt64(&t.a) // want "address of non 64-bit aligned field .a passed to atomic.LoadInt64"
|
||||||
|
atomic.LoadUint64(&t.b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func structPointer() {
|
||||||
|
t := &t{}
|
||||||
|
atomic.StoreInt64(&t.a, -1) // want "address of non 64-bit aligned field .a passed to atomic.StoreInt64"
|
||||||
|
atomic.StoreUint64(&t.b, 1)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user