From: Ian Lance Taylor Date: Thu, 10 Nov 2016 22:34:32 +0000 (-0800) Subject: cmd/cgo: don't ignore qualifiers, don't cast to void* X-Git-Tag: go1.8beta1~214 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fb8c896aff9549e868df58f9d40fd06b67ae7d07;p=gostls13.git cmd/cgo: don't ignore qualifiers, don't cast to void* The cgo tool used to simply ignore C type qualifiers. To avoid problems when a C function expected a qualifier that was not present, cgo emitted a cast to void* around all pointer arguments. Unfortunately, that broke code that contains both a function declaration and a macro, when the macro required the argument to have the right type. To fix this problem, don't ignore qualifiers. They are easy enough to handle for the limited set of cases that matter for cgo, in which we don't care about array or function types. Fixes #17537. Change-Id: Ie2988d21db6ee016a3e99b07f53cfb0f1243a020 Reviewed-on: https://go-review.googlesource.com/33097 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Russ Cox --- 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")