// genAppend generates constraints for a call to append. func (a *analysis) genAppend(instr *ssa.Call, cgn *cgnode) { // Consider z = append(x, y). y is optional. // This may allocate a new [1]T array; call its object w. // We get the following constraints: // z = x // z = &w // *z = *y x := instr.Call.Args[0] z := instr a.copy(a.valueNode(z), a.valueNode(x), 1) // z = x if len(instr.Call.Args) == 1 { return // no allocation for z = append(x) or _ = append(x). } // TODO(adonovan): test append([]byte, ...string) []byte. y := instr.Call.Args[1] tArray := sliceToArray(instr.Call.Args[0].Type()) var w nodeid w = a.nextNode() a.addNodes(tArray, "append") a.endObject(w, cgn, instr) a.copyElems(cgn, tArray.Elem(), z, y) // *z = *y a.addressOf(instr.Type(), a.valueNode(z), w) // z = &w }
func (ctxt *context) callees(inst *ssa.Call) ([]*ssa.Function, error) { pos := ctxt.lprog.Fset.Position(inst.Pos()) if pos.Line <= 0 { return nil, fmt.Errorf("no position") } qpos, err := oracle.ParseQueryPos(ctxt.lprog, posStr(pos), true) if err != nil { return nil, fmt.Errorf("cannot parse query pos %q: %v", posStr(pos), err) } result, err := ctxt.oracle.Query("callees", qpos) if err != nil { return nil, fmt.Errorf("query error: %v", err) } return calleeFuncs(result), nil }