case OASOP:
case OAS:
case OAS2:
- case OAS2DOTTYPE:
case OAS2RECV:
case OAS2FUNC:
case OAS2MAPR:
racewalknode(&n->left, init, 0, 0);
goto ret;
- case OSWITCH:
- if(n->ntest->op == OTYPESW)
- // TODO(dvyukov): the expression can contain calls or reads.
- return;
- goto ret;
-
case ONOT:
case OMINUS:
case OPLUS:
racewalknode(&n->left, init, 0, 0);
goto ret;
+ case OTYPESW:
+ racewalknode(&n->right, init, 0, 0);
+ goto ret;
+
// should not appear in AST by now
case OSEND:
case ORECV:
case OMAKESLICE:
case OCALL:
case OCOPY:
+ case OAPPEND:
case ORUNESTR:
case OARRAYBYTESTR:
case OARRAYRUNESTR:
case OADDSTR:
case ODOTTYPE:
case ODOTTYPE2:
+ case OAS2DOTTYPE:
case OCALLPART: // lowered to PTRLIT
case OCLOSURE: // lowered to PTRLIT
case ORANGE: // lowered to ordinary for loop
case OIF:
case OCALLMETH:
case ORETURN:
+ case OSWITCH:
case OSELECT:
case OEMPTY:
case OBREAK:
case OLITERAL:
case OSLICESTR: // always preceded by bounds checking, avoid double instrumentation.
goto ret;
-
- // unimplemented
- case OAPPEND:
- goto ret;
}
ret:
if(isartificial(n))
return 0;
if(t->etype == TSTRUCT) {
+ // TODO: instrument arrays similarly.
// PARAMs w/o PHEAP are not interesting.
if(n->class == PPARAM || n->class == PPARAMOUT)
return 0;
// that has got a pointer inside. Whether it points to
// the heap or not is impossible to know at compile time
if((class&PHEAP) || class == PPARAMREF || class == PEXTERN
- || b->type->etype == TARRAY || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
+ || b->op == OINDEX || b->op == ODOTPTR || b->op == OIND || b->op == OXDOT) {
hascalls = 0;
foreach(n, hascallspred, &hascalls);
if(hascalls) {
return r;
}
+// basenod returns the simplest child node of n pointing to the same
+// memory area.
static Node*
basenod(Node *n)
{
n = n->left;
continue;
}
- if(n->op == OINDEX) {
+ if(n->op == OINDEX && isfixedarray(n->type)) {
n = n->left;
continue;
}
<-ch
}
+func TestRaceCaseType(t *testing.T) {
+ var x, y int
+ var i interface{} = x
+ c := make(chan int, 1)
+ go func() {
+ switch i.(type) {
+ case nil:
+ case int:
+ }
+ c <- 1
+ }()
+ i = y
+ <-c
+}
+
+func TestRaceCaseTypeBody(t *testing.T) {
+ var x, y int
+ var i interface{} = &x
+ c := make(chan int, 1)
+ go func() {
+ switch i := i.(type) {
+ case nil:
+ case *int:
+ *i = y
+ }
+ c <- 1
+ }()
+ x = y
+ <-c
+}
+
func TestNoRaceRange(t *testing.T) {
ch := make(chan int, 3)
a := [...]int{1, 2, 3}
<-c
}
+func TestRaceAppendSliceStruct(t *testing.T) {
+ type X struct {
+ x, y int
+ }
+ c := make(chan bool, 1)
+ x := make([]X, 10)
+ go func() {
+ y := make([]X, 0, 10)
+ y = append(y, x...)
+ c <- true
+ }()
+ x[1].y = 42
+ <-c
+}
+
func TestRaceStructInd(t *testing.T) {
c := make(chan bool, 1)
type Item struct {