GoPLS Viewer

Home|gopls/go/pointer/example_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
5package pointer_test
6
7import (
8    "fmt"
9    "sort"
10
11    "golang.org/x/tools/go/callgraph"
12    "golang.org/x/tools/go/loader"
13    "golang.org/x/tools/go/pointer"
14    "golang.org/x/tools/go/ssa"
15    "golang.org/x/tools/go/ssa/ssautil"
16)
17
18// This program demonstrates how to use the pointer analysis to
19// obtain a conservative call-graph of a Go program.
20// It also shows how to compute the points-to set of a variable,
21// in this case, (C).f's ch parameter.
22func Example() {
23    const myprog = `
24package main
25
26import "fmt"
27
28type I interface {
29    f(map[string]int)
30}
31
32type C struct{}
33
34func (C) f(m map[string]int) {
35    fmt.Println("C.f()")
36}
37
38func main() {
39    var i I = C{}
40    x := map[string]int{"one":1}
41    i.f(x) // dynamic method call
42}
43`
44    var conf loader.Config
45
46    // Parse the input file, a string.
47    // (Command-line tools should use conf.FromArgs.)
48    fileerr := conf.ParseFile("myprog.go"myprog)
49    if err != nil {
50        fmt.Print(err// parse error
51        return
52    }
53
54    // Create single-file main package and import its dependencies.
55    conf.CreateFromFiles("main"file)
56
57    iprogerr := conf.Load()
58    if err != nil {
59        fmt.Print(err// type error in some package
60        return
61    }
62
63    // Create SSA-form program representation.
64    prog := ssautil.CreateProgram(iprogssa.InstantiateGenerics)
65    mainPkg := prog.Package(iprog.Created[0].Pkg)
66
67    // Build SSA code for bodies of all functions in the whole program.
68    prog.Build()
69
70    // Configure the pointer analysis to build a call-graph.
71    config := &pointer.Config{
72        Mains:          []*ssa.Package{mainPkg},
73        BuildCallGraphtrue,
74    }
75
76    // Query points-to set of (C).f's parameter m, a map.
77    C := mainPkg.Type("C").Type()
78    Cfm := prog.LookupMethod(CmainPkg.Pkg"f").Params[1]
79    config.AddQuery(Cfm)
80
81    // Run the pointer analysis.
82    resulterr := pointer.Analyze(config)
83    if err != nil {
84        panic(err// internal error in pointer analysis
85    }
86
87    // Find edges originating from the main package.
88    // By converting to strings, we de-duplicate nodes
89    // representing the same function due to context sensitivity.
90    var edges []string
91    callgraph.GraphVisitEdges(result.CallGraph, func(edge *callgraph.Edgeerror {
92        caller := edge.Caller.Func
93        if caller.Pkg == mainPkg {
94            edges = append(edgesfmt.Sprint(caller" --> "edge.Callee.Func))
95        }
96        return nil
97    })
98
99    // Print the edges in sorted order.
100    sort.Strings(edges)
101    for _edge := range edges {
102        fmt.Println(edge)
103    }
104    fmt.Println()
105
106    // Print the labels of (C).f(m)'s points-to set.
107    fmt.Println("m may point to:")
108    var labels []string
109    for _l := range result.Queries[Cfm].PointsTo().Labels() {
110        label := fmt.Sprintf("  %s: %s"prog.Fset.Position(l.Pos()), l)
111        labels = append(labelslabel)
112    }
113    sort.Strings(labels)
114    for _label := range labels {
115        fmt.Println(label)
116    }
117
118    // Output:
119    // (main.C).f --> fmt.Println
120    // main.init --> fmt.init
121    // main.main --> (main.C).f
122    //
123    // m may point to:
124    //   myprog.go:18:21: makemap
125}
126
MembersX
Example.iprog
Example.RangeStmt_2479.edge
Example.RangeStmt_2651.BlockStmt.label
Example.BlockStmt.caller
Example.labels
Example.RangeStmt_2837.label
loader
Example
Example.conf
Example.config
Example.result
pointer
ssautil
Example.prog
Example.C
Example.RangeStmt_2651.l
Example.myprog
Example.file
Example.err
Example.mainPkg
Example.edges
Members
X