some deletions
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / go / analysis / passes / cgocall / cgocall.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/go/analysis/passes/cgocall/cgocall.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/go/analysis/passes/cgocall/cgocall.go
deleted file mode 100644 (file)
index 5768d0b..0000000
+++ /dev/null
@@ -1,376 +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 cgocall defines an Analyzer that detects some violations of
-// the cgo pointer passing rules.
-package cgocall
-
-import (
-       "fmt"
-       "go/ast"
-       "go/format"
-       "go/parser"
-       "go/token"
-       "go/types"
-       "log"
-       "os"
-       "strconv"
-
-       "golang.org/x/tools/go/analysis"
-       "golang.org/x/tools/go/analysis/passes/internal/analysisutil"
-)
-
-const debug = false
-
-const Doc = `detect some violations of the cgo pointer passing rules
-
-Check for invalid cgo pointer passing.
-This looks for code that uses cgo to call C code passing values
-whose types are almost always invalid according to the cgo pointer
-sharing rules.
-Specifically, it warns about attempts to pass a Go chan, map, func,
-or slice to C, either directly, or via a pointer, array, or struct.`
-
-var Analyzer = &analysis.Analyzer{
-       Name:             "cgocall",
-       Doc:              Doc,
-       RunDespiteErrors: true,
-       Run:              run,
-}
-
-func run(pass *analysis.Pass) (interface{}, error) {
-       if !analysisutil.Imports(pass.Pkg, "runtime/cgo") {
-               return nil, nil // doesn't use cgo
-       }
-
-       cgofiles, info, err := typeCheckCgoSourceFiles(pass.Fset, pass.Pkg, pass.Files, pass.TypesInfo, pass.TypesSizes)
-       if err != nil {
-               return nil, err
-       }
-       for _, f := range cgofiles {
-               checkCgo(pass.Fset, f, info, pass.Reportf)
-       }
-       return nil, nil
-}
-
-func checkCgo(fset *token.FileSet, f *ast.File, info *types.Info, reportf func(token.Pos, string, ...interface{})) {
-       ast.Inspect(f, func(n ast.Node) bool {
-               call, ok := n.(*ast.CallExpr)
-               if !ok {
-                       return true
-               }
-
-               // Is this a C.f() call?
-               var name string
-               if sel, ok := analysisutil.Unparen(call.Fun).(*ast.SelectorExpr); ok {
-                       if id, ok := sel.X.(*ast.Ident); ok && id.Name == "C" {
-                               name = sel.Sel.Name
-                       }
-               }
-               if name == "" {
-                       return true // not a call we need to check
-               }
-
-               // A call to C.CBytes passes a pointer but is always safe.
-               if name == "CBytes" {
-                       return true
-               }
-
-               if debug {
-                       log.Printf("%s: call to C.%s", fset.Position(call.Lparen), name)
-               }
-
-               for _, arg := range call.Args {
-                       if !typeOKForCgoCall(cgoBaseType(info, arg), make(map[types.Type]bool)) {
-                               reportf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
-                               break
-                       }
-
-                       // Check for passing the address of a bad type.
-                       if conv, ok := arg.(*ast.CallExpr); ok && len(conv.Args) == 1 &&
-                               isUnsafePointer(info, conv.Fun) {
-                               arg = conv.Args[0]
-                       }
-                       if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
-                               if !typeOKForCgoCall(cgoBaseType(info, u.X), make(map[types.Type]bool)) {
-                                       reportf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
-                                       break
-                               }
-                       }
-               }
-               return true
-       })
-}
-
-// typeCheckCgoSourceFiles returns type-checked syntax trees for the raw
-// cgo files of a package (those that import "C"). Such files are not
-// Go, so there may be gaps in type information around C.f references.
-//
-// This checker was initially written in vet to inspect raw cgo source
-// files using partial type information. However, Analyzers in the new
-// analysis API are presented with the type-checked, "cooked" Go ASTs
-// resulting from cgo-processing files, so we must choose between
-// working with the cooked file generated by cgo (which was tried but
-// proved fragile) or locating the raw cgo file (e.g. from //line
-// directives) and working with that, as we now do.
-//
-// Specifically, we must type-check the raw cgo source files (or at
-// least the subtrees needed for this analyzer) in an environment that
-// simulates the rest of the already type-checked package.
-//
-// For example, for each raw cgo source file in the original package,
-// such as this one:
-//
-//     package p
-//     import "C"
-//     import "fmt"
-//     type T int
-//     const k = 3
-//     var x, y = fmt.Println()
-//     func f() { ... }
-//     func g() { ... C.malloc(k) ... }
-//     func (T) f(int) string { ... }
-//
-// we synthesize a new ast.File, shown below, that dot-imports the
-// original "cooked" package using a special name ("·this·"), so that all
-// references to package members resolve correctly. (References to
-// unexported names cause an "unexported" error, which we ignore.)
-//
-// To avoid shadowing names imported from the cooked package,
-// package-level declarations in the new source file are modified so
-// that they do not declare any names.
-// (The cgocall analysis is concerned with uses, not declarations.)
-// Specifically, type declarations are discarded;
-// all names in each var and const declaration are blanked out;
-// each method is turned into a regular function by turning
-// the receiver into the first parameter;
-// and all functions are renamed to "_".
-//
-//     package p
-//     import . "·this·" // declares T, k, x, y, f, g, T.f
-//     import "C"
-//     import "fmt"
-//     const _ = 3
-//     var _, _ = fmt.Println()
-//     func _() { ... }
-//     func _() { ... C.malloc(k) ... }
-//     func _(T, int) string { ... }
-//
-// In this way, the raw function bodies and const/var initializer
-// expressions are preserved but refer to the "cooked" objects imported
-// from "·this·", and none of the transformed package-level declarations
-// actually declares anything. In the example above, the reference to k
-// in the argument of the call to C.malloc resolves to "·this·".k, which
-// has an accurate type.
-//
-// This approach could in principle be generalized to more complex
-// analyses on raw cgo files. One could synthesize a "C" package so that
-// C.f would resolve to "·this·"._C_func_f, for example. But we have
-// limited ourselves here to preserving function bodies and initializer
-// expressions since that is all that the cgocall analyzer needs.
-//
-func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*ast.File, info *types.Info, sizes types.Sizes) ([]*ast.File, *types.Info, error) {
-       const thispkg = "·this·"
-
-       // Which files are cgo files?
-       var cgoFiles []*ast.File
-       importMap := map[string]*types.Package{thispkg: pkg}
-       for _, raw := range files {
-               // If f is a cgo-generated file, Position reports
-               // the original file, honoring //line directives.
-               filename := fset.Position(raw.Pos()).Filename
-               f, err := parser.ParseFile(fset, filename, nil, parser.Mode(0))
-               if err != nil {
-                       return nil, nil, fmt.Errorf("can't parse raw cgo file: %v", err)
-               }
-               found := false
-               for _, spec := range f.Imports {
-                       if spec.Path.Value == `"C"` {
-                               found = true
-                               break
-                       }
-               }
-               if !found {
-                       continue // not a cgo file
-               }
-
-               // Record the original import map.
-               for _, spec := range raw.Imports {
-                       path, _ := strconv.Unquote(spec.Path.Value)
-                       importMap[path] = imported(info, spec)
-               }
-
-               // Add special dot-import declaration:
-               //    import . "·this·"
-               var decls []ast.Decl
-               decls = append(decls, &ast.GenDecl{
-                       Tok: token.IMPORT,
-                       Specs: []ast.Spec{
-                               &ast.ImportSpec{
-                                       Name: &ast.Ident{Name: "."},
-                                       Path: &ast.BasicLit{
-                                               Kind:  token.STRING,
-                                               Value: strconv.Quote(thispkg),
-                                       },
-                               },
-                       },
-               })
-
-               // Transform declarations from the raw cgo file.
-               for _, decl := range f.Decls {
-                       switch decl := decl.(type) {
-                       case *ast.GenDecl:
-                               switch decl.Tok {
-                               case token.TYPE:
-                                       // Discard type declarations.
-                                       continue
-                               case token.IMPORT:
-                                       // Keep imports.
-                               case token.VAR, token.CONST:
-                                       // Blank the declared var/const names.
-                                       for _, spec := range decl.Specs {
-                                               spec := spec.(*ast.ValueSpec)
-                                               for i := range spec.Names {
-                                                       spec.Names[i].Name = "_"
-                                               }
-                                       }
-                               }
-                       case *ast.FuncDecl:
-                               // Blank the declared func name.
-                               decl.Name.Name = "_"
-
-                               // Turn a method receiver:  func (T) f(P) R {...}
-                               // into regular parameter:  func _(T, P) R {...}
-                               if decl.Recv != nil {
-                                       var params []*ast.Field
-                                       params = append(params, decl.Recv.List...)
-                                       params = append(params, decl.Type.Params.List...)
-                                       decl.Type.Params.List = params
-                                       decl.Recv = nil
-                               }
-                       }
-                       decls = append(decls, decl)
-               }
-               f.Decls = decls
-               if debug {
-                       format.Node(os.Stderr, fset, f) // debugging
-               }
-               cgoFiles = append(cgoFiles, f)
-       }
-       if cgoFiles == nil {
-               return nil, nil, nil // nothing to do (can't happen?)
-       }
-
-       // Type-check the synthetic files.
-       tc := &types.Config{
-               FakeImportC: true,
-               Importer: importerFunc(func(path string) (*types.Package, error) {
-                       return importMap[path], nil
-               }),
-               Sizes: sizes,
-               Error: func(error) {}, // ignore errors (e.g. unused import)
-       }
-
-       // It's tempting to record the new types in the
-       // existing pass.TypesInfo, but we don't own it.
-       altInfo := &types.Info{
-               Types: make(map[ast.Expr]types.TypeAndValue),
-       }
-       tc.Check(pkg.Path(), fset, cgoFiles, altInfo)
-
-       return cgoFiles, altInfo, nil
-}
-
-// cgoBaseType tries to look through type conversions involving
-// unsafe.Pointer to find the real type. It converts:
-//   unsafe.Pointer(x) => x
-//   *(*unsafe.Pointer)(unsafe.Pointer(&x)) => x
-func cgoBaseType(info *types.Info, arg ast.Expr) types.Type {
-       switch arg := arg.(type) {
-       case *ast.CallExpr:
-               if len(arg.Args) == 1 && isUnsafePointer(info, arg.Fun) {
-                       return cgoBaseType(info, arg.Args[0])
-               }
-       case *ast.StarExpr:
-               call, ok := arg.X.(*ast.CallExpr)
-               if !ok || len(call.Args) != 1 {
-                       break
-               }
-               // Here arg is *f(v).
-               t := info.Types[call.Fun].Type
-               if t == nil {
-                       break
-               }
-               ptr, ok := t.Underlying().(*types.Pointer)
-               if !ok {
-                       break
-               }
-               // Here arg is *(*p)(v)
-               elem, ok := ptr.Elem().Underlying().(*types.Basic)
-               if !ok || elem.Kind() != types.UnsafePointer {
-                       break
-               }
-               // Here arg is *(*unsafe.Pointer)(v)
-               call, ok = call.Args[0].(*ast.CallExpr)
-               if !ok || len(call.Args) != 1 {
-                       break
-               }
-               // Here arg is *(*unsafe.Pointer)(f(v))
-               if !isUnsafePointer(info, call.Fun) {
-                       break
-               }
-               // Here arg is *(*unsafe.Pointer)(unsafe.Pointer(v))
-               u, ok := call.Args[0].(*ast.UnaryExpr)
-               if !ok || u.Op != token.AND {
-                       break
-               }
-               // Here arg is *(*unsafe.Pointer)(unsafe.Pointer(&v))
-               return cgoBaseType(info, u.X)
-       }
-
-       return info.Types[arg].Type
-}
-
-// typeOKForCgoCall reports whether the type of arg is OK to pass to a
-// C function using cgo. This is not true for Go types with embedded
-// pointers. m is used to avoid infinite recursion on recursive types.
-func typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {
-       if t == nil || m[t] {
-               return true
-       }
-       m[t] = true
-       switch t := t.Underlying().(type) {
-       case *types.Chan, *types.Map, *types.Signature, *types.Slice:
-               return false
-       case *types.Pointer:
-               return typeOKForCgoCall(t.Elem(), m)
-       case *types.Array:
-               return typeOKForCgoCall(t.Elem(), m)
-       case *types.Struct:
-               for i := 0; i < t.NumFields(); i++ {
-                       if !typeOKForCgoCall(t.Field(i).Type(), m) {
-                               return false
-                       }
-               }
-       }
-       return true
-}
-
-func isUnsafePointer(info *types.Info, e ast.Expr) bool {
-       t := info.Types[e].Type
-       return t != nil && t.Underlying() == types.Typ[types.UnsafePointer]
-}
-
-type importerFunc func(path string) (*types.Package, error)
-
-func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
-
-// TODO(adonovan): make this a library function or method of Info.
-func imported(info *types.Info, spec *ast.ImportSpec) *types.Package {
-       obj, ok := info.Implicits[spec]
-       if !ok {
-               obj = info.Defs[spec.Name] // renaming import
-       }
-       return obj.(*types.PkgName).Imported()
-}