]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: don't ignore qualifiers, don't cast to void*
authorIan Lance Taylor <iant@golang.org>
Thu, 10 Nov 2016 22:34:32 +0000 (14:34 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 11 Nov 2016 01:31:12 +0000 (01:31 +0000)
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 <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
misc/cgo/test/cgo_test.go
misc/cgo/test/issue17537.go [new file with mode: 0644]
src/cmd/cgo/gcc.go
src/cmd/cgo/out.go

index 7bfb38d10e80098c1b6bce537cf961a0272eba87..2f591377aee87755cd59dc0e73e60df49afa4b21 100644 (file)
@@ -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 (file)
index 0000000..a1558bc
--- /dev/null
@@ -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 <stdlib.h>
+
+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)
+       }
+}
index 8fd490ce95c8bd62fb3d16f9072b8ea655b59179..812e315eaf6520621e12ff21f08cdfbc0b6f4739 100644 (file)
@@ -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:
index 1940f9176c87e34cb2b72ac4a498fe2f949f8c73..e82ec375a274510a6f0d120b5b59e0a6daa59f19 100644 (file)
@@ -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")