diff --git a/cgo/cgo.go b/cgo/cgo.go index 9867b875..22666499 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -992,3 +992,29 @@ func (p *cgoPackage) walker(cursor *astutil.Cursor) bool { } return true } + +// renameFieldKeywords renames all reserved words in Go to some other field name +// with a "_" prefix. For example, it renames `type` to `_type`. +// +// See: https://golang.org/cmd/cgo/#hdr-Go_references_to_C +func renameFieldKeywords(fieldList *ast.FieldList) { + renameFieldName(fieldList, "type") +} + +// renameFieldName renames a given field name to a name with a "_" prepended. It +// makes sure to do the same thing for any field sharing the same name. +func renameFieldName(fieldList *ast.FieldList, name string) { + var ident *ast.Ident + for _, f := range fieldList.List { + for _, n := range f.Names { + if n.Name == name { + ident = n + } + } + } + if ident == nil { + return + } + renameFieldName(fieldList, "_"+name) + ident.Name = "_" + ident.Name +} diff --git a/cgo/libclang.go b/cgo/libclang.go index a4817a4f..1cbc78c4 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -605,6 +605,7 @@ func (p *cgoPackage) makeASTRecordType(cursor C.GoCXCursor, pos token.Pos) (*ast }{fieldList, p, &inBitfield, &bitfieldNum, &bitfieldList}) defer storedRefs.Remove(ref) C.tinygo_clang_visitChildren(cursor, C.CXCursorVisitor(C.tinygo_clang_struct_visitor), C.CXClientData(ref)) + renameFieldKeywords(fieldList) switch C.tinygo_clang_getCursorKind(cursor) { case C.CXCursor_StructDecl: return &ast.StructType{ diff --git a/cgo/testdata/types.go b/cgo/testdata/types.go index b129d4be..bd1f0ffb 100644 --- a/cgo/testdata/types.go +++ b/cgo/testdata/types.go @@ -15,6 +15,18 @@ typedef struct point3d { int z; } point3d_t; +// Structs with reserved field names. +struct type1 { + // All these fields should be renamed. + int type; + int _type; + int __type; +}; +struct type2 { + // This field should not be renamed. + int _type; +}; + // Enums. These define constant numbers. All these constants must be given the // correct number. typedef enum option { @@ -66,6 +78,10 @@ var ( _ C.point3d_t _ C.struct_point3d + // Structs with reserved field names. + _ C.struct_type1 + _ C.struct_type2 + // Enums (anonymous and named). _ C.option_t _ C.enum_option diff --git a/cgo/testdata/types.out.go b/cgo/testdata/types.out.go index 6e586a9d..939c1a5a 100644 --- a/cgo/testdata/types.out.go +++ b/cgo/testdata/types.out.go @@ -72,4 +72,10 @@ type C.struct_point3d struct { y C.int z C.int } +type C.struct_type1 struct { + _type C.int + __type C.int + ___type C.int +} +type C.struct_type2 struct{ _type C.int } type C.enum_option C.int