// marked go:uintptrescapes.
const uintptrEscapesTag = "uintptr-escapes"
-func esctag(fn *Node) {
- fn.Esc = EscFuncTagged
-
- narg := 0
- for _, fs := range types.RecvsParams {
- for _, f := range fs(fn.Type).Fields().Slice() {
- narg++
- f.Note = escparamtag(fn, narg, f)
- }
- }
-}
-
-func escparamtag(fn *Node, narg int, f *types.Field) string {
+func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
name := func() string {
if f.Sym != nil {
return f.Sym.Name
// External functions are assumed unsafe, unless
// //go:noescape is given before the declaration.
if fn.Noescape() {
+ if Debug['m'] != 0 && f.Sym != nil {
+ Warnl(fn.Pos, "%S %v does not escape", funcSym(fn), name())
+ }
return mktag(EscNone)
}
+
+ if Debug['m'] != 0 && f.Sym != nil {
+ Warnl(fn.Pos, "leaking param: %v", name())
+ }
return mktag(EscHeap)
}
}
n := asNode(f.Nname)
- return mktag(int(n.Esc))
+ loc := e.oldLoc(n)
+ esc := finalizeEsc(loc.paramEsc)
+
+ if Debug['m'] != 0 && !loc.escapes {
+ if esc == EscNone {
+ Warnl(n.Pos, "%S %S does not escape", funcSym(fn), n)
+ } else if esc == EscHeap {
+ Warnl(n.Pos, "leaking param: %S", n)
+ } else {
+ if esc&EscContentEscapes != 0 {
+ Warnl(n.Pos, "leaking param content: %S", n)
+ }
+ for i := 0; i < numEscReturns; i++ {
+ if x := getEscReturn(esc, i); x >= 0 {
+ res := n.Name.Curfn.Type.Results().Field(i).Sym
+ Warnl(n.Pos, "leaking param: %S to result %v level=%d", n, res, x)
+ }
+ }
+ }
+ }
+
+ return mktag(int(esc))
}
e.curfn = nil
e.walkAll()
- e.finish()
-
- // Record parameter tags for package export data.
- for _, fn := range fns {
- esctag(fn)
- }
+ e.finish(fns)
}
func (e *Escape) initFunc(fn *Node) {
}
}
-func (e *Escape) finish() {
+func (e *Escape) finish(fns []*Node) {
+ // Record parameter tags for package export data.
+ for _, fn := range fns {
+ fn.Esc = EscFuncTagged
+
+ narg := 0
+ for _, fs := range types.RecvsParams {
+ for _, f := range fs(fn.Type).Fields().Slice() {
+ narg++
+ f.Note = e.paramTag(fn, narg, f)
+ }
+ }
+ }
+
for _, loc := range e.allLocs {
n := loc.n
if n == nil {
}
n.Esc = EscHeap
addrescapes(n)
- } else if loc.isName(PPARAM) {
- n.Esc = finalizeEsc(loc.paramEsc)
-
- if Debug['m'] != 0 && types.Haspointers(n.Type) {
- if n.Esc == EscNone {
- Warnl(n.Pos, "%S %S does not escape", funcSym(loc.curfn), n)
- } else if n.Esc == EscHeap {
- Warnl(n.Pos, "leaking param: %S", n)
- } else {
- if n.Esc&EscContentEscapes != 0 {
- Warnl(n.Pos, "leaking param content: %S", n)
- }
- for i := 0; i < numEscReturns; i++ {
- if x := getEscReturn(n.Esc, i); x >= 0 {
- res := n.Name.Curfn.Type.Results().Field(i).Sym
- Warnl(n.Pos, "leaking param: %S to result %v level=%d", n, res, x)
- }
- }
- }
- }
} else {
+ if Debug['m'] != 0 && n.Op != ONAME && n.Op != OTYPESW && n.Op != ORANGE && n.Op != ODEFER {
+ Warnl(n.Pos, "%S %S does not escape", funcSym(loc.curfn), n)
+ }
n.Esc = EscNone
if loc.transient {
switch n.Op {
n.SetNoescape(true)
}
}
-
- if Debug['m'] != 0 && n.Op != ONAME && n.Op != OTYPESW && n.Op != ORANGE && n.Op != ODEFER {
- Warnl(n.Pos, "%S %S does not escape", funcSym(loc.curfn), n)
- }
}
}
}