From 652bb7c2bed501110d7371ea0187d56dd58acef3 Mon Sep 17 00:00:00 2001 From: Eden Li Date: Wed, 18 Nov 2009 09:59:10 -0800 Subject: [PATCH] Mangle C struct fields that happen to be named after Go keywords by prefixing them with _. Collisions with existing fields are resolved by prefixing the new Go identifier with _ until it matches nothing else in the struct. Fixes #36. R=rsc https://golang.org/cl/157061 --- src/cmd/cgo/gcc.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 79dcd29a9657ac..5f3653976df4f3 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -619,6 +619,34 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s csyntax = "struct { "; fld := make([]*ast.Field, 0, 2*len(dt.Field)+1); // enough for padding around every field off := int64(0); + + // Mangle struct fields that happen to be named Go keywords into + // _{keyword}. Create a map from C ident -> Go ident. The Go ident will + // be mangled. Any existing identifier that already has the same name on + // the C-side will cause the Go-mangled version to be prefixed with _. + // (e.g. in a struct with fields '_type' and 'type', the latter would be + // rendered as '__type' in Go). + ident := make(map[string]string); + used := make(map[string]bool); + for _, f := range dt.Field { + ident[f.Name] = f.Name; + used[f.Name] = true; + } + for cid, goid := range ident { + if token.Lookup(strings.Bytes(goid)).IsKeyword() { + // Avoid keyword + goid = "_" + goid; + + // Also avoid existing fields + for _, exist := used[goid]; exist; _, exist = used[goid] { + goid = "_" + goid + } + + used[goid] = true; + ident[cid] = goid; + } + } + for _, f := range dt.Field { if f.ByteOffset > off { fld = c.pad(fld, f.ByteOffset-off); @@ -627,7 +655,8 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s t := c.Type(f.Type); n := len(fld); fld = fld[0 : n+1]; - fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(f.Name)}, Type: t.Go}; + + fld[n] = &ast.Field{Names: []*ast.Ident{c.Ident(ident[f.Name])}, Type: t.Go}; off += t.Size; csyntax += t.C + " " + f.Name + "; "; if t.Align > align {