@@ -130,6 +130,9 @@ func (p *Package) processCgo(filename string, f *ast.File, cflags []string) erro
130
130
// Declare functions found by libclang.
131
131
info .addFuncDecls ()
132
132
133
+ // Declare stub function pointer values found by libclang.
134
+ info .addFuncPtrDecls ()
135
+
133
136
// Declare globals found by libclang.
134
137
info .addVarDecls ()
135
138
@@ -199,6 +202,55 @@ func (info *fileInfo) addFuncDecls() {
199
202
}
200
203
}
201
204
205
+ // addFuncPtrDecls creates stub declarations of function pointer values. These
206
+ // values will later be replaced with the real values in the compiler.
207
+ // It adds code like the following to the AST:
208
+ //
209
+ // var (
210
+ // C.add unsafe.Pointer
211
+ // C.mul unsafe.Pointer
212
+ // // ...
213
+ // )
214
+ func (info * fileInfo ) addFuncPtrDecls () {
215
+ gen := & ast.GenDecl {
216
+ TokPos : info .importCPos ,
217
+ Tok : token .VAR ,
218
+ Lparen : info .importCPos ,
219
+ Rparen : info .importCPos ,
220
+ }
221
+ names := make ([]string , 0 , len (info .functions ))
222
+ for name := range info .functions {
223
+ names = append (names , name )
224
+ }
225
+ sort .Strings (names )
226
+ for _ , name := range names {
227
+ obj := & ast.Object {
228
+ Kind : ast .Typ ,
229
+ Name : "C." + name + "$funcaddr" ,
230
+ }
231
+ valueSpec := & ast.ValueSpec {
232
+ Names : []* ast.Ident {& ast.Ident {
233
+ NamePos : info .importCPos ,
234
+ Name : "C." + name + "$funcaddr" ,
235
+ Obj : obj ,
236
+ }},
237
+ Type : & ast.SelectorExpr {
238
+ X : & ast.Ident {
239
+ NamePos : info .importCPos ,
240
+ Name : "unsafe" ,
241
+ },
242
+ Sel : & ast.Ident {
243
+ NamePos : info .importCPos ,
244
+ Name : "Pointer" ,
245
+ },
246
+ },
247
+ }
248
+ obj .Decl = valueSpec
249
+ gen .Specs = append (gen .Specs , valueSpec )
250
+ }
251
+ info .Decls = append (info .Decls , gen )
252
+ }
253
+
202
254
// addVarDecls declares external C globals in the Go source.
203
255
// It adds code like the following to the AST:
204
256
//
@@ -327,15 +379,34 @@ func (info *fileInfo) addTypedefs() {
327
379
// separate namespace (no _Cgo_ hacks like in gc).
328
380
func (info * fileInfo ) walker (cursor * astutil.Cursor ) bool {
329
381
switch node := cursor .Node ().(type ) {
382
+ case * ast.CallExpr :
383
+ fun , ok := node .Fun .(* ast.SelectorExpr )
384
+ if ! ok {
385
+ return true
386
+ }
387
+ x , ok := fun .X .(* ast.Ident )
388
+ if ! ok {
389
+ return true
390
+ }
391
+ if _ , ok := info .functions [fun .Sel .Name ]; ok && x .Name == "C" {
392
+ node .Fun = & ast.Ident {
393
+ NamePos : x .NamePos ,
394
+ Name : "C." + fun .Sel .Name ,
395
+ }
396
+ }
330
397
case * ast.SelectorExpr :
331
398
x , ok := node .X .(* ast.Ident )
332
399
if ! ok {
333
400
return true
334
401
}
335
402
if x .Name == "C" {
403
+ name := "C." + node .Sel .Name
404
+ if _ , ok := info .functions [node .Sel .Name ]; ok {
405
+ name += "$funcaddr"
406
+ }
336
407
cursor .Replace (& ast.Ident {
337
408
NamePos : x .NamePos ,
338
- Name : "C." + node . Sel . Name ,
409
+ Name : name ,
339
410
})
340
411
}
341
412
}
0 commit comments