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>
diff --git a/go/analysis/passes/atomicalign/atomicalign.go b/go/analysis/passes/atomicalign/atomicalign.go
index d3fc3e2..0326bf5 100644
--- a/go/analysis/passes/atomicalign/atomicalign.go
+++ b/go/analysis/passes/atomicalign/atomicalign.go
@@ -21,7 +21,7 @@
var Analyzer = &analysis.Analyzer{
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},
Run: run,
}
@@ -70,7 +70,7 @@
}
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
// uint64 and int64 variables can be relied upon to be 64-bit aligned.
unary, ok := arg.(*ast.UnaryExpr)
@@ -80,16 +80,18 @@
// Retrieve the types.Struct in order to get the offset of the
// atomically accessed field.
- sel, ok := unary.X.(*ast.SelectorExpr)
+ selector, ok := unary.X.(*ast.SelectorExpr)
if !ok {
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() {
return
}
- stype, ok := pass.TypesInfo.Types[sel.X].Type.Underlying().(*types.Struct)
+ stype, ok := sel.Recv().Underlying().(*types.Struct)
if !ok {
return
}
diff --git a/go/analysis/passes/atomicalign/testdata/src/a/a.go b/go/analysis/passes/atomicalign/testdata/src/a/a.go
index 45dd73d..7aa7278 100644
--- a/go/analysis/passes/atomicalign/testdata/src/a/a.go
+++ b/go/analysis/passes/atomicalign/testdata/src/a/a.go
@@ -228,3 +228,22 @@
atomic.AddUint64(&s1.b, 9) // want "address of non 64-bit aligned field .b passed to atomic.AddUint64"
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)
+}