func checkPointsToExpectation(e *expectation, ptr pointer.Pointer, lineMapping map[string]string, prog *ssa.Program) bool { expected := make(map[string]int) surplus := make(map[string]int) exact := true for _, g := range e.args { if g == "..." { exact = false continue } expected[g]++ } // Find the set of labels that the probe's // argument (x in print(x)) may point to. for _, label := range ptr.PointsTo().Labels() { name := labelString(label, lineMapping, prog) if expected[name] > 0 { expected[name]-- } else if exact { surplus[name]++ } } // Report multiset difference: ok := true for _, count := range expected { if count > 0 { ok = false e.errorf("value does not alias these expected labels: %s", join(expected)) break } } for _, count := range surplus { if count > 0 { ok = false e.errorf("value may additionally alias these labels: %s", join(surplus)) break } } return ok }
func checkTypesExpectation(e *expectation, ptr pointer.Pointer, typ types.Type) bool { var expected typemap.M var surplus typemap.M exact := true for _, g := range e.types { if g == types.Typ[types.Invalid] { exact = false continue } expected.Set(g, struct{}{}) } if !pointer.CanHaveDynamicTypes(typ) { e.errorf("@types expectation requires an interface- or reflect.Value-typed operand, got %s", typ) return false } // Find the set of types that the probe's // argument (x in print(x)) may contain. for _, T := range ptr.PointsTo().DynamicTypes().Keys() { if expected.At(T) != nil { expected.Delete(T) } else if exact { surplus.Set(T, struct{}{}) } } // Report set difference: ok := true if expected.Len() > 0 { ok = false e.errorf("interface cannot contain these types: %s", expected.KeysString()) } if surplus.Len() > 0 { ok = false e.errorf("interface may additionally contain these types: %s", surplus.KeysString()) } return ok }