Update module spf13/viper to v1.7.0 (#494)
Update module spf13/viper to v1.7.0 Reviewed-on: https://kolaente.dev/vikunja/api/pulls/494
This commit is contained in:
18
vendor/honnef.co/go/tools/ssa/builder.go
vendored
18
vendor/honnef.co/go/tools/ssa/builder.go
vendored
@ -32,7 +32,7 @@ package ssa
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
@ -58,12 +58,12 @@ var (
|
||||
tString = types.Typ[types.String]
|
||||
tUntypedNil = types.Typ[types.UntypedNil]
|
||||
tRangeIter = &opaqueType{nil, "iter"} // the type of all "range" iterators
|
||||
tEface = types.NewInterface(nil, nil).Complete()
|
||||
tEface = types.NewInterfaceType(nil, nil).Complete()
|
||||
|
||||
// SSA Value constants.
|
||||
vZero = intConst(0)
|
||||
vOne = intConst(1)
|
||||
vTrue = NewConst(exact.MakeBool(true), tBool)
|
||||
vTrue = NewConst(constant.MakeBool(true), tBool)
|
||||
)
|
||||
|
||||
// builder holds state associated with the package currently being built.
|
||||
@ -131,11 +131,11 @@ func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
|
||||
switch e.Op {
|
||||
case token.LAND:
|
||||
b.cond(fn, e.X, rhs, done)
|
||||
short = NewConst(exact.MakeBool(false), t)
|
||||
short = NewConst(constant.MakeBool(false), t)
|
||||
|
||||
case token.LOR:
|
||||
b.cond(fn, e.X, done, rhs)
|
||||
short = NewConst(exact.MakeBool(true), t)
|
||||
short = NewConst(constant.MakeBool(true), t)
|
||||
}
|
||||
|
||||
// Is rhs unreachable?
|
||||
@ -969,10 +969,10 @@ func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
|
||||
c.Args = b.emitCallArgs(fn, sig, e, c.Args)
|
||||
}
|
||||
|
||||
// assignOp emits to fn code to perform loc += incr or loc -= incr.
|
||||
func (b *builder) assignOp(fn *Function, loc lvalue, incr Value, op token.Token, pos token.Pos) {
|
||||
// assignOp emits to fn code to perform loc <op>= val.
|
||||
func (b *builder) assignOp(fn *Function, loc lvalue, val Value, op token.Token, pos token.Pos) {
|
||||
oldv := loc.load(fn)
|
||||
loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, incr, oldv.Type()), loc.typ(), pos))
|
||||
loc.store(fn, emitArith(fn, op, oldv, emitConv(fn, val, oldv.Type()), loc.typ(), pos))
|
||||
}
|
||||
|
||||
// localValueSpec emits to fn code to define all of the vars in the
|
||||
@ -1998,7 +1998,7 @@ start:
|
||||
op = token.SUB
|
||||
}
|
||||
loc := b.addr(fn, s.X, false)
|
||||
b.assignOp(fn, loc, NewConst(exact.MakeInt64(1), loc.typ()), op, s.Pos())
|
||||
b.assignOp(fn, loc, NewConst(constant.MakeInt64(1), loc.typ()), op, s.Pos())
|
||||
|
||||
case *ast.AssignStmt:
|
||||
switch s.Tok {
|
||||
|
44
vendor/honnef.co/go/tools/ssa/const.go
vendored
44
vendor/honnef.co/go/tools/ssa/const.go
vendored
@ -8,7 +8,7 @@ package ssa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strconv"
|
||||
@ -17,14 +17,14 @@ import (
|
||||
// NewConst returns a new constant of the specified value and type.
|
||||
// val must be valid according to the specification of Const.Value.
|
||||
//
|
||||
func NewConst(val exact.Value, typ types.Type) *Const {
|
||||
func NewConst(val constant.Value, typ types.Type) *Const {
|
||||
return &Const{typ, val}
|
||||
}
|
||||
|
||||
// intConst returns an 'int' constant that evaluates to i.
|
||||
// (i is an int64 in case the host is narrower than the target.)
|
||||
func intConst(i int64) *Const {
|
||||
return NewConst(exact.MakeInt64(i), tInt)
|
||||
return NewConst(constant.MakeInt64(i), tInt)
|
||||
}
|
||||
|
||||
// nilConst returns a nil constant of the specified type, which may
|
||||
@ -36,7 +36,7 @@ func nilConst(typ types.Type) *Const {
|
||||
|
||||
// stringConst returns a 'string' constant that evaluates to s.
|
||||
func stringConst(s string) *Const {
|
||||
return NewConst(exact.MakeString(s), tString)
|
||||
return NewConst(constant.MakeString(s), tString)
|
||||
}
|
||||
|
||||
// zeroConst returns a new "zero" constant of the specified type,
|
||||
@ -48,11 +48,11 @@ func zeroConst(t types.Type) *Const {
|
||||
case *types.Basic:
|
||||
switch {
|
||||
case t.Info()&types.IsBoolean != 0:
|
||||
return NewConst(exact.MakeBool(false), t)
|
||||
return NewConst(constant.MakeBool(false), t)
|
||||
case t.Info()&types.IsNumeric != 0:
|
||||
return NewConst(exact.MakeInt64(0), t)
|
||||
return NewConst(constant.MakeInt64(0), t)
|
||||
case t.Info()&types.IsString != 0:
|
||||
return NewConst(exact.MakeString(""), t)
|
||||
return NewConst(constant.MakeString(""), t)
|
||||
case t.Kind() == types.UnsafePointer:
|
||||
fallthrough
|
||||
case t.Kind() == types.UntypedNil:
|
||||
@ -74,8 +74,8 @@ func (c *Const) RelString(from *types.Package) string {
|
||||
var s string
|
||||
if c.Value == nil {
|
||||
s = "nil"
|
||||
} else if c.Value.Kind() == exact.String {
|
||||
s = exact.StringVal(c.Value)
|
||||
} else if c.Value.Kind() == constant.String {
|
||||
s = constant.StringVal(c.Value)
|
||||
const max = 20
|
||||
// TODO(adonovan): don't cut a rune in half.
|
||||
if len(s) > max {
|
||||
@ -121,14 +121,14 @@ func (c *Const) IsNil() bool {
|
||||
// a signed 64-bit integer.
|
||||
//
|
||||
func (c *Const) Int64() int64 {
|
||||
switch x := exact.ToInt(c.Value); x.Kind() {
|
||||
case exact.Int:
|
||||
if i, ok := exact.Int64Val(x); ok {
|
||||
switch x := constant.ToInt(c.Value); x.Kind() {
|
||||
case constant.Int:
|
||||
if i, ok := constant.Int64Val(x); ok {
|
||||
return i
|
||||
}
|
||||
return 0
|
||||
case exact.Float:
|
||||
f, _ := exact.Float64Val(x)
|
||||
case constant.Float:
|
||||
f, _ := constant.Float64Val(x)
|
||||
return int64(f)
|
||||
}
|
||||
panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
|
||||
@ -138,14 +138,14 @@ func (c *Const) Int64() int64 {
|
||||
// an unsigned 64-bit integer.
|
||||
//
|
||||
func (c *Const) Uint64() uint64 {
|
||||
switch x := exact.ToInt(c.Value); x.Kind() {
|
||||
case exact.Int:
|
||||
if u, ok := exact.Uint64Val(x); ok {
|
||||
switch x := constant.ToInt(c.Value); x.Kind() {
|
||||
case constant.Int:
|
||||
if u, ok := constant.Uint64Val(x); ok {
|
||||
return u
|
||||
}
|
||||
return 0
|
||||
case exact.Float:
|
||||
f, _ := exact.Float64Val(x)
|
||||
case constant.Float:
|
||||
f, _ := constant.Float64Val(x)
|
||||
return uint64(f)
|
||||
}
|
||||
panic(fmt.Sprintf("unexpected constant value: %T", c.Value))
|
||||
@ -155,7 +155,7 @@ func (c *Const) Uint64() uint64 {
|
||||
// a float64.
|
||||
//
|
||||
func (c *Const) Float64() float64 {
|
||||
f, _ := exact.Float64Val(c.Value)
|
||||
f, _ := constant.Float64Val(c.Value)
|
||||
return f
|
||||
}
|
||||
|
||||
@ -163,7 +163,7 @@ func (c *Const) Float64() float64 {
|
||||
// fit a complex128.
|
||||
//
|
||||
func (c *Const) Complex128() complex128 {
|
||||
re, _ := exact.Float64Val(exact.Real(c.Value))
|
||||
im, _ := exact.Float64Val(exact.Imag(c.Value))
|
||||
re, _ := constant.Float64Val(constant.Real(c.Value))
|
||||
im, _ := constant.Float64Val(constant.Imag(c.Value))
|
||||
return complex(re, im)
|
||||
}
|
||||
|
17
vendor/honnef.co/go/tools/ssa/create.go
vendored
17
vendor/honnef.co/go/tools/ssa/create.go
vendored
@ -251,12 +251,19 @@ func (prog *Program) AllPackages() []*Package {
|
||||
return pkgs
|
||||
}
|
||||
|
||||
// ImportedPackage returns the importable SSA Package whose import
|
||||
// path is path, or nil if no such SSA package has been created.
|
||||
// ImportedPackage returns the importable Package whose PkgPath
|
||||
// is path, or nil if no such Package has been created.
|
||||
//
|
||||
// Not all packages are importable. For example, no import
|
||||
// declaration can resolve to the x_test package created by 'go test'
|
||||
// or the ad-hoc main package created 'go build foo.go'.
|
||||
// A parameter to CreatePackage determines whether a package should be
|
||||
// considered importable. For example, no import declaration can resolve
|
||||
// to the ad-hoc main package created by 'go build foo.go'.
|
||||
//
|
||||
// TODO(adonovan): rethink this function and the "importable" concept;
|
||||
// most packages are importable. This function assumes that all
|
||||
// types.Package.Path values are unique within the ssa.Program, which is
|
||||
// false---yet this function remains very convenient.
|
||||
// Clients should use (*Program).Package instead where possible.
|
||||
// SSA doesn't really need a string-keyed map of packages.
|
||||
//
|
||||
func (prog *Program) ImportedPackage(path string) *Package {
|
||||
return prog.imported[path]
|
||||
|
12
vendor/honnef.co/go/tools/ssa/doc.go
vendored
12
vendor/honnef.co/go/tools/ssa/doc.go
vendored
@ -23,11 +23,13 @@
|
||||
// such as multi-way branch can be reconstructed as needed; see
|
||||
// ssautil.Switches() for an example.
|
||||
//
|
||||
// To construct an SSA-form program, call ssautil.CreateProgram on a
|
||||
// loader.Program, a set of type-checked packages created from
|
||||
// parsed Go source files. The resulting ssa.Program contains all the
|
||||
// packages and their members, but SSA code is not created for
|
||||
// function bodies until a subsequent call to (*Package).Build.
|
||||
// The simplest way to create the SSA representation of a package is
|
||||
// to load typed syntax trees using golang.org/x/tools/go/packages, then
|
||||
// invoke the ssautil.Packages helper function. See ExampleLoadPackages
|
||||
// and ExampleWholeProgram for examples.
|
||||
// The resulting ssa.Program contains all the packages and their
|
||||
// members, but SSA code is not created for function bodies until a
|
||||
// subsequent call to (*Package).Build or (*Program).Build.
|
||||
//
|
||||
// The builder initially builds a naive SSA form in which all local
|
||||
// variables are addresses of stack locations with explicit loads and
|
||||
|
6
vendor/honnef.co/go/tools/ssa/dom.go
vendored
6
vendor/honnef.co/go/tools/ssa/dom.go
vendored
@ -53,7 +53,7 @@ func (a byDomPreorder) Less(i, j int) bool { return a[i].dom.pre < a[j].dom.pre
|
||||
//
|
||||
func (f *Function) DomPreorder() []*BasicBlock {
|
||||
n := len(f.Blocks)
|
||||
order := make(byDomPreorder, n, n)
|
||||
order := make(byDomPreorder, n)
|
||||
copy(order, f.Blocks)
|
||||
sort.Sort(order)
|
||||
return order
|
||||
@ -123,7 +123,7 @@ func buildDomTree(f *Function) {
|
||||
n := len(f.Blocks)
|
||||
// Allocate space for 5 contiguous [n]*BasicBlock arrays:
|
||||
// sdom, parent, ancestor, preorder, buckets.
|
||||
space := make([]*BasicBlock, 5*n, 5*n)
|
||||
space := make([]*BasicBlock, 5*n)
|
||||
lt := ltState{
|
||||
sdom: space[0:n],
|
||||
parent: space[n : 2*n],
|
||||
@ -310,6 +310,7 @@ func sanityCheckDomTree(f *Function) {
|
||||
// Printing functions ----------------------------------------
|
||||
|
||||
// printDomTree prints the dominator tree as text, using indentation.
|
||||
//lint:ignore U1000 used during debugging
|
||||
func printDomTreeText(buf *bytes.Buffer, v *BasicBlock, indent int) {
|
||||
fmt.Fprintf(buf, "%*s%s\n", 4*indent, "", v)
|
||||
for _, child := range v.dom.children {
|
||||
@ -319,6 +320,7 @@ func printDomTreeText(buf *bytes.Buffer, v *BasicBlock, indent int) {
|
||||
|
||||
// printDomTreeDot prints the dominator tree of f in AT&T GraphViz
|
||||
// (.dot) format.
|
||||
//lint:ignore U1000 used during debugging
|
||||
func printDomTreeDot(buf *bytes.Buffer, f *Function) {
|
||||
fmt.Fprintln(buf, "//", f)
|
||||
fmt.Fprintln(buf, "digraph domtree {")
|
||||
|
1
vendor/honnef.co/go/tools/ssa/emit.go
vendored
1
vendor/honnef.co/go/tools/ssa/emit.go
vendored
@ -127,6 +127,7 @@ func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
|
||||
x = emitConv(f, x, y.Type())
|
||||
} else if _, ok := y.(*Const); ok {
|
||||
y = emitConv(f, y, x.Type())
|
||||
//lint:ignore SA9003 no-op
|
||||
} else {
|
||||
// other cases, e.g. channels. No-op.
|
||||
}
|
||||
|
64
vendor/honnef.co/go/tools/ssa/func.go
vendored
64
vendor/honnef.co/go/tools/ssa/func.go
vendored
@ -328,6 +328,70 @@ func (f *Function) finishBody() {
|
||||
}
|
||||
f.Locals = f.Locals[:j]
|
||||
|
||||
// comma-ok receiving from a time.Tick channel will never return
|
||||
// ok == false, so any branching on the value of ok can be
|
||||
// replaced with an unconditional jump. This will primarily match
|
||||
// `for range time.Tick(x)` loops, but it can also match
|
||||
// user-written code.
|
||||
for _, block := range f.Blocks {
|
||||
if len(block.Instrs) < 3 {
|
||||
continue
|
||||
}
|
||||
if len(block.Succs) != 2 {
|
||||
continue
|
||||
}
|
||||
var instrs []*Instruction
|
||||
for i, ins := range block.Instrs {
|
||||
if _, ok := ins.(*DebugRef); ok {
|
||||
continue
|
||||
}
|
||||
instrs = append(instrs, &block.Instrs[i])
|
||||
}
|
||||
|
||||
for i, ins := range instrs {
|
||||
unop, ok := (*ins).(*UnOp)
|
||||
if !ok || unop.Op != token.ARROW {
|
||||
continue
|
||||
}
|
||||
call, ok := unop.X.(*Call)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if call.Common().IsInvoke() {
|
||||
continue
|
||||
}
|
||||
|
||||
// OPT(dh): surely there is a more efficient way of doing
|
||||
// this, than using FullName. We should already have
|
||||
// resolved time.Tick somewhere?
|
||||
v, ok := call.Common().Value.(*Function)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
t, ok := v.Object().(*types.Func)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if t.FullName() != "time.Tick" {
|
||||
continue
|
||||
}
|
||||
ex, ok := (*instrs[i+1]).(*Extract)
|
||||
if !ok || ex.Tuple != unop || ex.Index != 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
ifstmt, ok := (*instrs[i+2]).(*If)
|
||||
if !ok || ifstmt.Cond != ex {
|
||||
continue
|
||||
}
|
||||
|
||||
*instrs[i+2] = NewJump(block)
|
||||
succ := block.Succs[1]
|
||||
block.Succs = block.Succs[0:1]
|
||||
succ.RemovePred(block)
|
||||
}
|
||||
}
|
||||
|
||||
optimizeBlocks(f)
|
||||
|
||||
buildReferrers(f)
|
||||
|
30
vendor/honnef.co/go/tools/ssa/lift.go
vendored
30
vendor/honnef.co/go/tools/ssa/lift.go
vendored
@ -341,10 +341,10 @@ func phiHasDirectReferrer(phi *Phi) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
type blockSet struct{ big.Int } // (inherit methods from Int)
|
||||
type BlockSet struct{ big.Int } // (inherit methods from Int)
|
||||
|
||||
// add adds b to the set and returns true if the set changed.
|
||||
func (s *blockSet) add(b *BasicBlock) bool {
|
||||
func (s *BlockSet) Add(b *BasicBlock) bool {
|
||||
i := b.Index
|
||||
if s.Bit(i) != 0 {
|
||||
return false
|
||||
@ -353,9 +353,13 @@ func (s *blockSet) add(b *BasicBlock) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *BlockSet) Has(b *BasicBlock) bool {
|
||||
return s.Bit(b.Index) == 1
|
||||
}
|
||||
|
||||
// take removes an arbitrary element from a set s and
|
||||
// returns its index, or returns -1 if empty.
|
||||
func (s *blockSet) take() int {
|
||||
func (s *BlockSet) Take() int {
|
||||
l := s.BitLen()
|
||||
for i := 0; i < l; i++ {
|
||||
if s.Bit(i) == 1 {
|
||||
@ -403,7 +407,7 @@ func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool
|
||||
|
||||
// Compute defblocks, the set of blocks containing a
|
||||
// definition of the alloc cell.
|
||||
var defblocks blockSet
|
||||
var defblocks BlockSet
|
||||
for _, instr := range *alloc.Referrers() {
|
||||
// Bail out if we discover the alloc is not liftable;
|
||||
// the only operations permitted to use the alloc are
|
||||
@ -416,7 +420,7 @@ func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool
|
||||
if instr.Addr != alloc {
|
||||
panic("Alloc.Referrers is inconsistent")
|
||||
}
|
||||
defblocks.add(instr.Block())
|
||||
defblocks.Add(instr.Block())
|
||||
case *UnOp:
|
||||
if instr.Op != token.MUL {
|
||||
return false // not a load
|
||||
@ -431,7 +435,7 @@ func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool
|
||||
}
|
||||
}
|
||||
// The Alloc itself counts as a (zero) definition of the cell.
|
||||
defblocks.add(alloc.Block())
|
||||
defblocks.Add(alloc.Block())
|
||||
|
||||
if debugLifting {
|
||||
fmt.Fprintln(os.Stderr, "\tlifting ", alloc, alloc.Name())
|
||||
@ -448,18 +452,18 @@ func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool
|
||||
//
|
||||
// TODO(adonovan): opt: recycle slice storage for W,
|
||||
// hasAlready, defBlocks across liftAlloc calls.
|
||||
var hasAlready blockSet
|
||||
var hasAlready BlockSet
|
||||
|
||||
// Initialize W and work to defblocks.
|
||||
var work blockSet = defblocks // blocks seen
|
||||
var W blockSet // blocks to do
|
||||
var work BlockSet = defblocks // blocks seen
|
||||
var W BlockSet // blocks to do
|
||||
W.Set(&defblocks.Int)
|
||||
|
||||
// Traverse iterated dominance frontier, inserting φ-nodes.
|
||||
for i := W.take(); i != -1; i = W.take() {
|
||||
for i := W.Take(); i != -1; i = W.Take() {
|
||||
u := fn.Blocks[i]
|
||||
for _, v := range df[u.Index] {
|
||||
if hasAlready.add(v) {
|
||||
if hasAlready.Add(v) {
|
||||
// Create φ-node.
|
||||
// It will be prepended to v.Instrs later, if needed.
|
||||
phi := &Phi{
|
||||
@ -478,8 +482,8 @@ func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool
|
||||
}
|
||||
newPhis[v] = append(newPhis[v], newPhi{phi, alloc})
|
||||
|
||||
if work.add(v) {
|
||||
W.add(v)
|
||||
if work.Add(v) {
|
||||
W.Add(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
vendor/honnef.co/go/tools/ssa/methods.go
vendored
4
vendor/honnef.co/go/tools/ssa/methods.go
vendored
@ -23,14 +23,14 @@ import (
|
||||
//
|
||||
func (prog *Program) MethodValue(sel *types.Selection) *Function {
|
||||
if sel.Kind() != types.MethodVal {
|
||||
panic(fmt.Sprintf("Method(%s) kind != MethodVal", sel))
|
||||
panic(fmt.Sprintf("MethodValue(%s) kind != MethodVal", sel))
|
||||
}
|
||||
T := sel.Recv()
|
||||
if isInterface(T) {
|
||||
return nil // abstract method
|
||||
}
|
||||
if prog.mode&LogSource != 0 {
|
||||
defer logStack("Method %s %v", T, sel)()
|
||||
defer logStack("MethodValue %s %v", T, sel)()
|
||||
}
|
||||
|
||||
prog.methodsMu.Lock()
|
||||
|
18
vendor/honnef.co/go/tools/ssa/sanity.go
vendored
18
vendor/honnef.co/go/tools/ssa/sanity.go
vendored
@ -410,8 +410,8 @@ func (s *sanity) checkFunction(fn *Function) bool {
|
||||
s.errorf("nil Prog")
|
||||
}
|
||||
|
||||
fn.String() // must not crash
|
||||
fn.RelString(fn.pkg()) // must not crash
|
||||
_ = fn.String() // must not crash
|
||||
_ = fn.RelString(fn.pkg()) // must not crash
|
||||
|
||||
// All functions have a package, except delegates (which are
|
||||
// shared across packages, or duplicated as weak symbols in a
|
||||
@ -448,6 +448,18 @@ func (s *sanity) checkFunction(fn *Function) bool {
|
||||
if p.Parent() != fn {
|
||||
s.errorf("Param %s at index %d has wrong parent", p.Name(), i)
|
||||
}
|
||||
// Check common suffix of Signature and Params match type.
|
||||
if sig := fn.Signature; sig != nil {
|
||||
j := i - len(fn.Params) + sig.Params().Len() // index within sig.Params
|
||||
if j < 0 {
|
||||
continue
|
||||
}
|
||||
if !types.Identical(p.Type(), sig.Params().At(j).Type()) {
|
||||
s.errorf("Param %s at index %d has wrong type (%s, versus %s in Signature)", p.Name(), i, p.Type(), sig.Params().At(j).Type())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
s.checkReferrerList(p)
|
||||
}
|
||||
for i, fv := range fn.FreeVars {
|
||||
@ -490,7 +502,7 @@ func sanityCheckPackage(pkg *Package) {
|
||||
if pkg.Pkg == nil {
|
||||
panic(fmt.Sprintf("Package %s has no Object", pkg))
|
||||
}
|
||||
pkg.String() // must not crash
|
||||
_ = pkg.String() // must not crash
|
||||
|
||||
for name, mem := range pkg.Members {
|
||||
if name != mem.Name() {
|
||||
|
2
vendor/honnef.co/go/tools/ssa/source.go
vendored
2
vendor/honnef.co/go/tools/ssa/source.go
vendored
@ -150,7 +150,7 @@ func findNamedFunc(pkg *Package, pos token.Pos) *Function {
|
||||
// (modulo "untyped" bools resulting from comparisons).
|
||||
//
|
||||
// (Tip: to find the ssa.Value given a source position, use
|
||||
// importer.PathEnclosingInterval to locate the ast.Node, then
|
||||
// astutil.PathEnclosingInterval to locate the ast.Node, then
|
||||
// EnclosingFunction to locate the Function, then ValueForExpr to find
|
||||
// the ssa.Value.)
|
||||
//
|
||||
|
16
vendor/honnef.co/go/tools/ssa/ssa.go
vendored
16
vendor/honnef.co/go/tools/ssa/ssa.go
vendored
@ -10,7 +10,7 @@ package ssa
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
exact "go/constant"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"sync"
|
||||
@ -405,7 +405,7 @@ type Parameter struct {
|
||||
// of the same type and value.
|
||||
//
|
||||
// Value holds the exact value of the constant, independent of its
|
||||
// Type(), using the same representation as package go/exact uses for
|
||||
// Type(), using the same representation as package go/constant uses for
|
||||
// constants, or nil for a typed nil value.
|
||||
//
|
||||
// Pos() returns token.NoPos.
|
||||
@ -417,7 +417,7 @@ type Parameter struct {
|
||||
//
|
||||
type Const struct {
|
||||
typ types.Type
|
||||
Value exact.Value
|
||||
Value constant.Value
|
||||
}
|
||||
|
||||
// A Global is a named Value holding the address of a package-level
|
||||
@ -572,8 +572,8 @@ type BinOp struct {
|
||||
register
|
||||
// One of:
|
||||
// ADD SUB MUL QUO REM + - * / %
|
||||
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &~
|
||||
// EQL LSS GTR NEQ LEQ GEQ == != < <= < >=
|
||||
// AND OR XOR SHL SHR AND_NOT & | ^ << >> &^
|
||||
// EQL NEQ LSS LEQ GTR GEQ == != < <= < >=
|
||||
Op token.Token
|
||||
X, Y Value
|
||||
}
|
||||
@ -680,10 +680,10 @@ type ChangeInterface struct {
|
||||
// value of a concrete type.
|
||||
//
|
||||
// Use Program.MethodSets.MethodSet(X.Type()) to find the method-set
|
||||
// of X, and Program.Method(m) to find the implementation of a method.
|
||||
// of X, and Program.MethodValue(m) to find the implementation of a method.
|
||||
//
|
||||
// To construct the zero value of an interface type T, use:
|
||||
// NewConst(exact.MakeNil(), T, pos)
|
||||
// NewConst(constant.MakeNil(), T, pos)
|
||||
//
|
||||
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
|
||||
// from an explicit conversion in the source.
|
||||
@ -813,7 +813,7 @@ type Slice struct {
|
||||
type FieldAddr struct {
|
||||
register
|
||||
X Value // *struct
|
||||
Field int // index into X.Type().Deref().(*types.Struct).Fields
|
||||
Field int // field is X.Type().Underlying().(*types.Pointer).Elem().Underlying().(*types.Struct).Field(Field)
|
||||
}
|
||||
|
||||
// The Field instruction yields the Field of struct X.
|
||||
|
143
vendor/honnef.co/go/tools/ssa/ssautil/load.go
vendored
143
vendor/honnef.co/go/tools/ssa/ssautil/load.go
vendored
@ -1,143 +0,0 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssautil
|
||||
|
||||
// This file defines utility functions for constructing programs in SSA form.
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
"golang.org/x/tools/go/packages"
|
||||
"honnef.co/go/tools/ssa"
|
||||
)
|
||||
|
||||
// Packages creates an SSA program for a set of packages loaded from
|
||||
// source syntax using the golang.org/x/tools/go/packages.Load function.
|
||||
// It creates and returns an SSA package for each well-typed package in
|
||||
// the initial list. The resulting list of packages has the same length
|
||||
// as initial, and contains a nil if SSA could not be constructed for
|
||||
// the corresponding initial package.
|
||||
//
|
||||
// Code for bodies of functions is not built until Build is called
|
||||
// on the resulting Program.
|
||||
//
|
||||
// The mode parameter controls diagnostics and checking during SSA construction.
|
||||
//
|
||||
func Packages(initial []*packages.Package, mode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {
|
||||
var fset *token.FileSet
|
||||
if len(initial) > 0 {
|
||||
fset = initial[0].Fset
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(fset, mode)
|
||||
seen := make(map[*packages.Package]*ssa.Package)
|
||||
var create func(p *packages.Package) *ssa.Package
|
||||
create = func(p *packages.Package) *ssa.Package {
|
||||
ssapkg, ok := seen[p]
|
||||
if !ok {
|
||||
if p.Types == nil || p.IllTyped {
|
||||
// not well typed
|
||||
seen[p] = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
ssapkg = prog.CreatePackage(p.Types, p.Syntax, p.TypesInfo, true)
|
||||
seen[p] = ssapkg
|
||||
|
||||
for _, imp := range p.Imports {
|
||||
create(imp)
|
||||
}
|
||||
}
|
||||
return ssapkg
|
||||
}
|
||||
|
||||
var ssapkgs []*ssa.Package
|
||||
for _, p := range initial {
|
||||
ssapkgs = append(ssapkgs, create(p))
|
||||
}
|
||||
return prog, ssapkgs
|
||||
}
|
||||
|
||||
// CreateProgram returns a new program in SSA form, given a program
|
||||
// loaded from source. An SSA package is created for each transitively
|
||||
// error-free package of lprog.
|
||||
//
|
||||
// Code for bodies of functions is not built until Build is called
|
||||
// on the result.
|
||||
//
|
||||
// mode controls diagnostics and checking during SSA construction.
|
||||
//
|
||||
func CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program {
|
||||
prog := ssa.NewProgram(lprog.Fset, mode)
|
||||
|
||||
for _, info := range lprog.AllPackages {
|
||||
if info.TransitivelyErrorFree {
|
||||
prog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable)
|
||||
}
|
||||
}
|
||||
|
||||
return prog
|
||||
}
|
||||
|
||||
// BuildPackage builds an SSA program with IR for a single package.
|
||||
//
|
||||
// It populates pkg by type-checking the specified file ASTs. All
|
||||
// dependencies are loaded using the importer specified by tc, which
|
||||
// typically loads compiler export data; SSA code cannot be built for
|
||||
// those packages. BuildPackage then constructs an ssa.Program with all
|
||||
// dependency packages created, and builds and returns the SSA package
|
||||
// corresponding to pkg.
|
||||
//
|
||||
// The caller must have set pkg.Path() to the import path.
|
||||
//
|
||||
// The operation fails if there were any type-checking or import errors.
|
||||
//
|
||||
// See ../ssa/example_test.go for an example.
|
||||
//
|
||||
func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {
|
||||
if fset == nil {
|
||||
panic("no token.FileSet")
|
||||
}
|
||||
if pkg.Path() == "" {
|
||||
panic("package has no import path")
|
||||
}
|
||||
|
||||
info := &types.Info{
|
||||
Types: make(map[ast.Expr]types.TypeAndValue),
|
||||
Defs: make(map[*ast.Ident]types.Object),
|
||||
Uses: make(map[*ast.Ident]types.Object),
|
||||
Implicits: make(map[ast.Node]types.Object),
|
||||
Scopes: make(map[ast.Node]*types.Scope),
|
||||
Selections: make(map[*ast.SelectorExpr]*types.Selection),
|
||||
}
|
||||
if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
prog := ssa.NewProgram(fset, mode)
|
||||
|
||||
// Create SSA packages for all imports.
|
||||
// Order is not significant.
|
||||
created := make(map[*types.Package]bool)
|
||||
var createAll func(pkgs []*types.Package)
|
||||
createAll = func(pkgs []*types.Package) {
|
||||
for _, p := range pkgs {
|
||||
if !created[p] {
|
||||
created[p] = true
|
||||
prog.CreatePackage(p, nil, nil, true)
|
||||
createAll(p.Imports())
|
||||
}
|
||||
}
|
||||
}
|
||||
createAll(pkg.Imports())
|
||||
|
||||
// Create and build the primary package.
|
||||
ssapkg := prog.CreatePackage(pkg, files, info, false)
|
||||
ssapkg.Build()
|
||||
return ssapkg, info, nil
|
||||
}
|
234
vendor/honnef.co/go/tools/ssa/ssautil/switch.go
vendored
234
vendor/honnef.co/go/tools/ssa/ssautil/switch.go
vendored
@ -1,234 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssautil
|
||||
|
||||
// This file implements discovery of switch and type-switch constructs
|
||||
// from low-level control flow.
|
||||
//
|
||||
// Many techniques exist for compiling a high-level switch with
|
||||
// constant cases to efficient machine code. The optimal choice will
|
||||
// depend on the data type, the specific case values, the code in the
|
||||
// body of each case, and the hardware.
|
||||
// Some examples:
|
||||
// - a lookup table (for a switch that maps constants to constants)
|
||||
// - a computed goto
|
||||
// - a binary tree
|
||||
// - a perfect hash
|
||||
// - a two-level switch (to partition constant strings by their first byte).
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
||||
"honnef.co/go/tools/ssa"
|
||||
)
|
||||
|
||||
// A ConstCase represents a single constant comparison.
|
||||
// It is part of a Switch.
|
||||
type ConstCase struct {
|
||||
Block *ssa.BasicBlock // block performing the comparison
|
||||
Body *ssa.BasicBlock // body of the case
|
||||
Value *ssa.Const // case comparand
|
||||
}
|
||||
|
||||
// A TypeCase represents a single type assertion.
|
||||
// It is part of a Switch.
|
||||
type TypeCase struct {
|
||||
Block *ssa.BasicBlock // block performing the type assert
|
||||
Body *ssa.BasicBlock // body of the case
|
||||
Type types.Type // case type
|
||||
Binding ssa.Value // value bound by this case
|
||||
}
|
||||
|
||||
// A Switch is a logical high-level control flow operation
|
||||
// (a multiway branch) discovered by analysis of a CFG containing
|
||||
// only if/else chains. It is not part of the ssa.Instruction set.
|
||||
//
|
||||
// One of ConstCases and TypeCases has length >= 2;
|
||||
// the other is nil.
|
||||
//
|
||||
// In a value switch, the list of cases may contain duplicate constants.
|
||||
// A type switch may contain duplicate types, or types assignable
|
||||
// to an interface type also in the list.
|
||||
// TODO(adonovan): eliminate such duplicates.
|
||||
//
|
||||
type Switch struct {
|
||||
Start *ssa.BasicBlock // block containing start of if/else chain
|
||||
X ssa.Value // the switch operand
|
||||
ConstCases []ConstCase // ordered list of constant comparisons
|
||||
TypeCases []TypeCase // ordered list of type assertions
|
||||
Default *ssa.BasicBlock // successor if all comparisons fail
|
||||
}
|
||||
|
||||
func (sw *Switch) String() string {
|
||||
// We represent each block by the String() of its
|
||||
// first Instruction, e.g. "print(42:int)".
|
||||
var buf bytes.Buffer
|
||||
if sw.ConstCases != nil {
|
||||
fmt.Fprintf(&buf, "switch %s {\n", sw.X.Name())
|
||||
for _, c := range sw.ConstCases {
|
||||
fmt.Fprintf(&buf, "case %s: %s\n", c.Value, c.Body.Instrs[0])
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "switch %s.(type) {\n", sw.X.Name())
|
||||
for _, c := range sw.TypeCases {
|
||||
fmt.Fprintf(&buf, "case %s %s: %s\n",
|
||||
c.Binding.Name(), c.Type, c.Body.Instrs[0])
|
||||
}
|
||||
}
|
||||
if sw.Default != nil {
|
||||
fmt.Fprintf(&buf, "default: %s\n", sw.Default.Instrs[0])
|
||||
}
|
||||
fmt.Fprintf(&buf, "}")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// Switches examines the control-flow graph of fn and returns the
|
||||
// set of inferred value and type switches. A value switch tests an
|
||||
// ssa.Value for equality against two or more compile-time constant
|
||||
// values. Switches involving link-time constants (addresses) are
|
||||
// ignored. A type switch type-asserts an ssa.Value against two or
|
||||
// more types.
|
||||
//
|
||||
// The switches are returned in dominance order.
|
||||
//
|
||||
// The resulting switches do not necessarily correspond to uses of the
|
||||
// 'switch' keyword in the source: for example, a single source-level
|
||||
// switch statement with non-constant cases may result in zero, one or
|
||||
// many Switches, one per plural sequence of constant cases.
|
||||
// Switches may even be inferred from if/else- or goto-based control flow.
|
||||
// (In general, the control flow constructs of the source program
|
||||
// cannot be faithfully reproduced from the SSA representation.)
|
||||
//
|
||||
func Switches(fn *ssa.Function) []Switch {
|
||||
// Traverse the CFG in dominance order, so we don't
|
||||
// enter an if/else-chain in the middle.
|
||||
var switches []Switch
|
||||
seen := make(map[*ssa.BasicBlock]bool) // TODO(adonovan): opt: use ssa.blockSet
|
||||
for _, b := range fn.DomPreorder() {
|
||||
if x, k := isComparisonBlock(b); x != nil {
|
||||
// Block b starts a switch.
|
||||
sw := Switch{Start: b, X: x}
|
||||
valueSwitch(&sw, k, seen)
|
||||
if len(sw.ConstCases) > 1 {
|
||||
switches = append(switches, sw)
|
||||
}
|
||||
}
|
||||
|
||||
if y, x, T := isTypeAssertBlock(b); y != nil {
|
||||
// Block b starts a type switch.
|
||||
sw := Switch{Start: b, X: x}
|
||||
typeSwitch(&sw, y, T, seen)
|
||||
if len(sw.TypeCases) > 1 {
|
||||
switches = append(switches, sw)
|
||||
}
|
||||
}
|
||||
}
|
||||
return switches
|
||||
}
|
||||
|
||||
func valueSwitch(sw *Switch, k *ssa.Const, seen map[*ssa.BasicBlock]bool) {
|
||||
b := sw.Start
|
||||
x := sw.X
|
||||
for x == sw.X {
|
||||
if seen[b] {
|
||||
break
|
||||
}
|
||||
seen[b] = true
|
||||
|
||||
sw.ConstCases = append(sw.ConstCases, ConstCase{
|
||||
Block: b,
|
||||
Body: b.Succs[0],
|
||||
Value: k,
|
||||
})
|
||||
b = b.Succs[1]
|
||||
if len(b.Instrs) > 2 {
|
||||
// Block b contains not just 'if x == k',
|
||||
// so it may have side effects that
|
||||
// make it unsafe to elide.
|
||||
break
|
||||
}
|
||||
if len(b.Preds) != 1 {
|
||||
// Block b has multiple predecessors,
|
||||
// so it cannot be treated as a case.
|
||||
break
|
||||
}
|
||||
x, k = isComparisonBlock(b)
|
||||
}
|
||||
sw.Default = b
|
||||
}
|
||||
|
||||
func typeSwitch(sw *Switch, y ssa.Value, T types.Type, seen map[*ssa.BasicBlock]bool) {
|
||||
b := sw.Start
|
||||
x := sw.X
|
||||
for x == sw.X {
|
||||
if seen[b] {
|
||||
break
|
||||
}
|
||||
seen[b] = true
|
||||
|
||||
sw.TypeCases = append(sw.TypeCases, TypeCase{
|
||||
Block: b,
|
||||
Body: b.Succs[0],
|
||||
Type: T,
|
||||
Binding: y,
|
||||
})
|
||||
b = b.Succs[1]
|
||||
if len(b.Instrs) > 4 {
|
||||
// Block b contains not just
|
||||
// {TypeAssert; Extract #0; Extract #1; If}
|
||||
// so it may have side effects that
|
||||
// make it unsafe to elide.
|
||||
break
|
||||
}
|
||||
if len(b.Preds) != 1 {
|
||||
// Block b has multiple predecessors,
|
||||
// so it cannot be treated as a case.
|
||||
break
|
||||
}
|
||||
y, x, T = isTypeAssertBlock(b)
|
||||
}
|
||||
sw.Default = b
|
||||
}
|
||||
|
||||
// isComparisonBlock returns the operands (v, k) if a block ends with
|
||||
// a comparison v==k, where k is a compile-time constant.
|
||||
//
|
||||
func isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {
|
||||
if n := len(b.Instrs); n >= 2 {
|
||||
if i, ok := b.Instrs[n-1].(*ssa.If); ok {
|
||||
if binop, ok := i.Cond.(*ssa.BinOp); ok && binop.Block() == b && binop.Op == token.EQL {
|
||||
if k, ok := binop.Y.(*ssa.Const); ok {
|
||||
return binop.X, k
|
||||
}
|
||||
if k, ok := binop.X.(*ssa.Const); ok {
|
||||
return binop.Y, k
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// isTypeAssertBlock returns the operands (y, x, T) if a block ends with
|
||||
// a type assertion "if y, ok := x.(T); ok {".
|
||||
//
|
||||
func isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {
|
||||
if n := len(b.Instrs); n >= 4 {
|
||||
if i, ok := b.Instrs[n-1].(*ssa.If); ok {
|
||||
if ext1, ok := i.Cond.(*ssa.Extract); ok && ext1.Block() == b && ext1.Index == 1 {
|
||||
if ta, ok := ext1.Tuple.(*ssa.TypeAssert); ok && ta.Block() == b {
|
||||
// hack: relies upon instruction ordering.
|
||||
if ext0, ok := b.Instrs[n-3].(*ssa.Extract); ok {
|
||||
return ext0, ta.X, ta.AssertedType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
79
vendor/honnef.co/go/tools/ssa/ssautil/visit.go
vendored
79
vendor/honnef.co/go/tools/ssa/ssautil/visit.go
vendored
@ -1,79 +0,0 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package ssautil // import "honnef.co/go/tools/ssa/ssautil"
|
||||
|
||||
import "honnef.co/go/tools/ssa"
|
||||
|
||||
// This file defines utilities for visiting the SSA representation of
|
||||
// a Program.
|
||||
//
|
||||
// TODO(adonovan): test coverage.
|
||||
|
||||
// AllFunctions finds and returns the set of functions potentially
|
||||
// needed by program prog, as determined by a simple linker-style
|
||||
// reachability algorithm starting from the members and method-sets of
|
||||
// each package. The result may include anonymous functions and
|
||||
// synthetic wrappers.
|
||||
//
|
||||
// Precondition: all packages are built.
|
||||
//
|
||||
func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
|
||||
visit := visitor{
|
||||
prog: prog,
|
||||
seen: make(map[*ssa.Function]bool),
|
||||
}
|
||||
visit.program()
|
||||
return visit.seen
|
||||
}
|
||||
|
||||
type visitor struct {
|
||||
prog *ssa.Program
|
||||
seen map[*ssa.Function]bool
|
||||
}
|
||||
|
||||
func (visit *visitor) program() {
|
||||
for _, pkg := range visit.prog.AllPackages() {
|
||||
for _, mem := range pkg.Members {
|
||||
if fn, ok := mem.(*ssa.Function); ok {
|
||||
visit.function(fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, T := range visit.prog.RuntimeTypes() {
|
||||
mset := visit.prog.MethodSets.MethodSet(T)
|
||||
for i, n := 0, mset.Len(); i < n; i++ {
|
||||
visit.function(visit.prog.MethodValue(mset.At(i)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (visit *visitor) function(fn *ssa.Function) {
|
||||
if !visit.seen[fn] {
|
||||
visit.seen[fn] = true
|
||||
var buf [10]*ssa.Value // avoid alloc in common case
|
||||
for _, b := range fn.Blocks {
|
||||
for _, instr := range b.Instrs {
|
||||
for _, op := range instr.Operands(buf[:0]) {
|
||||
if fn, ok := (*op).(*ssa.Function); ok {
|
||||
visit.function(fn)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MainPackages returns the subset of the specified packages
|
||||
// named "main" that define a main function.
|
||||
// The result may include synthetic "testmain" packages.
|
||||
func MainPackages(pkgs []*ssa.Package) []*ssa.Package {
|
||||
var mains []*ssa.Package
|
||||
for _, pkg := range pkgs {
|
||||
if pkg.Pkg.Name() == "main" && pkg.Func("main") != nil {
|
||||
mains = append(mains, pkg)
|
||||
}
|
||||
}
|
||||
return mains
|
||||
}
|
3
vendor/honnef.co/go/tools/ssa/staticcheck.conf
vendored
Normal file
3
vendor/honnef.co/go/tools/ssa/staticcheck.conf
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
# ssa/... is mostly imported from upstream and we don't want to
|
||||
# deviate from it too much, hence disabling SA1019
|
||||
checks = ["inherit", "-SA1019"]
|
8
vendor/honnef.co/go/tools/ssa/testmain.go
vendored
8
vendor/honnef.co/go/tools/ssa/testmain.go
vendored
@ -8,8 +8,8 @@ package ssa
|
||||
// tests of the supplied packages.
|
||||
// It is closely coupled to $GOROOT/src/cmd/go/test.go and $GOROOT/src/testing.
|
||||
//
|
||||
// TODO(adonovan): this file no longer needs to live in the ssa package.
|
||||
// Move it to ssautil.
|
||||
// TODO(adonovan): throws this all away now that x/tools/go/packages
|
||||
// provides access to the actual synthetic test main files.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -26,6 +26,8 @@ import (
|
||||
// FindTests returns the Test, Benchmark, and Example functions
|
||||
// (as defined by "go test") defined in the specified package,
|
||||
// and its TestMain function, if any.
|
||||
//
|
||||
// Deprecated: use x/tools/go/packages to access synthetic testmain packages.
|
||||
func FindTests(pkg *Package) (tests, benchmarks, examples []*Function, main *Function) {
|
||||
prog := pkg.Prog
|
||||
|
||||
@ -109,6 +111,8 @@ func isTest(name, prefix string) bool {
|
||||
//
|
||||
// Subsequent calls to prog.AllPackages include the new package.
|
||||
// The package pkg must belong to the program prog.
|
||||
//
|
||||
// Deprecated: use x/tools/go/packages to access synthetic testmain packages.
|
||||
func (prog *Program) CreateTestMainPackage(pkg *Package) *Package {
|
||||
if pkg.Prog != prog {
|
||||
log.Fatal("Package does not belong to Program")
|
||||
|
6
vendor/honnef.co/go/tools/ssa/wrappers.go
vendored
6
vendor/honnef.co/go/tools/ssa/wrappers.go
vendored
@ -141,13 +141,9 @@ func makeWrapper(prog *Program, sel *types.Selection) *Function {
|
||||
// start is the index of the first regular parameter to use.
|
||||
//
|
||||
func createParams(fn *Function, start int) {
|
||||
var last *Parameter
|
||||
tparams := fn.Signature.Params()
|
||||
for i, n := start, tparams.Len(); i < n; i++ {
|
||||
last = fn.addParamObj(tparams.At(i))
|
||||
}
|
||||
if fn.Signature.Variadic() {
|
||||
last.typ = types.NewSlice(last.typ)
|
||||
fn.addParamObj(tparams.At(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user