type paramsAnalyzer … // getParams returns an *ir.Name slice containing all params for the // function (plus rcvr as well if applicable). func getParams(fn *ir.Func) []*ir.Name { … } // addParamsAnalyzer creates a new paramsAnalyzer helper object for // the function fn, appends it to the analyzers list, and returns the // new list. If the function in question doesn't have any interesting // parameters then the analyzer list is returned unchanged, and the // params flags in "fp" are updated accordingly. func addParamsAnalyzer(fn *ir.Func, analyzers []propAnalyzer, fp *FuncProps, nf *nameFinder) []propAnalyzer { … } // makeParamsAnalyzer creates a new helper object to analyze parameters // of function fn. If the function doesn't have any interesting // params, a nil helper is returned along with a set of default param // flags for the func. func makeParamsAnalyzer(fn *ir.Func, nf *nameFinder) (*paramsAnalyzer, []ParamPropBits) { … } func (pa *paramsAnalyzer) setResults(funcProps *FuncProps) { … } func (pa *paramsAnalyzer) findParamIdx(n *ir.Name) int { … } type testfType … // paramsAnalyzer invokes function 'testf' on the specified expression // 'x' for each parameter, and if the result is TRUE, or's 'flag' into // the flags for that param. func (pa *paramsAnalyzer) checkParams(x ir.Node, flag ParamPropBits, mayflag ParamPropBits, testf testfType) { … } // foldCheckParams checks expression 'x' (an 'if' condition or // 'switch' stmt expr) to see if the expr would fold away if a // specific parameter had a constant value. func (pa *paramsAnalyzer) foldCheckParams(x ir.Node) { … } // callCheckParams examines the target of call expression 'ce' to see // if it is making a call to the value passed in for some parameter. func (pa *paramsAnalyzer) callCheckParams(ce *ir.CallExpr) { … } // deriveFlagsFromCallee tries to derive flags for the current // function based on a call this function makes to some other // function. Example: // // /* Simple */ /* Derived from callee */ // func foo(f func(int)) { func foo(f func(int)) { // f(2) bar(32, f) // } } // func bar(x int, f func()) { // f(x) // } // // Here we can set the "param feeds indirect call" flag for // foo's param 'f' since we know that bar has that flag set for // its second param, and we're passing that param a function. func (pa *paramsAnalyzer) deriveFlagsFromCallee(ce *ir.CallExpr, callee *ir.Func) { … } func (pa *paramsAnalyzer) nodeVisitPost(n ir.Node) { … } func (pa *paramsAnalyzer) nodeVisitPre(n ir.Node) { … } type condLevelTracker … func (c *condLevelTracker) pre(n ir.Node) { … } func (c *condLevelTracker) post(n ir.Node) { … }