diff options
Diffstat (limited to 'go/pointer/analysis.go')
-rw-r--r-- | go/pointer/analysis.go | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/go/pointer/analysis.go b/go/pointer/analysis.go index 0abb04dd8..e3c85ede4 100644 --- a/go/pointer/analysis.go +++ b/go/pointer/analysis.go @@ -16,6 +16,7 @@ import ( "runtime" "runtime/debug" "sort" + "strings" "golang.org/x/tools/go/callgraph" "golang.org/x/tools/go/ssa" @@ -46,7 +47,6 @@ const ( // // (Note: most variables called 'obj' are not *objects but nodeids // such that a.nodes[obj].obj != nil.) -// type object struct { // flags is a bitset of the node type (ot*) flags defined above. flags uint32 @@ -59,8 +59,8 @@ type object struct { // // ssa.Value for an object allocated by an SSA operation. // types.Type for an rtype instance object or *rtype-tagged object. - // string for an instrinsic object, e.g. the array behind os.Args. - // nil for an object allocated by an instrinsic. + // string for an intrinsic object, e.g. the array behind os.Args. + // nil for an object allocated by an intrinsic. // (cgn provides the identity of the intrinsic.) data interface{} @@ -82,7 +82,6 @@ type nodeid uint32 // // Nodes that are pointed-to locations ("labels") have an enclosing // object (see analysis.enclosingObject). -// type node struct { // If non-nil, this node is the start of an object // (addressable memory location). @@ -215,7 +214,6 @@ func (a *analysis) computeTrackBits() { // // Pointer analysis of a transitively closed well-typed program should // always succeed. An error can occur only due to an internal bug. -// func Analyze(config *Config) (result *Result, err error) { if config.Mains == nil { return nil, fmt.Errorf("no main/test packages to analyze (check $GOROOT/$GOPATH)") @@ -361,7 +359,6 @@ func Analyze(config *Config) (result *Result, err error) { // callEdge is called for each edge in the callgraph. // calleeid is the callee's object node (has otFunction flag). -// func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) { obj := a.nodes[calleeid].obj if obj.flags&otFunction == 0 { @@ -381,12 +378,27 @@ func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) { fmt.Fprintf(a.log, "\tcall edge %s -> %s\n", site, callee) } - // Warn about calls to non-intrinsic external functions. + // Warn about calls to functions that are handled unsoundly. // TODO(adonovan): de-dup these messages. - if fn := callee.fn; fn.Blocks == nil && a.findIntrinsic(fn) == nil { + fn := callee.fn + + // Warn about calls to non-intrinsic external functions. + if fn.Blocks == nil && a.findIntrinsic(fn) == nil { a.warnf(site.pos(), "unsound call to unknown intrinsic: %s", fn) a.warnf(fn.Pos(), " (declared here)") } + + // Warn about calls to generic function bodies. + if fn.TypeParams().Len() > 0 && len(fn.TypeArgs()) == 0 { + a.warnf(site.pos(), "unsound call to generic function body: %s (build with ssa.InstantiateGenerics)", fn) + a.warnf(fn.Pos(), " (declared here)") + } + + // Warn about calls to instantiation wrappers of generics functions. + if fn.Origin() != nil && strings.HasPrefix(fn.Synthetic, "instantiation wrapper ") { + a.warnf(site.pos(), "unsound call to instantiation wrapper of generic: %s (build with ssa.InstantiateGenerics)", fn) + a.warnf(fn.Pos(), " (declared here)") + } } // dumpSolution writes the PTS solution to the specified file. @@ -394,7 +406,6 @@ func (a *analysis) callEdge(caller *cgnode, site *callsite, calleeid nodeid) { // It only dumps the nodes that existed before solving. The order in // which solver-created nodes are created depends on pre-solver // optimization, so we can't include them in the cross-check. -// func (a *analysis) dumpSolution(filename string, N int) { f, err := os.Create(filename) if err != nil { @@ -422,7 +433,6 @@ func (a *analysis) dumpSolution(filename string, N int) { // showCounts logs the size of the constraint system. A typical // optimized distribution is 65% copy, 13% load, 11% addr, 5% // offsetAddr, 4% store, 2% others. -// func (a *analysis) showCounts() { if a.log != nil { counts := make(map[reflect.Type]int) |