diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 155eb0440f..71a9457f5f 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -524,6 +524,10 @@ func (p *Package) loadDWARF(f *File, names []*Name) { for i, n := range names { nameToIndex[n] = i } + nameToRef := make(map[*Name]*Ref) + for _, ref := range f.Ref { + nameToRef[ref.Name] = ref + } r := d.Reader() for { e, err := r.Next() @@ -597,12 +601,16 @@ func (p *Package) loadDWARF(f *File, names []*Name) { if types[i] == nil { continue } + pos := token.NoPos + if ref, ok := nameToRef[n]; ok { + pos = ref.Pos() + } f, fok := types[i].(*dwarf.FuncType) if n.Kind != "type" && fok { n.Kind = "func" - n.FuncType = conv.FuncType(f) + n.FuncType = conv.FuncType(f, pos) } else { - n.Type = conv.Type(types[i]) + n.Type = conv.Type(types[i], pos) if enums[i] != 0 && n.Type.EnumValues != nil { k := fmt.Sprintf("__cgo_enum__%d", i) n.Kind = "const" @@ -972,10 +980,10 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) { // Type returns a *Type with the same memory layout as // dtype when used as the type of a variable or a struct field. -func (c *typeConv) Type(dtype dwarf.Type) *Type { +func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { if t, ok := c.m[dtype]; ok { if t.Go == nil { - fatalf("type conversion loop at %s", dtype) + fatalf("%s: type conversion loop at %s", lineno(pos), dtype) } return t } @@ -998,11 +1006,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { switch dt := dtype.(type) { default: - fatalf("unexpected type: %s", dtype) + fatalf("%s: unexpected type: %s", lineno(pos), dtype) case *dwarf.AddrType: if t.Size != c.ptrSize { - fatalf("unexpected: %d-byte address type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte address type - %s", lineno(pos), t.Size, dtype) } t.Go = c.uintptr t.Align = t.Size @@ -1017,7 +1025,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { Len: c.intExpr(dt.Count), } t.Go = gt // publish before recursive call - sub := c.Type(dt.Type) + sub := c.Type(dt.Type, pos) t.Align = sub.Align gt.Elt = sub.Go t.C.Set("typeof(%s[%d])", sub.C, dt.Count) @@ -1028,7 +1036,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { case *dwarf.CharType: if t.Size != 1 { - fatalf("unexpected: %d-byte char type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte char type - %s", lineno(pos), t.Size, dtype) } t.Go = c.int8 t.Align = 1 @@ -1048,7 +1056,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { } switch t.Size + int64(signed) { default: - fatalf("unexpected: %d-byte enum type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte enum type - %s", lineno(pos), t.Size, dtype) case 1: t.Go = c.uint8 case 2: @@ -1070,7 +1078,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { case *dwarf.FloatType: switch t.Size { default: - fatalf("unexpected: %d-byte float type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte float type - %s", lineno(pos), t.Size, dtype) case 4: t.Go = c.float32 case 8: @@ -1083,7 +1091,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { case *dwarf.ComplexType: switch t.Size { default: - fatalf("unexpected: %d-byte complex type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte complex type - %s", lineno(pos), t.Size, dtype) case 8: t.Go = c.complex64 case 16: @@ -1101,11 +1109,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { case *dwarf.IntType: if dt.BitSize > 0 { - fatalf("unexpected: %d-bit int type - %s", dt.BitSize, dtype) + fatalf("%s: unexpected: %d-bit int type - %s", lineno(pos), dt.BitSize, dtype) } switch t.Size { default: - fatalf("unexpected: %d-byte int type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte int type - %s", lineno(pos), t.Size, dtype) case 1: t.Go = c.int8 case 2: @@ -1131,13 +1139,13 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { gt := &ast.StarExpr{} t.Go = gt // publish before recursive call - sub := c.Type(dt.Type) + sub := c.Type(dt.Type, pos) gt.X = sub.Go t.C.Set("%s*", sub.C) case *dwarf.QualType: // Ignore qualifier. - t = c.Type(dt.Type) + t = c.Type(dt.Type, pos) c.m[dtype] = t return t @@ -1161,7 +1169,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { t.C.Set("typeof(unsigned char[%d])", t.Size) } case "struct": - g, csyntax, align := c.Struct(dt) + g, csyntax, align := c.Struct(dt, pos) if t.C.Empty() { t.C.Set(csyntax) } @@ -1191,7 +1199,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { name := c.Ident("_Ctype_" + dt.Name) goIdent[name.Name] = name t.Go = name // publish before recursive call - sub := c.Type(dt.Type) + sub := c.Type(dt.Type, pos) t.Size = sub.Size t.Align = sub.Align if _, ok := typedef[name.Name]; !ok { @@ -1203,18 +1211,18 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { case *dwarf.UcharType: if t.Size != 1 { - fatalf("unexpected: %d-byte uchar type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte uchar type - %s", lineno(pos), t.Size, dtype) } t.Go = c.uint8 t.Align = 1 case *dwarf.UintType: if dt.BitSize > 0 { - fatalf("unexpected: %d-bit uint type - %s", dt.BitSize, dtype) + fatalf("%s: unexpected: %d-bit uint type - %s", lineno(pos), dt.BitSize, dtype) } switch t.Size { default: - fatalf("unexpected: %d-byte uint type - %s", t.Size, dtype) + fatalf("%s: unexpected: %d-byte uint type - %s", lineno(pos), t.Size, dtype) case 1: t.Go = c.uint8 case 2: @@ -1250,7 +1258,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { } if t.C.Empty() { - fatalf("internal error: did not create C name for %s", dtype) + fatalf("%s: internal error: did not create C name for %s", lineno(pos), dtype) } return t @@ -1258,8 +1266,8 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type { // FuncArg returns a Go type with the same memory layout as // dtype when used as the type of a C function argument. -func (c *typeConv) FuncArg(dtype dwarf.Type) *Type { - t := c.Type(dtype) +func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { + t := c.Type(dtype, pos) switch dt := dtype.(type) { case *dwarf.ArrayType: // Arrays are passed implicitly as pointers in C. @@ -1281,7 +1289,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type { // 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) + return c.Type(ptr, pos) } } } @@ -1290,7 +1298,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type) *Type { // FuncType returns the Go type analogous to dtype. // There is no guarantee about matching memory layout. -func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType { +func (c *typeConv) FuncType(dtype *dwarf.FuncType, pos token.Pos) *FuncType { p := make([]*Type, len(dtype.ParamType)) gp := make([]*ast.Field, len(dtype.ParamType)) for i, f := range dtype.ParamType { @@ -1303,13 +1311,13 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType { p, gp = nil, nil break } - p[i] = c.FuncArg(f) + p[i] = c.FuncArg(f, pos) gp[i] = &ast.Field{Type: p[i].Go} } var r *Type var gr []*ast.Field if _, ok := dtype.ReturnType.(*dwarf.VoidType); !ok && dtype.ReturnType != nil { - r = c.Type(dtype.ReturnType) + r = c.Type(dtype.ReturnType, pos) gr = []*ast.Field{{Type: r.Go}} } return &FuncType{ @@ -1352,7 +1360,7 @@ func (c *typeConv) pad(fld []*ast.Field, size int64) []*ast.Field { } // Struct conversion: return Go and (6g) C syntax for type. -func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax string, align int64) { +func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.StructType, csyntax string, align int64) { var buf bytes.Buffer buf.WriteString("struct {") fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field @@ -1394,7 +1402,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s fld = c.pad(fld, f.ByteOffset-off) off = f.ByteOffset } - t := c.Type(f.Type) + t := c.Type(f.Type, pos) tgo := t.Go size := t.Size @@ -1435,7 +1443,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s off = dt.ByteSize } if off != dt.ByteSize { - fatalf("struct size calculation error") + fatalf("%s: struct size calculation error", lineno(pos)) } buf.WriteString("}") csyntax = buf.String() diff --git a/src/cmd/cgo/util.go b/src/cmd/cgo/util.go index 8a778418df..1bf665ff47 100644 --- a/src/cmd/cgo/util.go +++ b/src/cmd/cgo/util.go @@ -64,6 +64,10 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) { return } +func lineno(pos token.Pos) string { + return fset.Position(pos).String() +} + // Die with an error message. func fatalf(msg string, args ...interface{}) { fmt.Fprintf(os.Stderr, msg+"\n", args...) diff --git a/test/fixedbugs/bug408.go b/test/fixedbugs/bug408.go new file mode 100644 index 0000000000..421b80d4b0 --- /dev/null +++ b/test/fixedbugs/bug408.go @@ -0,0 +1,16 @@ +// errchk cgo $D/$F.go + +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 1800: cgo not reporting line numbers. + +package main + +// #include +import "C" + +func f() { + C.printf(nil) // ERROR "go:15.*unexpected type" +}