Skip to content

Commit 7388956

Browse files
committed
cmd/cgo: fix mangling of enum and union types
Consider this test package: package p // enum E { E0 }; // union U { long x; }; // void f(enum E e, union U* up) {} import "C" func f() { C.f(C.enum_E(C.E0), (*C.union_U)(nil)) } In Go 1.14, cgo translated this to (omitting irrelevant details): type _Ctype_union_U [8]byte func f() { _Cfunc_f(uint32(_Ciconst_E0), (*[8]byte)(nil)) } func _Cfunc_f(p0 uint32, p1 *[8]byte) (r1 _Ctype_void) { ... } Notably, _Ctype_union_U was declared as a defined type, but uses were being rewritten into uses of the underlying type, which matched how _Cfunc_f was declared. After CL 230037, cgo started consistently rewriting "C.foo" type expressions as "_Ctype_foo", which caused it to start emitting: type _Ctype_enum_E uint32 type _Ctype_union_U [8]byte func f() { _Cfunc_f(_Ctype_enum_E(_Ciconst_E0), (*_Ctype_union_U)(nil)) } // _Cfunc_f unchanged Of course, this fails to type-check because _Ctype_enum_E and _Ctype_union_U are defined types. This CL changes cgo to emit: type _Ctype_enum_E = uint32 type _Ctype_union_U = [8]byte // f unchanged since CL 230037 // _Cfunc_f still unchanged It would probably be better to fix this in (*typeConv).loadType so that cgo generated code uses the _Ctype_foo aliases too. But as it wouldn't have any effect on actual compilation, it's not worth the risk of touching it at this point in the release cycle. Updates #39537. Fixes #40494. Change-Id: I88269660b40aeda80a9a9433777601a781b48ac0 Reviewed-on: https://go-review.googlesource.com/c/go/+/246057 Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent b56791c commit 7388956

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

misc/cgo/test/test.go

+13
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,12 @@ typedef struct S32579 { unsigned char data[1]; } S32579;
901901
// issue 38649
902902
// Test that #define'd type aliases work.
903903
#define netbsd_gid unsigned int
904+
905+
// issue 40494
906+
// Inconsistent handling of tagged enum and union types.
907+
enum Enum40494 { X_40494 };
908+
union Union40494 { int x; };
909+
void issue40494(enum Enum40494 e, union Union40494* up) {}
904910
*/
905911
import "C"
906912

@@ -2204,3 +2210,10 @@ var issue38649 C.netbsd_gid = 42
22042210
// issue 39877
22052211

22062212
var issue39877 *C.void = nil
2213+
2214+
// issue 40494
2215+
// No runtime test; just make sure it compiles.
2216+
2217+
func Issue40494() {
2218+
C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
2219+
}

src/cmd/cgo/out.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ func (p *Package) writeDefs() {
123123
// Moreover, empty file name makes compile emit no source debug info at all.
124124
var buf bytes.Buffer
125125
noSourceConf.Fprint(&buf, fset, def.Go)
126-
if bytes.HasPrefix(buf.Bytes(), []byte("_Ctype_")) {
126+
if bytes.HasPrefix(buf.Bytes(), []byte("_Ctype_")) ||
127+
strings.HasPrefix(name, "_Ctype_enum_") ||
128+
strings.HasPrefix(name, "_Ctype_union_") {
127129
// This typedef is of the form `typedef a b` and should be an alias.
128130
fmt.Fprintf(fgo2, "= ")
129131
}

0 commit comments

Comments
 (0)