GoPLS Viewer

Home|gopls/go/pointer/pointer_test.go
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// No testdata on Android.
6
7//go:build !android
8// +build !android
9
10package pointer_test
11
12// This test uses 'expectation' comments embedded within testdata/*.go
13// files to specify the expected pointer analysis behaviour.
14// See below for grammar.
15
16import (
17    "bytes"
18    "errors"
19    "fmt"
20    "go/token"
21    "go/types"
22    "io/ioutil"
23    "os"
24    "path/filepath"
25    "regexp"
26    "strconv"
27    "strings"
28    "testing"
29    "unsafe"
30
31    "golang.org/x/tools/go/callgraph"
32    "golang.org/x/tools/go/packages"
33    "golang.org/x/tools/go/pointer"
34    "golang.org/x/tools/go/ssa"
35    "golang.org/x/tools/go/ssa/ssautil"
36    "golang.org/x/tools/go/types/typeutil"
37    "golang.org/x/tools/internal/typeparams"
38)
39
40var inputs = []string{
41    "testdata/a_test.go",
42    "testdata/another.go",
43    "testdata/arrayreflect.go",
44    "testdata/arrays.go",
45    "testdata/channels.go",
46    "testdata/chanreflect.go",
47    "testdata/context.go",
48    "testdata/conv.go",
49    "testdata/extended.go",
50    "testdata/finalizer.go",
51    "testdata/flow.go",
52    "testdata/fmtexcerpt.go",
53    "testdata/func.go",
54    "testdata/funcreflect.go",
55    "testdata/hello.go"// NB: causes spurious failure of HVN cross-check
56    "testdata/interfaces.go",
57    "testdata/issue9002.go",
58    "testdata/mapreflect.go",
59    "testdata/maps.go",
60    "testdata/panic.go",
61    "testdata/recur.go",
62    "testdata/reflect.go",
63    "testdata/rtti.go",
64    "testdata/structreflect.go",
65    "testdata/structs.go",
66    // "testdata/timer.go", // TODO(adonovan): fix broken assumptions about runtime timers
67}
68
69var raceEnabled = false
70
71// Expectation grammar:
72//
73// @calls f -> g
74//
75//    A 'calls' expectation asserts that edge (f, g) appears in the
76//    callgraph.  f and g are notated as per Function.String(), which
77//    may contain spaces (e.g. promoted method in anon struct).
78//
79// @pointsto a | b | c
80//
81//        A 'pointsto' expectation asserts that the points-to set of its
82//        operand contains exactly the set of labels {a,b,c} notated as per
83//        labelString.
84//
85//        A 'pointsto' expectation must appear on the same line as a
86//        print(x) statement; the expectation's operand is x.
87//
88//        If one of the strings is "...", the expectation asserts that the
89//        points-to set at least the other labels.
90//
91//        We use '|' because label names may contain spaces, e.g.  methods
92//        of anonymous structs.
93//
94//     Assertions within generic functions are treated as a union of all
95//     of the instantiations.
96//
97//        From a theoretical perspective, concrete types in interfaces are
98//        labels too, but they are represented differently and so have a
99//        different expectation, @types, below.
100//
101// @types t | u | v
102//
103//        A 'types' expectation asserts that the set of possible dynamic
104//        types of its interface operand is exactly {t,u,v}, notated per
105//        go/types.Type.String(). In other words, it asserts that the type
106//        component of the interface may point to that set of concrete type
107//        literals.  It also works for reflect.Value, though the types
108//        needn't be concrete in that case.
109//
110//        A 'types' expectation must appear on the same line as a
111//        print(x) statement; the expectation's operand is x.
112//
113//        If one of the strings is "...", the expectation asserts that the
114//        interface's type may point to at least the other types.
115//
116//        We use '|' because type names may contain spaces.
117//
118//     Assertions within generic functions are treated as a union of all
119//     of the instantiations.
120//
121// @warning "regexp"
122//
123//    A 'warning' expectation asserts that the analysis issues a
124//    warning that matches the regular expression within the string
125//    literal.
126//
127// @line id
128//
129//    A line directive associates the name "id" with the current
130//    file:line.  The string form of labels will use this id instead of
131//    a file:line, making @pointsto expectations more robust against
132//    perturbations in the source file.
133//    (NB, anon functions still include line numbers.)
134type expectation struct {
135    kind     string // "pointsto" | "pointstoquery" | "types" | "calls" | "warning"
136    filepath string
137    linenum  int // source line number, 1-based
138    args     []string
139    query    string             // extended query
140    extended []*pointer.Pointer // extended query pointer [per instantiation]
141    types    []types.Type       // for types
142}
143
144func (e *expectationString() string {
145    return fmt.Sprintf("@%s[%s]"e.kindstrings.Join(e.args" | "))
146}
147
148func (e *expectationerrorf(format stringargs ...interface{}) {
149    fmt.Printf("%s:%d: "e.filepathe.linenum)
150    fmt.Printf(formatargs...)
151    fmt.Println()
152}
153
154func (e *expectationneedsProbe() bool {
155    return e.kind == "pointsto" || e.kind == "pointstoquery" || e.kind == "types"
156}
157
158// Find probes (call to print(x)) of same source file/line as expectation.
159//
160// May match multiple calls for different instantiations.
161func findProbes(prog *ssa.Programprobes map[*ssa.CallCommon]boole *expectation) []*ssa.CallCommon {
162    var calls []*ssa.CallCommon
163    for call := range probes {
164        pos := prog.Fset.Position(call.Pos())
165        if pos.Line == e.linenum && pos.Filename == e.filepath {
166            // TODO(adonovan): send this to test log (display only on failure).
167            // fmt.Printf("%s:%d: info: found probe for %s: %s\n",
168            //     e.filepath, e.linenum, e, p.arg0) // debugging
169            calls = append(callscall)
170        }
171    }
172    return calls
173}
174
175// Find points to sets of probes (call to print(x)).
176func probesPointTo(calls []*ssa.CallCommonqueries map[ssa.Value]pointer.Pointer) []pointer.PointsToSet {
177    ptss := make([]pointer.PointsToSetlen(calls))
178    for icall := range calls {
179        ptss[i] = queries[call.Args[0]].PointsTo()
180    }
181    return ptss
182}
183
184// Find the types of the probes (call to print(x)).
185// Returns an error if type of the probe cannot point.
186func probesPointToTypes(calls []*ssa.CallCommon) ([]types.Typeerror) {
187    tProbes := make([]types.Typelen(calls))
188    for icall := range calls {
189        tProbes[i] = call.Args[0].Type()
190        if !pointer.CanPoint(tProbes[i]) {
191            return nilfmt.Errorf("expectation on non-pointerlike operand: %s"tProbes[i])
192        }
193    }
194    return tProbesnil
195}
196
197func doOneInput(t *testing.Tinputfpath stringbool {
198    cfg := &packages.Config{
199        Mode:  packages.LoadAllSyntax,
200        Teststrue,
201    }
202    pkgserr := packages.Load(cfgfpath)
203    if err != nil {
204        fmt.Println(err)
205        return false
206    }
207    if packages.PrintErrors(pkgs) > 0 {
208        fmt.Println("loaded packages have errors")
209        return false
210    }
211
212    // SSA creation + building.
213    mode := ssa.SanityCheckFunctions | ssa.InstantiateGenerics
214    progssaPkgs := ssautil.AllPackages(pkgsmode)
215    prog.Build()
216
217    // main underlying packages.Package.
218    mainPpkg := pkgs[0]
219    mainpkg := ssaPkgs[0]
220    ptrmain := mainpkg // main package for the pointer analysis
221    if mainpkg.Func("main") == nil {
222        // For test programs without main, such as testdata/a_test.go,
223        // the package with the original code is "main [main.test]" and
224        // the package with the main is "main.test".
225        for ipkg := range pkgs {
226            if pkg.ID == mainPpkg.ID+".test" {
227                ptrmain = ssaPkgs[i]
228            } else if pkg.ID == fmt.Sprintf("%s [%s.test]"mainPpkg.IDmainPpkg.ID) {
229                mainpkg = ssaPkgs[i]
230            }
231        }
232    }
233
234    // files in mainPpkg.
235    mainFiles := make(map[*token.File]bool)
236    for _syn := range mainPpkg.Syntax {
237        mainFiles[prog.Fset.File(syn.Pos())] = true
238    }
239
240    // Find all calls to the built-in print(x).  Analytically,
241    // print is a no-op, but it's a convenient hook for testing
242    // the PTS of an expression, so our tests use it.
243    // Exclude generic bodies as these should be dead code for pointer.
244    // Instance of generics are included.
245    probes := make(map[*ssa.CallCommon]bool)
246    for fn := range ssautil.AllFunctions(prog) {
247        if isGenericBody(fn) {
248            continue // skip generic bodies
249        }
250        // TODO(taking): Switch to a more principled check like fn.declaredPackage() == mainPkg if Origin is exported.
251        if fn.Pkg == mainpkg || (fn.Pkg == nil && mainFiles[prog.Fset.File(fn.Pos())]) {
252            for _b := range fn.Blocks {
253                for _instr := range b.Instrs {
254                    if instrok := instr.(ssa.CallInstruction); ok {
255                        call := instr.Common()
256                        if bok := call.Value.(*ssa.Builtin); ok && b.Name() == "print" && len(call.Args) == 1 {
257                            probes[instr.Common()] = true
258                        }
259                    }
260                }
261            }
262        }
263    }
264
265    ok := true
266
267    lineMapping := make(map[string]string// maps "file:line" to @line tag
268
269    // Parse expectations in this input.
270    var exps []*expectation
271    re := regexp.MustCompile("// *@([a-z]*) *(.*)$")
272    lines := strings.Split(input"\n")
273    for linenumline := range lines {
274        linenum++ // make it 1-based
275        if matches := re.FindAllStringSubmatch(line, -1); matches != nil {
276            match := matches[0]
277            kindrest := match[1], match[2]
278            e := &expectation{kindkindfilepathfpathlinenumlinenum}
279
280            if kind == "line" {
281                if rest == "" {
282                    ok = false
283                    e.errorf("@%s expectation requires identifier"kind)
284                } else {
285                    lineMapping[fmt.Sprintf("%s:%d"fpathlinenum)] = rest
286                }
287                continue
288            }
289
290            if e.needsProbe() && !strings.Contains(line"print(") {
291                ok = false
292                e.errorf("@%s expectation must follow call to print(x)"kind)
293                continue
294            }
295
296            switch kind {
297            case "pointsto":
298                e.args = split(rest"|")
299
300            case "pointstoquery":
301                args := strings.SplitN(rest" "2)
302                e.query = args[0]
303                e.args = split(args[1], "|")
304            case "types":
305                for _typstr := range split(rest"|") {
306                    var t types.Type = types.Typ[types.Invalid// means "..."
307                    if typstr != "..." {
308                        tverr := types.Eval(prog.Fsetmainpkg.PkgmainPpkg.Syntax[0].Pos(), typstr)
309                        if err != nil {
310                            ok = false
311                            // Don't print err since its location is bad.
312                            e.errorf("'%s' is not a valid type: %s"typstrerr)
313                            continue
314                        }
315                        t = tv.Type
316                    }
317                    e.types = append(e.typest)
318                }
319
320            case "calls":
321                e.args = split(rest"->")
322                // TODO(adonovan): eagerly reject the
323                // expectation if fn doesn't denote
324                // existing function, rather than fail
325                // the expectation after analysis.
326                if len(e.args) != 2 {
327                    ok = false
328                    e.errorf("@calls expectation wants 'caller -> callee' arguments")
329                    continue
330                }
331
332            case "warning":
333                literr := strconv.Unquote(strings.TrimSpace(rest))
334                if err != nil {
335                    ok = false
336                    e.errorf("couldn't parse @warning operand: %s"err.Error())
337                    continue
338                }
339                e.args = append(e.argslit)
340
341            default:
342                ok = false
343                e.errorf("unknown expectation kind: %s"e)
344                continue
345            }
346            exps = append(expse)
347        }
348    }
349
350    var log bytes.Buffer
351    fmt.Fprintf(&log"Input: %s\n"fpath)
352
353    // Run the analysis.
354    config := &pointer.Config{
355        Reflection:     true,
356        BuildCallGraphtrue,
357        Mains:          []*ssa.Package{ptrmain},
358        Log:            &log,
359    }
360    for probe := range probes {
361        v := probe.Args[0]
362        pos := prog.Fset.Position(probe.Pos())
363        for _e := range exps {
364            if e.linenum == pos.Line && e.filepath == pos.Filename && e.kind == "pointstoquery" {
365                extendederr := config.AddExtendedQuery(ve.query)
366                if err != nil {
367                    panic(err)
368                }
369                e.extended = append(e.extendedextended)
370            }
371        }
372        if pointer.CanPoint(v.Type()) {
373            config.AddQuery(v)
374        }
375    }
376
377    // Print the log is there was an error or a panic.
378    complete := false
379    defer func() {
380        if !complete || !ok {
381            log.WriteTo(os.Stderr)
382        }
383    }()
384
385    resulterr := pointer.Analyze(config)
386    if err != nil {
387        panic(err// internal error in pointer analysis
388    }
389
390    // Check the expectations.
391    for _e := range exps {
392        var tProbes []types.Type
393        var calls []*ssa.CallCommon
394        var ptss []pointer.PointsToSet
395        if e.needsProbe() {
396            calls = findProbes(progprobese)
397            if len(calls) == 0 {
398                ok = false
399                e.errorf("unreachable print() statement has expectation %s"e)
400                continue
401            }
402            if e.extended == nil {
403                ptss = probesPointTo(callsresult.Queries)
404            } else {
405                ptss = make([]pointer.PointsToSetlen(e.extended))
406                for ip := range e.extended {
407                    ptss[i] = p.PointsTo()
408                }
409            }
410
411            var err error
412            tProbeserr = probesPointToTypes(calls)
413            if err != nil {
414                ok = false
415                e.errorf(err.Error())
416                continue
417            }
418        }
419
420        switch e.kind {
421        case "pointsto""pointstoquery":
422            if !checkPointsToExpectation(eptsslineMappingprog) {
423                ok = false
424            }
425
426        case "types":
427            if !checkTypesExpectation(eptsstProbes) {
428                ok = false
429            }
430
431        case "calls":
432            if !checkCallsExpectation(progeresult.CallGraph) {
433                ok = false
434            }
435
436        case "warning":
437            if !checkWarningExpectation(progeresult.Warnings) {
438                ok = false
439            }
440        }
441    }
442
443    complete = true
444
445    // ok = false // debugging: uncomment to always see log
446
447    return ok
448}
449
450func labelString(l *pointer.LabellineMapping map[string]stringprog *ssa.Programstring {
451    // Functions and Globals need no pos suffix,
452    // nor do allocations in intrinsic operations
453    // (for which we'll print the function name).
454    switch l.Value().(type) {
455    case nil, *ssa.Function, *ssa.Global:
456        return l.String()
457    }
458
459    str := l.String()
460    if pos := l.Pos(); pos != token.NoPos {
461        // Append the position, using a @line tag instead of a line number, if defined.
462        posn := prog.Fset.Position(pos)
463        s := fmt.Sprintf("%s:%d"posn.Filenameposn.Line)
464        if tagok := lineMapping[s]; ok {
465            return fmt.Sprintf("%s@%s:%d"strtagposn.Column)
466        }
467        str = fmt.Sprintf("%s@%s"strposn)
468    }
469    return str
470}
471
472func checkPointsToExpectation(e *expectationptss []pointer.PointsToSetlineMapping map[string]stringprog *ssa.Programbool {
473    expected := make(map[string]int)
474    surplus := make(map[string]int)
475    exact := true
476    for _g := range e.args {
477        if g == "..." {
478            exact = false
479            continue
480        }
481        expected[g]++
482    }
483    // Find the set of labels that the probe's
484    // argument (x in print(x)) may point to.
485    for _pts := range ptss { // treat ptss as union of points-to sets.
486        for _label := range pts.Labels() {
487            name := labelString(labellineMappingprog)
488            if expected[name] > 0 {
489                expected[name]--
490            } else if exact {
491                surplus[name]++
492            }
493        }
494    }
495    // Report multiset difference:
496    ok := true
497    for _count := range expected {
498        if count > 0 {
499            ok = false
500            e.errorf("value does not alias these expected labels: %s"join(expected))
501            break
502        }
503    }
504    for _count := range surplus {
505        if count > 0 {
506            ok = false
507            e.errorf("value may additionally alias these labels: %s"join(surplus))
508            break
509        }
510    }
511    return ok
512}
513
514func checkTypesExpectation(e *expectationptss []pointer.PointsToSettyps []types.Typebool {
515    var expected typeutil.Map
516    var surplus typeutil.Map
517    exact := true
518    for _g := range e.types {
519        if g == types.Typ[types.Invalid] {
520            exact = false
521            continue
522        }
523        expected.Set(g, struct{}{})
524    }
525
526    if len(typs) != len(ptss) {
527        e.errorf("@types expectation internal error differing number of types(%d) and points to sets (%d)"len(typs), len(ptss))
528        return false
529    }
530
531    // Find the set of types that the probe's
532    // argument (x in print(x)) may contain.
533    for i := range ptss {
534        var Ts []types.Type
535        if pointer.CanHaveDynamicTypes(typs[i]) {
536            Ts = ptss[i].DynamicTypes().Keys()
537        } else {
538            Ts = append(Tstyps[i]) // static type
539        }
540        for _T := range Ts {
541            if expected.At(T) != nil {
542                expected.Delete(T)
543            } else if exact {
544                surplus.Set(T, struct{}{})
545            }
546        }
547    }
548    // Report set difference:
549    ok := true
550    if expected.Len() > 0 {
551        ok = false
552        e.errorf("interface cannot contain these types: %s"expected.KeysString())
553    }
554    if surplus.Len() > 0 {
555        ok = false
556        e.errorf("interface may additionally contain these types: %s"surplus.KeysString())
557    }
558    return ok
559}
560
561var errOK = errors.New("OK")
562
563func checkCallsExpectation(prog *ssa.Programe *expectationcg *callgraph.Graphbool {
564    found := make(map[string]int)
565    err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edgeerror {
566        // Name-based matching is inefficient but it allows us to
567        // match functions whose names that would not appear in an
568        // index ("<root>") or which are not unique ("func@1.2").
569        if edge.Caller.Func.String() == e.args[0] {
570            calleeStr := edge.Callee.Func.String()
571            if calleeStr == e.args[1] {
572                return errOK // expectation satisfied; stop the search
573            }
574            found[calleeStr]++
575        }
576        return nil
577    })
578    if err == errOK {
579        return true
580    }
581    if len(found) == 0 {
582        e.errorf("didn't find any calls from %s"e.args[0])
583    }
584    e.errorf("found no call from %s to %s, but only to %s",
585        e.args[0], e.args[1], join(found))
586    return false
587}
588
589func checkWarningExpectation(prog *ssa.Programe *expectationwarnings []pointer.Warningbool {
590    // TODO(adonovan): check the position part of the warning too?
591    reerr := regexp.Compile(e.args[0])
592    if err != nil {
593        e.errorf("invalid regular expression in @warning expectation: %s"err.Error())
594        return false
595    }
596
597    if len(warnings) == 0 {
598        e.errorf("@warning %q expectation, but no warnings"e.args[0])
599        return false
600    }
601
602    for _w := range warnings {
603        if re.MatchString(w.Message) {
604            return true
605        }
606    }
607
608    e.errorf("@warning %q expectation not satisfied; found these warnings though:"e.args[0])
609    for _w := range warnings {
610        fmt.Printf("%s: warning: %s\n"prog.Fset.Position(w.Pos), w.Message)
611    }
612    return false
613}
614
615func TestInput(t *testing.T) {
616    if testing.Short() {
617        t.Skip("skipping in short mode; this test requires tons of memory; https://golang.org/issue/14113")
618    }
619
620    wderr := os.Getwd()
621    if err != nil {
622        t.Errorf("os.Getwd: %s"err)
623        return
624    }
625
626    // 'go test' does a chdir so that relative paths in
627    // diagnostics no longer make sense relative to the invoking
628    // shell's cwd.  We print a special marker so that Emacs can
629    // make sense of them.
630    fmt.Fprintf(os.Stderr"Entering directory `%s'\n"wd)
631
632    for _filename := range inputs {
633        filename := filename
634        t.Run(filename, func(t *testing.T) {
635            if filename == "testdata/a_test.go" {
636                // For some reason this particular file is way more expensive than the others.
637                if unsafe.Sizeof(unsafe.Pointer(nil)) <= 4 {
638                    t.Skip("skipping memory-intensive test on platform with small address space; https://golang.org/issue/14113")
639                }
640                if raceEnabled {
641                    t.Skip("skipping memory-intensive test under race detector; https://golang.org/issue/14113")
642                }
643            } else {
644                t.Parallel()
645            }
646
647            contenterr := ioutil.ReadFile(filename)
648            if err != nil {
649                t.Fatalf("couldn't read file '%s': %s"filenameerr)
650            }
651
652            fpatherr := filepath.Abs(filename)
653            if err != nil {
654                t.Fatalf("couldn't get absolute path for '%s': %s"filenameerr)
655            }
656
657            if !doOneInput(tstring(content), fpath) {
658                t.Fail()
659            }
660        })
661    }
662}
663
664// isGenericBody returns true if fn is the body of a generic function.
665func isGenericBody(fn *ssa.Functionbool {
666    sig := fn.Signature
667    if typeparams.ForSignature(sig).Len() > 0 || typeparams.RecvTypeParams(sig).Len() > 0 {
668        return fn.Synthetic == ""
669    }
670    return false
671}
672
673// join joins the elements of multiset with " | "s.
674func join(set map[string]intstring {
675    var buf bytes.Buffer
676    sep := ""
677    for namecount := range set {
678        for i := 0i < counti++ {
679            buf.WriteString(sep)
680            sep = " | "
681            buf.WriteString(name)
682        }
683    }
684    return buf.String()
685}
686
687// split returns the list of sep-delimited non-empty strings in s.
688func split(ssep string) (r []string) {
689    for _elem := range strings.Split(ssep) {
690        elem = strings.TrimSpace(elem)
691        if elem != "" {
692            r = append(relem)
693        }
694    }
695    return
696}
697
698func TestTypeParam(t *testing.T) {
699    if !typeparams.Enabled {
700        t.Skip("TestTypeParamInput requires type parameters")
701    }
702    // Based on TestInput. Keep this up to date with that.
703    filename := "testdata/typeparams.go"
704
705    if testing.Short() {
706        t.Skip("skipping in short mode; this test requires tons of memory; https://golang.org/issue/14113")
707    }
708
709    wderr := os.Getwd()
710    if err != nil {
711        t.Fatalf("os.Getwd: %s"err)
712    }
713    fmt.Fprintf(os.Stderr"Entering directory `%s'\n"wd)
714
715    contenterr := ioutil.ReadFile(filename)
716    if err != nil {
717        t.Fatalf("couldn't read file '%s': %s"filenameerr)
718    }
719    fpatherr := filepath.Abs(filename)
720    if err != nil {
721        t.Errorf("couldn't get absolute path for '%s': %s"filenameerr)
722    }
723
724    if !doOneInput(tstring(content), fpath) {
725        t.Fail()
726    }
727}
728
MembersX
doOneInput.prog
labelString.BlockStmt.posn
join.RangeStmt_18888.BlockStmt.i
doOneInput.lines
checkTypesExpectation.typs
checkTypesExpectation.RangeStmt_14883.BlockStmt.RangeStmt_15069.T
TestInput.err
expectation.errorf
doOneInput.t
doOneInput.ptrmain
doOneInput.re
TestInput.RangeStmt_17599.BlockStmt.BlockStmt.err
labelString.lineMapping
labelString.prog
checkCallsExpectation.cg
checkWarningExpectation.err
TestTypeParam.err
checkWarningExpectation.RangeStmt_16796.w
TestInput.RangeStmt_17599.BlockStmt.BlockStmt.fpath
probesPointTo.calls
doOneInput.RangeStmt_7584.BlockStmt.BlockStmt.RangeStmt_7892.BlockStmt.RangeStmt_7926.instr
doOneInput.RangeStmt_8448.linenum
doOneInput.complete
split.s
split.RangeStmt_19154.elem
TestTypeParam.content
doOneInput.RangeStmt_11412.BlockStmt.ptss
doOneInput.RangeStmt_11412.BlockStmt.BlockStmt.err
TestInput
isGenericBody.fn
split
TestTypeParam.wd
expectation.query
findProbes
doOneInput.pkgs
checkCallsExpectation.BlockStmt.BlockStmt.calleeStr
doOneInput
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.e
TestTypeParam.fpath
doOneInput.RangeStmt_10700.BlockStmt.RangeStmt_10792.BlockStmt.BlockStmt.err
checkPointsToExpectation.expected
expectation.errorf.e
probesPointToTypes.RangeStmt_5844.i
doOneInput.RangeStmt_7173.syn
doOneInput.lineMapping
unsafe
probesPointToTypes
TestTypeParam
expectation.filepath
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.err
checkCallsExpectation
checkWarningExpectation.RangeStmt_16974.w
checkWarningExpectation.warnings
isGenericBody
join.buf
doOneInput.cfg
checkPointsToExpectation.e
checkTypesExpectation.ok
checkCallsExpectation.err
checkPointsToExpectation.surplus
checkWarningExpectation.e
doOneInput.log
checkTypesExpectation.RangeStmt_14883.i
regexp
expectation
findProbes.RangeStmt_4953.BlockStmt.pos
doOneInput.err
expectation.linenum
expectation.extended
probesPointTo.RangeStmt_5527.call
doOneInput.RangeStmt_7584.BlockStmt.BlockStmt.RangeStmt_7892.BlockStmt.RangeStmt_7926.BlockStmt.BlockStmt.call
doOneInput.RangeStmt_10700.BlockStmt.pos
raceEnabled
findProbes.probes
probesPointTo.queries
probesPointToTypes.RangeStmt_5844.call
strconv
packages
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.RangeStmt_9300.BlockStmt.BlockStmt.err
checkPointsToExpectation.ok
checkWarningExpectation.re
split.sep
expectation.needsProbe.e
findProbes.e
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.args
doOneInput.RangeStmt_10700.probe
probesPointTo
doOneInput.probes
doOneInput.RangeStmt_11412.e
checkPointsToExpectation.RangeStmt_14158.count
checkPointsToExpectation.RangeStmt_13999.count
checkTypesExpectation.RangeStmt_14493.g
expectation.errorf.format
doOneInput.RangeStmt_7584.fn
labelString.str
labelString.BlockStmt.s
labelString
checkTypesExpectation.exact
TestTypeParam.t
expectation.types
doOneInput.BlockStmt.RangeStmt_6901.pkg
doOneInput.ok
doOneInput.RangeStmt_11412.BlockStmt.BlockStmt.BlockStmt.RangeStmt_11859.i
TestInput.RangeStmt_17599.BlockStmt.filename
join.set
expectation.String.e
expectation.errorf.args
labelString.l
checkPointsToExpectation.RangeStmt_13696.pts
doOneInput.RangeStmt_10700.BlockStmt.RangeStmt_10792.BlockStmt.BlockStmt.extended
doOneInput.RangeStmt_11412.BlockStmt.BlockStmt.BlockStmt.RangeStmt_11859.p
checkPointsToExpectation.RangeStmt_13696.BlockStmt.RangeStmt_13767.label
expectation.String
probesPointTo.ptss
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.RangeStmt_9300.BlockStmt.t
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.RangeStmt_9300.BlockStmt.BlockStmt.tv
checkPointsToExpectation
join.sep
join.RangeStmt_18888.name
split.r
TestInput.RangeStmt_17599.BlockStmt.BlockStmt.content
probesPointTo.RangeStmt_5527.i
doOneInput.RangeStmt_8448.BlockStmt.matches
checkTypesExpectation.surplus
checkCallsExpectation.found
doOneInput.input
doOneInput.mainFiles
TestTypeParam.filename
checkTypesExpectation.ptss
checkCallsExpectation.prog
checkWarningExpectation
checkWarningExpectation.prog
doOneInput.exps
doOneInput.RangeStmt_11412.BlockStmt.tProbes
doOneInput.RangeStmt_11412.BlockStmt.calls
checkPointsToExpectation.ptss
probesPointToTypes.calls
doOneInput.ssaPkgs
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.lit
checkPointsToExpectation.prog
errors
expectation.needsProbe
findProbes.prog
findProbes.RangeStmt_4953.call
checkPointsToExpectation.RangeStmt_13696.BlockStmt.RangeStmt_13767.BlockStmt.name
TestInput.wd
TestInput.RangeStmt_17599.filename
expectation.kind
expectation.args
join
checkTypesExpectation.expected
checkTypesExpectation.RangeStmt_14883.BlockStmt.Ts
checkCallsExpectation.e
isGenericBody.sig
doOneInput.fpath
doOneInput.BlockStmt.RangeStmt_6901.i
doOneInput.RangeStmt_7584.BlockStmt.BlockStmt.RangeStmt_7892.b
doOneInput.RangeStmt_10700.BlockStmt.RangeStmt_10792.e
join.RangeStmt_18888.count
labelString.pos
checkPointsToExpectation.lineMapping
checkTypesExpectation.e
TestInput.t
probesPointToTypes.tProbes
doOneInput.RangeStmt_8448.BlockStmt.BlockStmt.BlockStmt.RangeStmt_9300.typstr
doOneInput.config
doOneInput.result
checkTypesExpectation
findProbes.calls
doOneInput.RangeStmt_8448.line
checkPointsToExpectation.exact
checkPointsToExpectation.RangeStmt_13511.g
Members
X