Skip to content

Commit fb8c896

Browse files
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent dc4a815 commit fb8c896

File tree

4 files changed

+53
-24
lines changed

4 files changed

+53
-24
lines changed

misc/cgo/test/cgo_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,5 +74,6 @@ func Test8756(t *testing.T) { test8756(t) }
7474
func Test17065(t *testing.T) { test17065(t) }
7575
func TestThreadLock(t *testing.T) { testThreadLockFunc(t) }
7676
func TestCheckConst(t *testing.T) { testCheckConst(t) }
77+
func Test17537(t *testing.T) { test17537(t) }
7778

7879
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

misc/cgo/test/issue17537.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Issue 17537. The void* cast introduced by cgo to avoid problems
6+
// with const/volatile qualifiers breaks C preprocessor macros that
7+
// emulate functions.
8+
9+
package cgotest
10+
11+
/*
12+
#include <stdlib.h>
13+
14+
typedef struct {
15+
int i;
16+
} S17537;
17+
18+
int I17537(S17537 *p);
19+
20+
#define I17537(p) ((p)->i)
21+
22+
// Calling this function used to fail without the cast.
23+
int F17537(const char **p) {
24+
return **p;
25+
}
26+
*/
27+
import "C"
28+
29+
import "testing"
30+
31+
func test17537(t *testing.T) {
32+
v := C.S17537{i: 17537}
33+
if got, want := C.I17537(&v), C.int(17537); got != want {
34+
t.Errorf("got %d, want %d", got, want)
35+
}
36+
37+
p := (*C.char)(C.malloc(1))
38+
*p = 17
39+
if got, want := C.F17537(&p), C.int(17); got != want {
40+
t.Errorf("got %d, want %d", got, want)
41+
}
42+
}

src/cmd/cgo/gcc.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -1702,9 +1702,13 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
17021702
c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
17031703

17041704
case *dwarf.QualType:
1705-
// Ignore qualifier.
1706-
t = c.Type(dt.Type, pos)
1707-
c.m[dtype] = t
1705+
t1 := c.Type(dt.Type, pos)
1706+
t.Size = t1.Size
1707+
t.Align = t1.Align
1708+
t.Go = t1.Go
1709+
t.EnumValues = nil
1710+
t.Typedef = ""
1711+
t.C.Set("%s "+dt.Qual, t1.C)
17081712
return t
17091713

17101714
case *dwarf.StructType:

src/cmd/cgo/out.go

+3-21
Original file line numberDiff line numberDiff line change
@@ -355,11 +355,7 @@ func (p *Package) structType(n *Name) (string, int64) {
355355
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
356356
off += pad
357357
}
358-
qual := ""
359-
if c := t.C.String(); c[len(c)-1] == '*' {
360-
qual = "const "
361-
}
362-
fmt.Fprintf(&buf, "\t\t%s%s r;\n", qual, t.C)
358+
fmt.Fprintf(&buf, "\t\t%s r;\n", t.C)
363359
off += t.Size
364360
}
365361
if off%p.PtrSize != 0 {
@@ -620,20 +616,10 @@ func (p *Package) writeOutputFunc(fgcc *os.File, n *Name) {
620616
}
621617
}
622618
fmt.Fprintf(fgcc, "%s(", n.C)
623-
for i, t := range n.FuncType.Params {
619+
for i := range n.FuncType.Params {
624620
if i > 0 {
625621
fmt.Fprintf(fgcc, ", ")
626622
}
627-
// We know the type params are correct, because
628-
// the Go equivalents had good type params.
629-
// However, our version of the type omits the magic
630-
// words const and volatile, which can provoke
631-
// C compiler warnings. Silence them by casting
632-
// all pointers to void*. (Eventually that will produce
633-
// other warnings.)
634-
if c := t.C.String(); c[len(c)-1] == '*' {
635-
fmt.Fprintf(fgcc, "(void*)")
636-
}
637623
fmt.Fprintf(fgcc, "a->p%d", i)
638624
}
639625
fmt.Fprintf(fgcc, ");\n")
@@ -693,14 +679,10 @@ func (p *Package) writeGccgoOutputFunc(fgcc *os.File, n *Name) {
693679
}
694680
}
695681
fmt.Fprintf(fgcc, "%s(", n.C)
696-
for i, t := range n.FuncType.Params {
682+
for i := range n.FuncType.Params {
697683
if i > 0 {
698684
fmt.Fprintf(fgcc, ", ")
699685
}
700-
// Cast to void* to avoid warnings due to omitted qualifiers.
701-
if c := t.C.String(); c[len(c)-1] == '*' {
702-
fmt.Fprintf(fgcc, "(void*)")
703-
}
704686
fmt.Fprintf(fgcc, "p%d", i)
705687
}
706688
fmt.Fprintf(fgcc, ");\n")

0 commit comments

Comments
 (0)