From 1a0c8fe9bb4498024c82dcc9d1beeb3e60cfe5d8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Feb 2012 13:32:55 -0500 Subject: [PATCH] cmd/cgo: bug fixes * disallow embedding of C type (Fixes issue 2552) * detect 0-length array (Fixes issue 2806) * use typedefs when possible, to avoid attribute((unavailable)) (Fixes issue 2888) * print Go types constructed from C types using original C types (Fixes issue 2612) This fix changes _cgo_export.h to repeat the preamble from import "C". Otherwise the fix to issue 2612 is impossible, since it cannot refer to types that have not been defined. If people are using //export and putting non-header information in the preamble, they will need to refactor their code. R=golang-dev, r, r CC=golang-dev https://golang.org/cl/5672080 --- doc/go1.html | 19 ++++++++++- doc/go1.tmpl | 19 ++++++++++- src/cmd/cgo/ast.go | 15 ++++++--- src/cmd/cgo/doc.go | 9 ++++-- src/cmd/cgo/gcc.go | 35 ++++++++++++++------ src/cmd/cgo/godefs.go | 2 +- src/cmd/cgo/main.go | 7 +++- src/cmd/cgo/out.go | 17 ++++++---- src/cmd/cgo/util.go | 6 +++- src/pkg/debug/dwarf/testdata/typedef.c | 8 ++++- src/pkg/debug/dwarf/testdata/typedef.elf | Bin 10837 -> 12448 bytes src/pkg/debug/dwarf/testdata/typedef.macho | Bin 5256 -> 5024 bytes src/pkg/debug/dwarf/type.go | 36 ++++++++++++++++++++- src/pkg/debug/dwarf/type_test.go | 19 ++++++++--- 14 files changed, 157 insertions(+), 35 deletions(-) diff --git a/doc/go1.html b/doc/go1.html index 05d3eb5031..f4a4623db6 100644 --- a/doc/go1.html +++ b/doc/go1.html @@ -1853,7 +1853,24 @@ Code that uses the old fields will fail to compile and must be updated by hand. The semantic changes make it difficult for the fix tool to update automatically.

-

The go command

+

The go command

+ +

+TODO: Write this. +

+ +

The cgo command

+ +

+In Go 1, the cgo command +uses a different _cgo_export.h +file, which is generated for packages containing //export lines. +The _cgo_export.h file now begins with the C preamble comment, +so that exported function definitions can use types defined there. +This has the effect of compiling the preamble multiple times, so a +package using //export must not put function definitions +or variable initializations in the C preamble. +

Packaged releases diff --git a/doc/go1.tmpl b/doc/go1.tmpl index 7a28be3c3a..314a6de93d 100644 --- a/doc/go1.tmpl +++ b/doc/go1.tmpl @@ -1725,7 +1725,24 @@ Code that uses the old fields will fail to compile and must be updated by hand. The semantic changes make it difficult for the fix tool to update automatically.

-

The go command

+

The go command

+ +

+TODO: Write this. +

+ +

The cgo command

+ +

+In Go 1, the cgo command +uses a different _cgo_export.h +file, which is generated for packages containing //export lines. +The _cgo_export.h file now begins with the C preamble comment, +so that exported function definitions can use types defined there. +This has the effect of compiling the preamble multiple times, so a +package using //export must not put function definitions +or variable initializations in the C preamble. +

