@@ -39,12 +39,15 @@ type cgoPackage struct {
39
39
cflags []string // CFlags from #cgo lines
40
40
ldflags []string // LDFlags from #cgo lines
41
41
visitedFiles map [string ][]byte
42
+ cgoHeaders []string
42
43
}
43
44
44
45
// cgoFile holds information only for a single Go file (with one or more
45
46
// `import "C"` statements).
46
47
type cgoFile struct {
47
48
* cgoPackage
49
+ file * ast.File
50
+ index int
48
51
defined map [string ]ast.Node
49
52
names map [string ]clangCursor
50
53
}
@@ -210,13 +213,13 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
210
213
}
211
214
}
212
215
// Patch some types, for example *C.char in C.CString.
213
- cf := p .newCGoFile ()
216
+ cf := p .newCGoFile (nil , - 1 )
214
217
astutil .Apply (p .generated , func (cursor * astutil.Cursor ) bool {
215
218
return cf .walker (cursor , nil )
216
219
}, nil )
217
220
218
221
// Find `import "C"` C fragments in the file.
219
- cgoHeaders : = make ([]string , len (files )) // combined CGo header fragment for each file
222
+ p . cgoHeaders = make ([]string , len (files )) // combined CGo header fragment for each file
220
223
for i , f := range files {
221
224
var cgoHeader string
222
225
for i := 0 ; i < len (f .Decls ); i ++ {
@@ -275,7 +278,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
275
278
cgoHeader += fragment
276
279
}
277
280
278
- cgoHeaders [i ] = cgoHeader
281
+ p . cgoHeaders [i ] = cgoHeader
279
282
}
280
283
281
284
// Define CFlags that will be used while parsing the package.
@@ -289,7 +292,7 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
289
292
}
290
293
291
294
// Retrieve types such as C.int, C.longlong, etc from C.
292
- p .newCGoFile ().readNames (builtinAliasTypedefs , cflagsForCGo , "" , func (names map [string ]clangCursor ) {
295
+ p .newCGoFile (nil , - 1 ).readNames (builtinAliasTypedefs , cflagsForCGo , "" , func (names map [string ]clangCursor ) {
293
296
gen := & ast.GenDecl {
294
297
TokPos : token .NoPos ,
295
298
Tok : token .TYPE ,
@@ -303,8 +306,8 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
303
306
304
307
// Process CGo imports for each file.
305
308
for i , f := range files {
306
- cf := p .newCGoFile ()
307
- cf .readNames (cgoHeaders [i ], cflagsForCGo , filepath .Base (fset .File (f .Pos ()).Name ()), func (names map [string ]clangCursor ) {
309
+ cf := p .newCGoFile (f , i )
310
+ cf .readNames (p . cgoHeaders [i ], cflagsForCGo , filepath .Base (fset .File (f .Pos ()).Name ()), func (names map [string ]clangCursor ) {
308
311
for _ , name := range builtinAliases {
309
312
// Names such as C.int should not be obtained from C.
310
313
// This works around an issue in picolibc that has `#define int`
@@ -320,12 +323,14 @@ func Process(files []*ast.File, dir string, fset *token.FileSet, cflags []string
320
323
// Print the newly generated in-memory AST, for debugging.
321
324
//ast.Print(fset, p.generated)
322
325
323
- return p .generated , cgoHeaders , p .cflags , p .ldflags , p .visitedFiles , p .errors
326
+ return p .generated , p . cgoHeaders , p .cflags , p .ldflags , p .visitedFiles , p .errors
324
327
}
325
328
326
- func (p * cgoPackage ) newCGoFile () * cgoFile {
329
+ func (p * cgoPackage ) newCGoFile (file * ast. File , index int ) * cgoFile {
327
330
return & cgoFile {
328
331
cgoPackage : p ,
332
+ file : file ,
333
+ index : index ,
329
334
defined : make (map [string ]ast.Node ),
330
335
names : make (map [string ]clangCursor ),
331
336
}
@@ -1117,8 +1122,11 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
1117
1122
return alias
1118
1123
}
1119
1124
node := f .getASTDeclNode (name , found , iscall )
1120
- if _ , ok := node .(* ast.FuncDecl ); ok && ! iscall {
1121
- return "C." + name + "$funcaddr"
1125
+ if node , ok := node .(* ast.FuncDecl ); ok {
1126
+ if ! iscall {
1127
+ return node .Name .Name + "$funcaddr"
1128
+ }
1129
+ return node .Name .Name
1122
1130
}
1123
1131
return "C." + name
1124
1132
}
@@ -1142,7 +1150,7 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
1142
1150
// Original cgo reports an error like
1143
1151
// cgo: inconsistent definitions for C.myint
1144
1152
// which is far less helpful.
1145
- f .addError (getPos (node ), " defined previously at "+ f .fset .Position (getPos (newNode )).String ()+ " with a different type" )
1153
+ f .addError (getPos (node ), name + " defined previously at "+ f .fset .Position (getPos (newNode )).String ()+ " with a different type" )
1146
1154
}
1147
1155
f .defined [name ] = node
1148
1156
return node
@@ -1152,17 +1160,25 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
1152
1160
f .defined [name ] = nil
1153
1161
node , elaboratedType := f .createASTNode (name , found )
1154
1162
f .defined [name ] = node
1155
- f .definedGlobally [name ] = node
1156
1163
switch node := node .(type ) {
1157
1164
case * ast.FuncDecl :
1165
+ if strings .HasPrefix (node .Doc .List [0 ].Text , "//export _Cgo_static_" ) {
1166
+ // Static function. Only accessible in the current Go file.
1167
+ globalName := strings .TrimPrefix (node .Doc .List [0 ].Text , "//export " )
1168
+ aliasDeclaration := fmt .Sprintf ("void %s(void) __attribute__((alias(%#v)));" , globalName , name )
1169
+ f .cgoHeaders [f .index ] += "\n \n " + aliasDeclaration
1170
+ } else {
1171
+ // Regular (non-static) function.
1172
+ f .definedGlobally [name ] = node
1173
+ }
1158
1174
f .generated .Decls = append (f .generated .Decls , node )
1159
1175
// Also add a declaration like the following:
1160
1176
// var C.foo$funcaddr unsafe.Pointer
1161
1177
f .generated .Decls = append (f .generated .Decls , & ast.GenDecl {
1162
1178
Tok : token .VAR ,
1163
1179
Specs : []ast.Spec {
1164
1180
& ast.ValueSpec {
1165
- Names : []* ast.Ident {{Name : "C." + name + "$funcaddr" }},
1181
+ Names : []* ast.Ident {{Name : node . Name . Name + "$funcaddr" }},
1166
1182
Type : & ast.SelectorExpr {
1167
1183
X : & ast.Ident {Name : "unsafe" },
1168
1184
Sel : & ast.Ident {Name : "Pointer" },
@@ -1171,8 +1187,10 @@ func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) as
1171
1187
},
1172
1188
})
1173
1189
case * ast.GenDecl :
1190
+ f .definedGlobally [name ] = node
1174
1191
f .generated .Decls = append (f .generated .Decls , node )
1175
1192
case * ast.TypeSpec :
1193
+ f .definedGlobally [name ] = node
1176
1194
f .generated .Decls = append (f .generated .Decls , & ast.GenDecl {
1177
1195
Tok : token .TYPE ,
1178
1196
Specs : []ast.Spec {node },
0 commit comments