diff --git a/tools/checklocks/facts.go b/tools/checklocks/facts.go index d978a2bee..3ea106378 100644 --- a/tools/checklocks/facts.go +++ b/tools/checklocks/facts.go @@ -670,7 +670,11 @@ func (pc *passContext) structLockGuardFacts(structType *types.Struct, ss *ast.St for i, field := range ss.Fields.List { var lgf lockGuardFacts fieldObj = structType.Field(i) // N.B. Captured above. - pc.fillLockGuardFacts(fieldObj, field.Doc, findLocal, &lgf) + if field.Doc != nil { + pc.fillLockGuardFacts(fieldObj, field.Doc, findLocal, &lgf) + } else if field.Comment != nil { + pc.fillLockGuardFacts(fieldObj, field.Comment, findLocal, &lgf) + } // See above, for anonymous structure fields. if ss, ok := field.Type.(*ast.StructType); ok { diff --git a/tools/checklocks/test/basics.go b/tools/checklocks/test/basics.go index e941fba5b..554b88608 100644 --- a/tools/checklocks/test/basics.go +++ b/tools/checklocks/test/basics.go @@ -143,3 +143,13 @@ func testTwoLocksDoubleGuardStructOnlyOne(tc *twoLocksDoubleGuardStruct) { func testTwoLocksDoubleGuardStructInvalid(tc *twoLocksDoubleGuardStruct) { tc.doubleGuardedField = 3 // +checklocksfail:2 } + +func testFieldCommentValid(tc *fieldCommentStruct) { + tc.mu.Lock() + tc.guardedField = 1 + tc.mu.Unlock() +} + +func testFieldCommentInvalid(tc *fieldCommentStruct) { + tc.guardedField = 2 // +checklocksfail +} diff --git a/tools/checklocks/test/test.go b/tools/checklocks/test/test.go index fd2a92162..61d6b3a2b 100644 --- a/tools/checklocks/test/test.go +++ b/tools/checklocks/test/test.go @@ -64,3 +64,10 @@ type nestedGuardStruct struct { val oneGuardStruct ptr *oneGuardStruct } + +// fieldCommentStruct has one lock and a single field, but uses the +// field.Comment instead of field.Doc for the guard. +type fieldCommentStruct struct { + mu sync.Mutex + guardedField int // +checklocks:mu +}