racewalknode(&n->right, init, 0, 0);
goto ret;
+ case OITAB:
+ racewalknode(&n->left, init, 0, 0);
+ goto ret;
+
// should not appear in AST by now
case OSEND:
case ORECV:
case OPANIC:
case ORECOVER:
case OCONVIFACE:
+ case OCMPIFACE:
case OMAKECHAN:
case OMAKEMAP:
case OMAKESLICE:
case OADDSTR:
case ODOTTYPE:
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);
goto ret;
// does not require instrumentation
case OPRINT: // 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 OCLOSUREVAR:// immutable pointer to captured variable
+ case ODOTMETH: // either part of CALLMETH or CALLPART (lowered to PTRLIT)
goto ret;
// unimplemented
case OSLICESTR:
case OAPPEND:
- case OCMPIFACE:
- case OARRAYLIT:
- case OMAPLIT:
- case OSTRUCTLIT:
- case OCLOSURE:
case ODCL:
case ODCLCONST:
case ODCLTYPE:
case OLITERAL:
- case ORANGE:
case OTYPE:
case ONONAME:
case OINDREG:
- case ODOTMETH:
- case OITAB:
case OHMUL:
- case OCHECKNOTNIL:
- case OCLOSUREVAR:
goto ret;
}
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) {
c := make(chan bool)
v := 0
_, _, _ = 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) {
c := make(chan bool, 1)
p := InterImpl{}
<-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) {
c := make(chan bool, 1)
err := errors.New("err")
<-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
func TestRaceFailingSliceStruct(t *testing.T) {
type X struct {