diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index 7bfb38d10e..2f591377ae 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -74,5 +74,6 @@ func Test8756(t *testing.T) { test8756(t) } func Test17065(t *testing.T) { test17065(t) } func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } func TestCheckConst(t *testing.T) { testCheckConst(t) } +func Test17537(t *testing.T) { test17537(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } diff --git a/misc/cgo/test/issue17537.go b/misc/cgo/test/issue17537.go new file mode 100644 index 0000000000..a1558bc5ed --- /dev/null +++ b/misc/cgo/test/issue17537.go @@ -0,0 +1,42 @@ +// Copyright 2016 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 17537. The void* cast introduced by cgo to avoid problems +// with const/volatile qualifiers breaks C preprocessor macros that +// emulate functions. + +package cgotest + +/* +#include + +typedef struct { + int i; +} S17537; + +int I17537(S17537 *p); + +#define I17537(p) ((p)->i) + +// Calling this function used to fail without the cast. +int F17537(const char **p) { + return **p; +} +*/ +import "C" + +import "testing" + +func test17537(t *testing.T) { + v := C.S17537{i: 17537} + if got, want := C.I17537(&v), C.int(17537); got != want { + t.Errorf("got %d, want %d", got, want) + } + + p := (*C.char)(C.malloc(1)) + *p = 17 + if got, want := C.F17537(&p), C.int(17); got != want { + t.Errorf("got %d, want %d", got, want) + } +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 8fd490ce95..812e315eaf 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1702,9 +1702,13 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t) case *dwarf.QualType: - // Ignore qualifier. - t = c.Type(dt.Type, pos) - c.m[dtype] = t + t1 := c.Type(dt.Type, pos) + t.Size = t1.Size + t.Align = t1.Align + t.Go = t1.Go + t.EnumValues = nil + t.Typedef = "" + t.C.Set("%s "+dt.Qual, t1.C) return t case *dwarf.StructType: diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 1940f9176c..e82ec375a2 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -355,11 +355,7 @@ func (p *Package) structType(n *Name) (string, int64) { fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad) off += pad } - qual := "" - if c := t.C.String(); c[len(c)-1] == '*' { - qual = "const " - } - fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C) + fmt.Fprintf(&buf, "\t\t%s r;\n", t.C) off += t.Size } if off%p.PtrSize != 0 { @@ -620,20 +616,10 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) { } } fmt.Fprintf(fgcc, "%s(", n.C) - for i, t := range n.FuncType.Params { + for i := range n.FuncType.Params { if i > 0 { fmt.Fprintf(fgcc, ", ") } - // We know the type params are correct, because - // the Go equivalents had good type params. - // However, our version of the type omits the magic - // words const and volatile, which can provoke - // C compiler warnings. Silence them by casting - // all pointers to void*. (Eventually that will produce - // other warnings.) - if c := t.C.String(); c[len(c)-1] == '*' { - fmt.Fprintf(fgcc, "(void*)") - } fmt.Fprintf(fgcc, "a->p%d", i) } fmt.Fprintf(fgcc, ");\n") @@ -693,14 +679,10 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) { } } fmt.Fprintf(fgcc, "%s(", n.C) - for i, t := range n.FuncType.Params { + for i := range n.FuncType.Params { if i > 0 { fmt.Fprintf(fgcc, ", ") } - // Cast to void* to avoid warnings due to omitted qualifiers. - if c := t.C.String(); c[len(c)-1] == '*' { - fmt.Fprintf(fgcc, "(void*)") - } fmt.Fprintf(fgcc, "p%d", i) } fmt.Fprintf(fgcc, ");\n")