github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/src/cmd/fix/cftype.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "go/ast" 9 "go/token" 10 "reflect" 11 "strings" 12 ) 13 14 func init() { 15 register(cftypeFix) 16 } 17 18 var cftypeFix = fix{ 19 name: "cftype", 20 date: "2017-09-27", 21 f: cftypefix, 22 desc: `Fixes initializers of C.CF*Ptr types`, 23 disabled: false, 24 } 25 26 // Old state: 27 // type CFTypeRef unsafe.Pointer 28 // New state: 29 // type CFTypeRef uintptr 30 // and similar for other CF*Ref types. 31 // This fix finds nils initializing these types and replaces the nils with 0s. 32 func cftypefix(f *ast.File) bool { 33 return typefix(f, func(s string) bool { 34 return strings.HasPrefix(s, "C.CF") && strings.HasSuffix(s, "Ref") 35 }) 36 } 37 38 // typefix replaces nil with 0 for all nils whose type, when passed to badType, returns true. 39 func typefix(f *ast.File, badType func(string) bool) bool { 40 if !imports(f, "C") { 41 return false 42 } 43 typeof, _ := typecheck(&TypeConfig{}, f) 44 45 // step 1: Find all the nils with the offending types. 46 // Compute their replacement. 47 badNils := map[interface{}]ast.Expr{} 48 walk(f, func(n interface{}) { 49 if i, ok := n.(*ast.Ident); ok && i.Name == "nil" && badType(typeof[n]) { 50 badNils[n] = &ast.BasicLit{ValuePos: i.NamePos, Kind: token.INT, Value: "0"} 51 } 52 }) 53 if len(badNils) == 0 { 54 return false 55 } 56 57 // step 2: find all uses of the bad nils, replace them with 0. 58 // There's no easy way to map from an ast.Expr to all the places that use them, so 59 // we use reflect to find all such references. 60 exprType := reflect.TypeOf((*ast.Expr)(nil)).Elem() 61 exprSliceType := reflect.TypeOf(([]ast.Expr)(nil)) 62 walk(f, func(n interface{}) { 63 if n == nil { 64 return 65 } 66 v := reflect.ValueOf(n) 67 if v.Type().Kind() != reflect.Ptr { 68 return 69 } 70 if v.IsNil() { 71 return 72 } 73 v = v.Elem() 74 if v.Type().Kind() != reflect.Struct { 75 return 76 } 77 for i := 0; i < v.NumField(); i++ { 78 f := v.Field(i) 79 if f.Type() == exprType { 80 if r := badNils[f.Interface()]; r != nil { 81 f.Set(reflect.ValueOf(r)) 82 } 83 } 84 if f.Type() == exprSliceType { 85 for j := 0; j < f.Len(); j++ { 86 e := f.Index(j) 87 if r := badNils[e.Interface()]; r != nil { 88 e.Set(reflect.ValueOf(r)) 89 } 90 } 91 } 92 } 93 }) 94 95 return true 96 }