Packaged releases diff --git a/src/cmd/cgo/ast.go b/src/cmd/cgo/ast.go index da6ae4176d..381e606ef4 100644 --- a/src/cmd/cgo/ast.go +++ b/src/cmd/cgo/ast.go @@ -147,6 +147,9 @@ func (f *File) saveRef(x interface{}, context string) { if context == "as2" { context = "expr" } + if context == "embed-type" { + error_(sel.Pos(), "cannot embed C type") + } goname := sel.Sel.Name if goname == "errno" { error_(sel.Pos(), "cannot refer to errno directly; see documentation") @@ -232,7 +235,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} // These are ordered and grouped to match ../../pkg/go/ast/ast.go case *ast.Field: - f.walk(&n.Type, "type", visit) + if len(n.Names) == 0 && context == "field" { + f.walk(&n.Type, "embed-type", visit) + } else { + f.walk(&n.Type, "type", visit) + } case *ast.FieldList: for _, field := range n.List { f.walk(field, context, visit) @@ -289,9 +296,9 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} case *ast.StructType: f.walk(n.Fields, "field", visit) case *ast.FuncType: - f.walk(n.Params, "field", visit) + f.walk(n.Params, "param", visit) if n.Results != nil { - f.walk(n.Results, "field", visit) + f.walk(n.Results, "param", visit) } case *ast.InterfaceType: f.walk(n.Methods, "field", visit) @@ -379,7 +386,7 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} f.walk(n.Specs, "spec", visit) case *ast.FuncDecl: if n.Recv != nil { - f.walk(n.Recv, "field", visit) + f.walk(n.Recv, "param", visit) } f.walk(n.Type, "type", visit) if n.Body != nil { diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 1d64c75ada..83f1ba46c0 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -16,8 +16,8 @@ the pseudo-package "C" and then refers to types such as C.size_t, variables such as C.stdout, or functions such as C.putchar. If the import of "C" is immediately preceded by a comment, that -comment is used as a header when compiling the C parts of -the package. For example: +comment, called the preamble, is used as a header when compiling +the C parts of the package. For example: // #include // #include @@ -57,6 +57,8 @@ The C type void* is represented by Go's unsafe.Pointer. To access a struct, union, or enum type directly, prefix it with struct_, union_, or enum_, as in C.struct_stat. +Go structs cannot embed fields with C types. + Any C function that returns a value may be called in a multiple assignment context to retrieve both the return value and the C errno variable as an error. For example: @@ -100,7 +102,8 @@ They will be available in the C code as: extern int64 MyFunction(int arg1, int arg2, GoString arg3); extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3); -found in _cgo_export.h generated header. Functions with multiple +found in _cgo_export.h generated header, after any preambles +copied from the cgo input files. Functions with multiple return values are mapped to functions returning a struct. Not all Go types can be mapped to C types in a useful way. diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 71a9457f5f..342a8a530d 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -709,7 +709,7 @@ func (p *Package) rewriteRef(f *File) { // Substitute definition for mangled type name. if id, ok := expr.(*ast.Ident); ok { if t := typedef[id.Name]; t != nil { - expr = t + expr = t.Go } if id.Name == r.Name.Mangle && r.Name.Const != "" { expr = ast.NewIdent(r.Name.Const) @@ -894,7 +894,7 @@ type typeConv struct { } var tagGen int -var typedef = make(map[string]ast.Expr) +var typedef = make(map[string]*Type) var goIdent = make(map[string]*ast.Ident) func (c *typeConv) Init(ptrSize int64) { @@ -1164,17 +1164,22 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { goIdent[name.Name] = name switch dt.Kind { case "union", "class": - typedef[name.Name] = c.Opaque(t.Size) if t.C.Empty() { t.C.Set("typeof(unsigned char[%d])", t.Size) } + typedef[name.Name] = t case "struct": g, csyntax, align := c.Struct(dt, pos) if t.C.Empty() { t.C.Set(csyntax) } t.Align = align - typedef[name.Name] = g + tt := *t + if tag != "" { + tt.C = &TypeRepr{"struct %s", []interface{}{tag}} + } + tt.Go = g + typedef[name.Name] = &tt } case *dwarf.TypedefType: @@ -1203,7 +1208,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { t.Size = sub.Size t.Align = sub.Align if _, ok := typedef[name.Name]; !ok { - typedef[name.Name] = sub.Go + tt := *t + tt.Go = sub.Go + typedef[name.Name] = &tt } if *godefs || *cdefs { t.Go = sub.Go @@ -1250,7 +1257,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { } s = strings.Join(strings.Split(s, " "), "") // strip spaces name := c.Ident("_Ctype_" + s) - typedef[name.Name] = t.Go + tt := *t + typedef[name.Name] = &tt if !*godefs && !*cdefs { t.Go = name } @@ -1288,9 +1296,18 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { if ptr, ok := base(dt.Type).(*dwarf.PtrType); ok { // Unless the typedef happens to point to void* since // Go has special rules around using unsafe.Pointer. - if _, void := base(ptr.Type).(*dwarf.VoidType); !void { - return c.Type(ptr, pos) + if _, void := base(ptr.Type).(*dwarf.VoidType); void { + break } + + t = c.Type(ptr, pos) + if t == nil { + return nil + } + + // Remember the C spelling, in case the struct + // has __attribute__((unavailable)) on it. See issue 2888. + t.Typedef = dt.Name } } return t @@ -1443,7 +1460,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct off = dt.ByteSize } if off != dt.ByteSize { - fatalf("%s: struct size calculation error", lineno(pos)) + fatalf("%s: struct size calculation error off=%d bytesize=%d", lineno(pos), off, dt.ByteSize) } buf.WriteString("}") csyntax = buf.String() diff --git a/src/cmd/cgo/godefs.go b/src/cmd/cgo/godefs.go index 478ed261cb..fec70a334b 100644 --- a/src/cmd/cgo/godefs.go +++ b/src/cmd/cgo/godefs.go @@ -80,7 +80,7 @@ func (p *Package) godefs(f *File, srcfile string) string { // and xxx is a typedef for yyy, make C.yyy format as T. for typ, def := range typedef { if new := override[typ]; new != "" { - if id, ok := def.(*ast.Ident); ok { + if id, ok := def.Go.(*ast.Ident); ok { override[id.Name] = new } } diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index fb5074e814..a8be7be7d9 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -39,6 +39,7 @@ type Package struct { Decl []ast.Decl GoFiles []string // list of Go files GccFiles []string // list of gcc output files + Preamble string // collected preamble for _cgo_export.h } // A File collects information about a single Go input file. @@ -98,6 +99,7 @@ type Type struct { C *TypeRepr Go ast.Expr EnumValues map[string]int64 + Typedef string } // A FuncType collects information about a function type in both the C and Go worlds. @@ -312,6 +314,9 @@ func (p *Package) Record(f *File) { } } - p.ExpFunc = append(p.ExpFunc, f.ExpFunc...) + if f.ExpFunc != nil { + p.ExpFunc = append(p.ExpFunc, f.ExpFunc...) + p.Preamble += "\n" + f.Preamble + } p.Decl = append(p.Decl, f.AST.Decls...) } diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 2a012177b3..4dc0f84549 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -59,7 +59,7 @@ func (p *Package) writeDefs() { for name, def := range typedef { fmt.Fprintf(fgo2, "type %s ", name) - conf.Fprint(fgo2, fset, def) + conf.Fprint(fgo2, fset, def.Go) fmt.Fprintf(fgo2, "\n\n") } fmt.Fprintf(fgo2, "type _Ctype_void [0]byte\n") @@ -196,7 +196,11 @@ func (p *Package) structType(n *Name) (string, int64) { fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) off += pad } - fmt.Fprintf(&buf, "\t\t%s p%d;\n", t.C, i) + c := t.Typedef + if c == "" { + c = t.C.String() + } + fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i) off += t.Size } if off%p.PtrSize != 0 { @@ -428,6 +432,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) { fgcch := creat(*objDir + "_cgo_export.h") fmt.Fprintf(fgcch, "/* Created by cgo - DO NOT EDIT. */\n") + fmt.Fprintf(fgcch, "%s\n", p.Preamble) fmt.Fprintf(fgcch, "%s\n", gccExportHeaderProlog) fmt.Fprintf(fgcc, "/* Created by cgo - DO NOT EDIT. */\n") @@ -693,10 +698,8 @@ func (p *Package) cgoType(e ast.Expr) *Type { } } } - for name, def := range typedef { - if name == t.Name { - return p.cgoType(def) - } + if def := typedef[t.Name]; def != nil { + return def } if t.Name == "uintptr" { return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("uintptr")} @@ -721,7 +724,7 @@ func (p *Package) cgoType(e ast.Expr) *Type { return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("void*")} } } - error_(e.Pos(), "unrecognized Go type %T", e) + error_(e.Pos(), "Go type not supported in export: %s", gofmt(e)) return &Type{Size: 4, Align: 4, C: c("int")} } diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go index 1bf665ff47..d6b6a7abb6 100644 --- a/src/cmd/cgo/util.go +++ b/src/cmd/cgo/util.go @@ -70,7 +70,11 @@ func lineno(pos token.Pos) string { // Die with an error message. func fatalf(msg string, args ...interface{}) { - fmt.Fprintf(os.Stderr, msg+"\n", args...) + // If we've already printed other errors, they might have + // caused the fatal condition. Assume they're enough. + if nerrors == 0 { + fmt.Fprintf(os.Stderr, msg+"\n", args...) + } os.Exit(2) } diff --git a/src/pkg/debug/dwarf/testdata/typedef.c b/src/pkg/debug/dwarf/testdata/typedef.c index 664d021ced..f05f01564f 100644 --- a/src/pkg/debug/dwarf/testdata/typedef.c +++ b/src/pkg/debug/dwarf/testdata/typedef.c @@ -28,8 +28,13 @@ typedef struct my_struct { volatile int vi; char x : 1; int y : 4; + int z[0]; long long array[40]; + int zz[0]; } t_my_struct; +typedef struct my_struct1 { + int zz [1]; +} t_my_struct1; typedef union my_union { volatile int vi; char x : 1; @@ -65,7 +70,8 @@ t_func_void_of_char *a9; t_func_void_of_void *a10; t_func_void_of_ptr_char_dots *a11; t_my_struct *a12; -t_my_union *a12a; +t_my_struct1 *a12a; +t_my_union *a12b; t_my_enum *a13; t_my_list *a14; t_my_tree *a15; diff --git a/src/pkg/debug/dwarf/testdata/typedef.elf b/src/pkg/debug/dwarf/testdata/typedef.elf index 44df8da9bc7c4683d557a34bee8715ab754e2d34..b2062d2c4bb828dcb229f12869f77fd5d9522278 100755 GIT binary patch literal 12448 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
uyG6y&-61`(FbhA4 zP_*q1yIl_UXcHZFZ~rcYzNixQ+x}qy9_&D|Ucke@R7Cu(_#}=;4?h9Fku*&&;ym)w z;km)$%@2EDh&16c~%Zxd4jKXy{) z=PxK9Smz2T{u~!wFX#X$>gHTVbXc9veW3WBbY6vXd`38*1;xGISpn??jf0~8&dWN! zZ)*A#O~0sV5)@D$V#+2Pikdl1&ujW&PzMPH-(t|kPC%!d2il4EFCtlP!+7vIf?Q?0 zy-6N#l4qLacQwiPG|7ui^64gdxk*0PB!8eu#$4=*7jw5u=5MCPe0U8v%KSaoDC>1m z&p+ApeyB+%SMFFBo6Y5&=3-;H*lI5JnTy@!Vo$l)UM_EVbZPEbm$x_f8SW>zW5YCC XVn3r}TkK?sKkBd1!lL@t9;5#P8kMr% literal 5256 zcmb7IU2I%O6+W{+_O*BSdTqy!lMS%JNt0HMo%L_hB(+mFiA{fiB&CH^yObq#l?!Z zu^sPQ24|i@N4a6*=u4Wm$E&!d6|cI@zqc&E=TQT2n+g0AeeXQqH8-!P9G>rOT`iuV z`jKEEo6T+gD;7#zj&1%0c(bN|fcF&qDR^*wR^l!bsSi+8} zhVfo9cwaMkf4q6T+LiU~c$d0;pf}9=KG|b{o2>183nfNyXUku0(jgf*RWrhj*ur- zjY>04ehA-BpdVm;m&iIe^GR@axfJ|pODvfF-{pb%&;H@t?Df+h>b@98-bPWPE~k^7 z)>CG^4`^+Z1bHn+y`6q65~ByHjz^FO{DrgBx%(f;&SfV?#zu14!>8BRi(Yo2lpo11 z)(gd@?Bvwc#I2&Z+m^iLk-UtqR|*?$%^R()t>gtfj{bhN2LuIqS8Gvr#U(wL;Nz z3Z(ijIt03`MobARoUoKT^PJY#`i0b*Ow!9A7@d7PXhgQI}ST3!IO825xA$KQ-XqBpivv(+#+tXTqqOurxsjr?Fq6)+tcm$NNyTNF<(Z zfa(QlBJ22YCzyzH6`iW4b$_XMe_jJ#1LbFNxvdvi`yL1e)H_9Wm{ruB;>v0)t8PF{ z^hg`!!V(wOhaP$j2wmzQ0W23{iy6&D?MdTEbgQtEUK0m_s8vPnoq|=Dngg{+5^#;a zCfBYwNOtvnP3D!#JPlQ9qabP@w|Qh(Y%K4)XsA?YWH^R1px(_X#bOzVDYsH_(exhn ziws-R^L13N;Y*Vol3uGb*ygQ!y*a4LF2Jx44fRr?T#{L(_V>m_`su`b>BKI0Fl;>7 zg|QC!!|&@iV;|($j7o5LZncmu3-98LsAFf!a;y{jk3=O+=J*`Hbg^=2Ci=vLQiV&qre4?q`buC&ryK(>Q z@?b};kFs~I;(0QpCSGUnqPGnDN!HoDQdn7S%9am4^;fM;1K>r};#Q}QpC*mXV=@OO zs`1q{O?hOoT=!iiGo>}R^-ysZ7uX)z>o{{~=a{(MQtd*mQYfv=72Rs}ytnLCyi(qi z6R=a*7w(v-<5wwkG1|IBEeAZ~j=Q4ncrL7a9t~0JNo_G9>ckJi1}|yVq^Og>4Xa+& zswq*Y-UzGysa4aW?(FLbc{7WNXWV0=W{!kaOE^Or_qeFp`LOC2T9rF0>hw}r$D@~V zbJ#a`ZH9Gyhy!$p%iObJ-FJ-+fw}wTu#&qQ9mhqT`BhlQeF`1ob(XuSCD>?1sLplb z-fL-%THOc`bcogba9CH=0m&g)3o~KecYGb9^}b7CT{otUdq^F$`V&zrWA&;&m4>U4 zL9FNtr7D$b3~~&QLAxm?5~)No!Nwk?eBAVY;ErN<_xhtFlkDDt*5B-oOwts5 zEF_5-%@e`kgNHHrz7!6ucB;`nG$J#}sO`_4;h04@_UwoEdneFip?@YhkvxeRWhnY) zGsy@av$x}8JP`y<1JZgVgEsP$_#%=8Rq9`uJx(8%iVrX)%|{Gckj{Nv)S^EVbIOupiCSH7<+%<74gk zeB#O5$s~B@@C0tR3B84Q6t^4k76?CZnBt7n@AP0{x(huc^lO8uF4V4{7ff@Z_N^}q zUf;NY%o~E4Pv68w=0)7Nmznumu4&%0!5z)Sr&an6=7p>8Ti$2-YGazydM#mn{GBNL z9l@eLah|^q3#Uj%`R_GNI4Yd;K*soTsG@Xpj2^+yZ`JpH<8cq|JUEBgpJ?CgEu zC=ZjPJ-GyKW5D2dBW#deK}@*>-UIzQg2HkbAJok9x|ner@>obe9g