Skip to content

Commit

Permalink
cmd/cgo: consistently map void* to *byte under -{c,go}defs
Browse files Browse the repository at this point in the history
Fixes golang#8478.

LGTM=iant
R=iant
CC=golang-codereviews
https://golang.org/cl/122150043
  • Loading branch information
mdempsky authored and wheatman committed Jun 28, 2018
1 parent edb8353 commit e6f18b7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 31 deletions.
20 changes: 20 additions & 0 deletions misc/cgo/testgodefs/issue8478.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2014 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.
//
// +build ignore

package main

// Issue 8478. Test that void* is consistently mapped to *byte.

/*
typedef struct {
void *p;
void **q;
void ***r;
} s;
*/
import "C"

type Issue8478 C.s
3 changes: 3 additions & 0 deletions misc/cgo/testgodefs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,8 @@ package main
var v1 T
var v2 = v1.L

// Test that P, Q, and R all point to byte.
var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)}

func main() {
}
2 changes: 1 addition & 1 deletion misc/cgo/testgodefs/test.bash
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# We are testing cgo -godefs, which translates Go files that use
# import "C" into Go files with Go definitions of types defined in the
# import "C" block. Add more tests here.
FILE_PREFIXES="anonunion"
FILE_PREFIXES="anonunion issue8478"

RM=
for FP in $FILE_PREFIXES
Expand Down
42 changes: 12 additions & 30 deletions src/cmd/cgo/gcc.go
Original file line number Diff line number Diff line change
Expand Up @@ -929,9 +929,6 @@ type typeConv struct {
// Map from types to incomplete pointers to those types.
ptrs map[dwarf.Type][]*Type

// Fields to be processed by godefsField after completing pointers.
todoFlds [][]*ast.Field

// Predeclared types.
bool ast.Expr
byte ast.Expr // denotes padding
Expand All @@ -940,9 +937,9 @@ type typeConv struct {
float32, float64 ast.Expr
complex64, complex128 ast.Expr
void ast.Expr
unsafePointer ast.Expr
string ast.Expr
goVoid ast.Expr // _Ctype_void, denotes C's void
goVoidPtr ast.Expr // unsafe.Pointer or *byte

ptrSize int64
intSize int64
Expand Down Expand Up @@ -972,10 +969,17 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.float64 = c.Ident("float64")
c.complex64 = c.Ident("complex64")
c.complex128 = c.Ident("complex128")
c.unsafePointer = c.Ident("unsafe.Pointer")
c.void = c.Ident("void")
c.string = c.Ident("string")
c.goVoid = c.Ident("_Ctype_void")

// Normally cgo translates void* to unsafe.Pointer,
// but for historical reasons -cdefs and -godefs use *byte instead.
if *cdefs || *godefs {
c.goVoidPtr = &ast.StarExpr{X: c.byte}
} else {
c.goVoidPtr = c.Ident("unsafe.Pointer")
}
}

// base strips away qualifiers and typedefs to get the underlying type
Expand Down Expand Up @@ -1037,8 +1041,7 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
}

// FinishType completes any outstanding type mapping work.
// In particular, it resolves incomplete pointer types and also runs
// godefsFields on any new struct types.
// In particular, it resolves incomplete pointer types.
func (c *typeConv) FinishType(pos token.Pos) {
// Completing one pointer type might produce more to complete.
// Keep looping until they're all done.
Expand All @@ -1053,13 +1056,6 @@ func (c *typeConv) FinishType(pos token.Pos) {
delete(c.ptrs, dtype)
}
}

// Now that pointer types are completed, we can invoke godefsFields
// to rewrite struct definitions.
for _, fld := range c.todoFlds {
godefsFields(fld)
}
c.todoFlds = nil
}

// Type returns a *Type with the same memory layout as
Expand Down Expand Up @@ -1209,9 +1205,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
case *dwarf.PtrType:
t.Align = c.ptrSize

// Translate void* as unsafe.Pointer
if _, ok := base(dt.Type).(*dwarf.VoidType); ok {
t.Go = c.unsafePointer
t.Go = c.goVoidPtr
t.C.Set("void*")
break
}
Expand Down Expand Up @@ -1656,7 +1651,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
csyntax = buf.String()

if *godefs || *cdefs {
c.todoFlds = append(c.todoFlds, fld)
godefsFields(fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
return
Expand Down Expand Up @@ -1694,19 +1689,6 @@ func godefsFields(fld []*ast.Field) {
n.Name = upper(n.Name)
}
}
p := &f.Type
t := *p
if star, ok := t.(*ast.StarExpr); ok {
star = &ast.StarExpr{X: star.X}
*p = star
p = &star.X
t = *p
}
if id, ok := t.(*ast.Ident); ok {
if id.Name == "unsafe.Pointer" {
*p = ast.NewIdent("*byte")
}
}
}
}

Expand Down

0 comments on commit e6f18b7

Please sign in to comment.