Home | History | Annotate | Download | only in testdata
      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 // This file contains tests for the copylock checker's
      6 // function declaration analysis.
      7 
      8 package testdata
      9 
     10 import "sync"
     11 
     12 func OkFunc(*sync.Mutex) {}
     13 func BadFunc(sync.Mutex) {} // ERROR "BadFunc passes lock by value: sync.Mutex"
     14 func BadFunc2(sync.Map)  {} // ERROR "BadFunc2 passes lock by value: sync.Map contains sync.Mutex"
     15 func OkRet() *sync.Mutex {}
     16 func BadRet() sync.Mutex {} // Don't warn about results
     17 
     18 var (
     19 	OkClosure   = func(*sync.Mutex) {}
     20 	BadClosure  = func(sync.Mutex) {} // ERROR "func passes lock by value: sync.Mutex"
     21 	BadClosure2 = func(sync.Map) {}   // ERROR "func passes lock by value: sync.Map contains sync.Mutex"
     22 )
     23 
     24 type EmbeddedRWMutex struct {
     25 	sync.RWMutex
     26 }
     27 
     28 func (*EmbeddedRWMutex) OkMeth() {}
     29 func (EmbeddedRWMutex) BadMeth() {} // ERROR "BadMeth passes lock by value: testdata.EmbeddedRWMutex"
     30 func OkFunc(e *EmbeddedRWMutex)  {}
     31 func BadFunc(EmbeddedRWMutex)    {} // ERROR "BadFunc passes lock by value: testdata.EmbeddedRWMutex"
     32 func OkRet() *EmbeddedRWMutex    {}
     33 func BadRet() EmbeddedRWMutex    {} // Don't warn about results
     34 
     35 type FieldMutex struct {
     36 	s sync.Mutex
     37 }
     38 
     39 func (*FieldMutex) OkMeth()   {}
     40 func (FieldMutex) BadMeth()   {} // ERROR "BadMeth passes lock by value: testdata.FieldMutex contains sync.Mutex"
     41 func OkFunc(*FieldMutex)      {}
     42 func BadFunc(FieldMutex, int) {} // ERROR "BadFunc passes lock by value: testdata.FieldMutex contains sync.Mutex"
     43 
     44 type L0 struct {
     45 	L1
     46 }
     47 
     48 type L1 struct {
     49 	l L2
     50 }
     51 
     52 type L2 struct {
     53 	sync.Mutex
     54 }
     55 
     56 func (*L0) Ok() {}
     57 func (L0) Bad() {} // ERROR "Bad passes lock by value: testdata.L0 contains testdata.L1 contains testdata.L2"
     58 
     59 type EmbeddedMutexPointer struct {
     60 	s *sync.Mutex // safe to copy this pointer
     61 }
     62 
     63 func (*EmbeddedMutexPointer) Ok()      {}
     64 func (EmbeddedMutexPointer) AlsoOk()   {}
     65 func StillOk(EmbeddedMutexPointer)     {}
     66 func LookinGood() EmbeddedMutexPointer {}
     67 
     68 type EmbeddedLocker struct {
     69 	sync.Locker // safe to copy interface values
     70 }
     71 
     72 func (*EmbeddedLocker) Ok()    {}
     73 func (EmbeddedLocker) AlsoOk() {}
     74 
     75 type CustomLock struct{}
     76 
     77 func (*CustomLock) Lock()   {}
     78 func (*CustomLock) Unlock() {}
     79 
     80 func Ok(*CustomLock) {}
     81 func Bad(CustomLock) {} // ERROR "Bad passes lock by value: testdata.CustomLock"
     82 
     83 // Passing lock values into interface function arguments
     84 func FuncCallInterfaceArg(f func(a int, b interface{})) {
     85 	var m sync.Mutex
     86 	var t struct{ lock sync.Mutex }
     87 
     88 	f(1, "foo")
     89 	f(2, &t)
     90 	f(3, &sync.Mutex{})
     91 	f(4, m) // ERROR "call of f copies lock value: sync.Mutex"
     92 	f(5, t) // ERROR "call of f copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
     93 	var fntab []func(t)
     94 	fntab[0](t) // ERROR "call of fntab.0. copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
     95 }
     96 
     97 // Returning lock via interface value
     98 func ReturnViaInterface(x int) (int, interface{}) {
     99 	var m sync.Mutex
    100 	var t struct{ lock sync.Mutex }
    101 
    102 	switch x % 4 {
    103 	case 0:
    104 		return 0, "qwe"
    105 	case 1:
    106 		return 1, &sync.Mutex{}
    107 	case 2:
    108 		return 2, m // ERROR "return copies lock value: sync.Mutex"
    109 	default:
    110 		return 3, t // ERROR "return copies lock value: struct.lock sync.Mutex. contains sync.Mutex"
    111 	}
    112 }
    113 
    114 // Some cases that we don't warn about.
    115 
    116 func AcceptedCases() {
    117 	x := EmbeddedRwMutex{} // composite literal on RHS is OK (#16227)
    118 	x = BadRet()           // function call on RHS is OK (#16227)
    119 	x = *OKRet()           // indirection of function call on RHS is OK (#16227)
    120 }
    121 
    122 // TODO: Unfortunate cases
    123 
    124 // Non-ideal error message:
    125 // Since we're looking for Lock methods, sync.Once's underlying
    126 // sync.Mutex gets called out, but without any reference to the sync.Once.
    127 type LocalOnce sync.Once
    128 
    129 func (LocalOnce) Bad() {} // ERROR "Bad passes lock by value: testdata.LocalOnce contains sync.Mutex"
    130 
    131 // False negative:
    132 // LocalMutex doesn't have a Lock method.
    133 // Nevertheless, it is probably a bad idea to pass it by value.
    134 type LocalMutex sync.Mutex
    135 
    136 func (LocalMutex) Bad() {} // WANTED: An error here :(
    137