Source file
src/cmd/fix/cftype.go
1
2
3
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 and casts of C.*Ref and JNI types`,
23 disabled: false,
24 }
25
26
27
28
29
30
31
32 func cftypefix(f *ast.File) bool {
33 return typefix(f, func(s string) bool {
34 return strings.HasPrefix(s, "C.") && strings.HasSuffix(s, "Ref") && s != "C.CFAllocatorRef"
35 })
36 }
37
38
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 changed := false
45
46
47
48 badNils := map[any]ast.Expr{}
49 walk(f, func(n any) {
50 if i, ok := n.(*ast.Ident); ok && i.Name == "nil" && badType(typeof[n]) {
51 badNils[n] = &ast.BasicLit{ValuePos: i.NamePos, Kind: token.INT, Value: "0"}
52 }
53 })
54
55
56
57
58 if len(badNils) > 0 {
59 exprType := reflect.TypeOf((*ast.Expr)(nil)).Elem()
60 exprSliceType := reflect.TypeOf(([]ast.Expr)(nil))
61 walk(f, func(n any) {
62 if n == nil {
63 return
64 }
65 v := reflect.ValueOf(n)
66 if v.Type().Kind() != reflect.Pointer {
67 return
68 }
69 if v.IsNil() {
70 return
71 }
72 v = v.Elem()
73 if v.Type().Kind() != reflect.Struct {
74 return
75 }
76 for i := 0; i < v.NumField(); i++ {
77 f := v.Field(i)
78 if f.Type() == exprType {
79 if r := badNils[f.Interface()]; r != nil {
80 f.Set(reflect.ValueOf(r))
81 changed = true
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 changed = true
90 }
91 }
92 }
93 }
94 })
95 }
96
97
98
99
100
101
102 walk(f, func(n any) {
103 if n == nil {
104 return
105 }
106
107 c, ok := n.(*ast.CallExpr)
108 if !ok {
109 return
110 }
111 if len(c.Args) != 1 {
112 return
113 }
114 p, ok := c.Fun.(*ast.ParenExpr)
115 if !ok {
116 return
117 }
118 s, ok := p.X.(*ast.StarExpr)
119 if !ok {
120 return
121 }
122 t, ok := s.X.(*ast.SelectorExpr)
123 if !ok {
124 return
125 }
126 pkg, ok := t.X.(*ast.Ident)
127 if !ok {
128 return
129 }
130 dst := pkg.Name + "." + t.Sel.Name
131 src := typeof[c.Args[0]]
132 if badType(dst) && src == "*unsafe.Pointer" ||
133 dst == "unsafe.Pointer" && strings.HasPrefix(src, "*") && badType(src[1:]) {
134 c.Args[0] = &ast.CallExpr{
135 Fun: &ast.SelectorExpr{X: &ast.Ident{Name: "unsafe"}, Sel: &ast.Ident{Name: "Pointer"}},
136 Args: []ast.Expr{c.Args[0]},
137 }
138 changed = true
139 }
140 })
141
142 return changed
143 }
144
View as plain text