1
0
mirror of https://github.com/golang/go synced 2024-11-26 04:17:59 -07:00

cmd/gc: more race instrumentation.

Handle interface comparison correctly,
add a few more tests, mark more nodes as impossible.

R=dvyukov, golang-dev
CC=golang-dev
https://golang.org/cl/7942045
This commit is contained in:
Rémy Oudompheng 2013-03-26 08:27:18 +01:00
parent ce99bb2caf
commit eb7c51c148
2 changed files with 106 additions and 10 deletions

View File

@ -312,6 +312,10 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
racewalknode(&n->right, init, 0, 0); racewalknode(&n->right, init, 0, 0);
goto ret; goto ret;
case OITAB:
racewalknode(&n->left, init, 0, 0);
goto ret;
// should not appear in AST by now // should not appear in AST by now
case OSEND: case OSEND:
case ORECV: case ORECV:
@ -323,6 +327,7 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OPANIC: case OPANIC:
case ORECOVER: case ORECOVER:
case OCONVIFACE: case OCONVIFACE:
case OCMPIFACE:
case OMAKECHAN: case OMAKECHAN:
case OMAKEMAP: case OMAKEMAP:
case OMAKESLICE: case OMAKESLICE:
@ -338,6 +343,12 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
case OADDSTR: case OADDSTR:
case ODOTTYPE: case ODOTTYPE:
case ODOTTYPE2: case ODOTTYPE2:
case OCALLPART: // lowered to PTRLIT
case OCLOSURE: // lowered to PTRLIT
case ORANGE: // lowered to ordinary for loop
case OARRAYLIT: // lowered to assignments
case OMAPLIT:
case OSTRUCTLIT:
yyerror("racewalk: %O must be lowered by now", n->op); yyerror("racewalk: %O must be lowered by now", n->op);
goto ret; goto ret;
@ -364,30 +375,23 @@ racewalknode(Node **np, NodeList **init, int wr, int skip)
// does not require instrumentation // does not require instrumentation
case OPRINT: // don't bother instrumenting it case OPRINT: // don't bother instrumenting it
case OPRINTN: // don't bother instrumenting it case OPRINTN: // don't bother instrumenting it
case OCHECKNOTNIL: // always followed by a read.
case OPARAM: // it appears only in fn->exit to copy heap params back case OPARAM: // it appears only in fn->exit to copy heap params back
case OCLOSUREVAR:// immutable pointer to captured variable
case ODOTMETH: // either part of CALLMETH or CALLPART (lowered to PTRLIT)
goto ret; goto ret;
// unimplemented // unimplemented
case OSLICESTR: case OSLICESTR:
case OAPPEND: case OAPPEND:
case OCMPIFACE:
case OARRAYLIT:
case OMAPLIT:
case OSTRUCTLIT:
case OCLOSURE:
case ODCL: case ODCL:
case ODCLCONST: case ODCLCONST:
case ODCLTYPE: case ODCLTYPE:
case OLITERAL: case OLITERAL:
case ORANGE:
case OTYPE: case OTYPE:
case ONONAME: case ONONAME:
case OINDREG: case OINDREG:
case ODOTMETH:
case OITAB:
case OHMUL: case OHMUL:
case OCHECKNOTNIL:
case OCLOSUREVAR:
goto ret; goto ret;
} }

View File

@ -576,6 +576,30 @@ func TestRaceIfaceWW(t *testing.T) {
a = b a = b
} }
func TestRaceIfaceCmp(t *testing.T) {
var a, b Writer
a = DummyWriter{1}
ch := make(chan bool, 1)
go func() {
a = DummyWriter{1}
ch <- true
}()
_ = a == b
<-ch
}
func TestRaceIfaceCmpNil(t *testing.T) {
var a Writer
a = DummyWriter{1}
ch := make(chan bool, 1)
go func() {
a = DummyWriter{1}
ch <- true
}()
_ = a == nil
<-ch
}
func TestRaceEfaceConv(t *testing.T) { func TestRaceEfaceConv(t *testing.T) {
c := make(chan bool) c := make(chan bool)
v := 0 v := 0
@ -1151,6 +1175,15 @@ func (p InterImpl) Foo(x int) {
_, _, _ = x, y, z _, _, _ = x, y, z
} }
type InterImpl2 InterImpl
func (p *InterImpl2) Foo(x int) {
if p == nil {
InterImpl{}.Foo(x)
}
InterImpl(*p).Foo(x)
}
func TestRaceInterCall(t *testing.T) { func TestRaceInterCall(t *testing.T) {
c := make(chan bool, 1) c := make(chan bool, 1)
p := InterImpl{} p := InterImpl{}
@ -1212,6 +1245,54 @@ func TestRaceMethodCall2(t *testing.T) {
<-c <-c
} }
// Method value with concrete value receiver.
func TestRaceMethodValue(t *testing.T) {
c := make(chan bool, 1)
i := InterImpl{}
go func() {
i = InterImpl{}
c <- true
}()
_ = i.Foo
<-c
}
// Method value with interface receiver.
func TestRaceMethodValue2(t *testing.T) {
c := make(chan bool, 1)
var i Inter = InterImpl{}
go func() {
i = InterImpl{}
c <- true
}()
_ = i.Foo
<-c
}
// Method value with implicit dereference.
func TestRaceMethodValue3(t *testing.T) {
c := make(chan bool, 1)
i := &InterImpl{}
go func() {
*i = InterImpl{}
c <- true
}()
_ = i.Foo // dereferences i.
<-c
}
// Method value implicitly taking receiver address.
func TestNoRaceMethodValue(t *testing.T) {
c := make(chan bool, 1)
i := InterImpl2{}
go func() {
i = InterImpl2{}
c <- true
}()
_ = i.Foo // takes the address of i only.
<-c
}
func TestRacePanicArg(t *testing.T) { func TestRacePanicArg(t *testing.T) {
c := make(chan bool, 1) c := make(chan bool, 1)
err := errors.New("err") err := errors.New("err")
@ -1338,6 +1419,17 @@ func TestRaceSliceSlice2(t *testing.T) {
<-c <-c
} }
func TestRaceSliceString(t *testing.T) {
c := make(chan bool, 1)
x := "hello"
go func() {
x = "world"
c <- true
}()
_ = x[2:3]
<-c
}
// http://golang.org/issue/4453 // http://golang.org/issue/4453
func TestRaceFailingSliceStruct(t *testing.T) { func TestRaceFailingSliceStruct(t *testing.T) {
type X struct { type X struct {