Skip to content

Commit a265c2c

Browse files
committed
cmd/cgo, misc/cgo: only cache anonymous struct typedefs with parent name
CL 181857 broke the translation of certain C types using cmd/cgo -godefs because it stores each typedef, array and qualified type with their parent type name in the translation cache. Fix this by only considering the parent type for typedefs of anonymous structs which is the only case where types might become ambiguous. Updates #31891 Fixes #37479 Fixes #37621 Change-Id: I301a749ec89585789cb0d213593bb8b7341beb88 Reviewed-on: https://go-review.googlesource.com/c/go/+/226341 Run-TryBot: Tobias Klauser <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 3ee782b commit a265c2c

File tree

5 files changed

+82
-3
lines changed

5 files changed

+82
-3
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2020 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+
// +build ignore
6+
7+
package main
8+
9+
/*
10+
typedef struct A A;
11+
12+
typedef struct {
13+
struct A *next;
14+
struct A **prev;
15+
} N;
16+
17+
struct A
18+
{
19+
N n;
20+
};
21+
22+
typedef struct B
23+
{
24+
A* a;
25+
} B;
26+
*/
27+
import "C"
28+
29+
type N C.N
30+
31+
type A C.A
32+
33+
type B C.B
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2020 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+
// +build ignore
6+
7+
package main
8+
9+
/*
10+
struct tt {
11+
long long a;
12+
long long b;
13+
};
14+
15+
struct s {
16+
struct tt ts[3];
17+
};
18+
*/
19+
import "C"
20+
21+
type TT C.struct_tt
22+
23+
type S C.struct_s

misc/cgo/testgodefs/testdata/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,13 @@ var v2 = v1.L
1111
// Test that P, Q, and R all point to byte.
1212
var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)}
1313

14+
// Test that N, A and B are fully defined
15+
var v4 = N{}
16+
var v5 = A{}
17+
var v6 = B{}
18+
19+
// Test that S is fully defined
20+
var v7 = S{}
21+
1422
func main() {
1523
}

misc/cgo/testgodefs/testgodefs_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ var filePrefixes = []string{
2121
"anonunion",
2222
"issue8478",
2323
"fieldtypedef",
24+
"issue37479",
25+
"issue37621",
2426
}
2527

2628
func TestGoDefs(t *testing.T) {

src/cmd/cgo/gcc.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
22432243
// Translate to zero-length array instead.
22442244
count = 0
22452245
}
2246-
sub := c.loadType(dt.Type, pos, key)
2246+
sub := c.Type(dt.Type, pos)
22472247
t.Align = sub.Align
22482248
t.Go = &ast.ArrayType{
22492249
Len: c.intExpr(count),
@@ -2388,7 +2388,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
23882388
c.ptrs[key] = append(c.ptrs[key], t)
23892389

23902390
case *dwarf.QualType:
2391-
t1 := c.loadType(dt.Type, pos, key)
2391+
t1 := c.Type(dt.Type, pos)
23922392
t.Size = t1.Size
23932393
t.Align = t1.Align
23942394
t.Go = t1.Go
@@ -2472,7 +2472,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
24722472
}
24732473
name := c.Ident("_Ctype_" + dt.Name)
24742474
goIdent[name.Name] = name
2475-
sub := c.loadType(dt.Type, pos, key)
2475+
akey := ""
2476+
if c.anonymousStructTypedef(dt) {
2477+
// only load type recursively for typedefs of anonymous
2478+
// structs, see issues 37479 and 37621.
2479+
akey = key
2480+
}
2481+
sub := c.loadType(dt.Type, pos, akey)
24762482
if c.badPointerTypedef(dt) {
24772483
// Treat this typedef as a uintptr.
24782484
s := *sub
@@ -2993,6 +2999,13 @@ func fieldPrefix(fld []*ast.Field) string {
29932999
return prefix
29943000
}
29953001

3002+
// anonymousStructTypedef reports whether dt is a C typedef for an anonymous
3003+
// struct.
3004+
func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
3005+
st, ok := dt.Type.(*dwarf.StructType)
3006+
return ok && st.StructName == ""
3007+
}
3008+
29963009
// badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
29973010
// A typedef is bad if C code sometimes stores non-pointers in this type.
29983011
// TODO: Currently our best solution is to find these manually and list them as

0 commit comments

Comments
 (0)