1
0
mirror of https://github.com/golang/go synced 2024-11-24 21:00:09 -07:00

cgo: print line numbers in fatal errors when relevant.

Signatures of fatalf and error_ helpers have been matched for
consistency.
Fixes #1800.

R=rsc
CC=golang-dev, remy
https://golang.org/cl/5593049
This commit is contained in:
Rémy Oudompheng 2012-02-06 20:38:54 +01:00
parent 1c290fda50
commit 0d07600de3
3 changed files with 58 additions and 30 deletions

View File

@ -524,6 +524,10 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
for i, n := range names { for i, n := range names {
nameToIndex[n] = i nameToIndex[n] = i
} }
nameToRef := make(map[*Name]*Ref)
for _, ref := range f.Ref {
nameToRef[ref.Name] = ref
}
r := d.Reader() r := d.Reader()
for { for {
e, err := r.Next() e, err := r.Next()
@ -597,12 +601,16 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
if types[i] == nil { if types[i] == nil {
continue continue
} }
pos := token.NoPos
if ref, ok := nameToRef[n]; ok {
pos = ref.Pos()
}
f, fok := types[i].(*dwarf.FuncType) f, fok := types[i].(*dwarf.FuncType)
if n.Kind != "type" && fok { if n.Kind != "type" && fok {
n.Kind = "func" n.Kind = "func"
n.FuncType = conv.FuncType(f) n.FuncType = conv.FuncType(f, pos)
} else { } else {
n.Type = conv.Type(types[i]) n.Type = conv.Type(types[i], pos)
if enums[i] != 0 && n.Type.EnumValues != nil { if enums[i] != 0 && n.Type.EnumValues != nil {
k := fmt.Sprintf("__cgo_enum__%d", i) k := fmt.Sprintf("__cgo_enum__%d", i)
n.Kind = "const" 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 // Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field. // 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, ok := c.m[dtype]; ok {
if t.Go == nil { if t.Go == nil {
fatalf("type conversion loop at %s", dtype) fatalf("%s: type conversion loop at %s", lineno(pos), dtype)
} }
return t return t
} }
@ -998,11 +1006,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
switch dt := dtype.(type) { switch dt := dtype.(type) {
default: default:
fatalf("unexpected type: %s", dtype) fatalf("%s: unexpected type: %s", lineno(pos), dtype)
case *dwarf.AddrType: case *dwarf.AddrType:
if t.Size != c.ptrSize { 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.Go = c.uintptr
t.Align = t.Size t.Align = t.Size
@ -1017,7 +1025,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
Len: c.intExpr(dt.Count), Len: c.intExpr(dt.Count),
} }
t.Go = gt // publish before recursive call t.Go = gt // publish before recursive call
sub := c.Type(dt.Type) sub := c.Type(dt.Type, pos)
t.Align = sub.Align t.Align = sub.Align
gt.Elt = sub.Go gt.Elt = sub.Go
t.C.Set("typeof(%s[%d])", sub.C, dt.Count) 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: case *dwarf.CharType:
if t.Size != 1 { 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.Go = c.int8
t.Align = 1 t.Align = 1
@ -1048,7 +1056,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
} }
switch t.Size + int64(signed) { switch t.Size + int64(signed) {
default: 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: case 1:
t.Go = c.uint8 t.Go = c.uint8
case 2: case 2:
@ -1070,7 +1078,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.FloatType: case *dwarf.FloatType:
switch t.Size { switch t.Size {
default: 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: case 4:
t.Go = c.float32 t.Go = c.float32
case 8: case 8:
@ -1083,7 +1091,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.ComplexType: case *dwarf.ComplexType:
switch t.Size { switch t.Size {
default: 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: case 8:
t.Go = c.complex64 t.Go = c.complex64
case 16: case 16:
@ -1101,11 +1109,11 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.IntType: case *dwarf.IntType:
if dt.BitSize > 0 { 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 { switch t.Size {
default: 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: case 1:
t.Go = c.int8 t.Go = c.int8
case 2: case 2:
@ -1131,13 +1139,13 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
gt := &ast.StarExpr{} gt := &ast.StarExpr{}
t.Go = gt // publish before recursive call t.Go = gt // publish before recursive call
sub := c.Type(dt.Type) sub := c.Type(dt.Type, pos)
gt.X = sub.Go gt.X = sub.Go
t.C.Set("%s*", sub.C) t.C.Set("%s*", sub.C)
case *dwarf.QualType: case *dwarf.QualType:
// Ignore qualifier. // Ignore qualifier.
t = c.Type(dt.Type) t = c.Type(dt.Type, pos)
c.m[dtype] = t c.m[dtype] = t
return t return t
@ -1161,7 +1169,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
t.C.Set("typeof(unsigned char[%d])", t.Size) t.C.Set("typeof(unsigned char[%d])", t.Size)
} }
case "struct": case "struct":
g, csyntax, align := c.Struct(dt) g, csyntax, align := c.Struct(dt, pos)
if t.C.Empty() { if t.C.Empty() {
t.C.Set(csyntax) t.C.Set(csyntax)
} }
@ -1191,7 +1199,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
name := c.Ident("_Ctype_" + dt.Name) name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name goIdent[name.Name] = name
t.Go = name // publish before recursive call t.Go = name // publish before recursive call
sub := c.Type(dt.Type) sub := c.Type(dt.Type, pos)
t.Size = sub.Size t.Size = sub.Size
t.Align = sub.Align t.Align = sub.Align
if _, ok := typedef[name.Name]; !ok { if _, ok := typedef[name.Name]; !ok {
@ -1203,18 +1211,18 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
case *dwarf.UcharType: case *dwarf.UcharType:
if t.Size != 1 { 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.Go = c.uint8
t.Align = 1 t.Align = 1
case *dwarf.UintType: case *dwarf.UintType:
if dt.BitSize > 0 { 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 { switch t.Size {
default: 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: case 1:
t.Go = c.uint8 t.Go = c.uint8
case 2: case 2:
@ -1250,7 +1258,7 @@ func (c *typeConv) Type(dtype dwarf.Type) *Type {
} }
if t.C.Empty() { 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 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 // FuncArg returns a Go type with the same memory layout as
// dtype when used as the type of a C function argument. // dtype when used as the type of a C function argument.
func (c *typeConv) FuncArg(dtype dwarf.Type) *Type { func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
t := c.Type(dtype) t := c.Type(dtype, pos)
switch dt := dtype.(type) { switch dt := dtype.(type) {
case *dwarf.ArrayType: case *dwarf.ArrayType:
// Arrays are passed implicitly as pointers in C. // 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 // Unless the typedef happens to point to void* since
// Go has special rules around using unsafe.Pointer. // Go has special rules around using unsafe.Pointer.
if _, void := base(ptr.Type).(*dwarf.VoidType); !void { 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. // FuncType returns the Go type analogous to dtype.
// There is no guarantee about matching memory layout. // 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)) p := make([]*Type, len(dtype.ParamType))
gp := make([]*ast.Field, len(dtype.ParamType)) gp := make([]*ast.Field, len(dtype.ParamType))
for i, f := range dtype.ParamType { for i, f := range dtype.ParamType {
@ -1303,13 +1311,13 @@ func (c *typeConv) FuncType(dtype *dwarf.FuncType) *FuncType {
p, gp = nil, nil p, gp = nil, nil
break break
} }
p[i] = c.FuncArg(f) p[i] = c.FuncArg(f, pos)
gp[i] = &ast.Field{Type: p[i].Go} gp[i] = &ast.Field{Type: p[i].Go}
} }
var r *Type var r *Type
var gr []*ast.Field var gr []*ast.Field
if _, ok := dtype.ReturnType.(*dwarf.VoidType); !ok && dtype.ReturnType != nil { 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}} gr = []*ast.Field{{Type: r.Go}}
} }
return &FuncType{ 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. // 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 var buf bytes.Buffer
buf.WriteString("struct {") buf.WriteString("struct {")
fld := make([]*ast.Field, 0, 2*len(dt.Field)+1) // enough for padding around every field 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) fld = c.pad(fld, f.ByteOffset-off)
off = f.ByteOffset off = f.ByteOffset
} }
t := c.Type(f.Type) t := c.Type(f.Type, pos)
tgo := t.Go tgo := t.Go
size := t.Size size := t.Size
@ -1435,7 +1443,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType) (expr *ast.StructType, csyntax s
off = dt.ByteSize off = dt.ByteSize
} }
if off != dt.ByteSize { if off != dt.ByteSize {
fatalf("struct size calculation error") fatalf("%s: struct size calculation error", lineno(pos))
} }
buf.WriteString("}") buf.WriteString("}")
csyntax = buf.String() csyntax = buf.String()

View File

@ -64,6 +64,10 @@ func run(stdin []byte, argv []string) (stdout, stderr []byte, ok bool) {
return return
} }
func lineno(pos token.Pos) string {
return fset.Position(pos).String()
}
// Die with an error message. // Die with an error message.
func fatalf(msg string, args ...interface{}) { func fatalf(msg string, args ...interface{}) {
fmt.Fprintf(os.Stderr, msg+"\n", args...) fmt.Fprintf(os.Stderr, msg+"\n", args...)

16
test/fixedbugs/bug408.go Normal file
View File

@ -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 <stdio.h>
import "C"
func f() {
C.printf(nil) // ERROR "go:15.*unexpected type"
}