Skip to content

Commit e13a4d9

Browse files
letientai299ianlancetaylor
authored andcommitted
cmd/cgo: build unique C type cache keys from parent names
When translating C types, cache the in-progress type under its parent names, so that anonymous structs can also be translated for multiple typedefs, without clashing. Standalone types are not affected by this change. Also updated the test for issue 9026 because the C struct name generation algorithm has changed. Fixes #31891 Change-Id: I00cc64852a2617ce33da13f74caec886af05b9f2 Reviewed-on: https://go-review.googlesource.com/c/go/+/181857 Run-TryBot: Tobias Klauser <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 5f4aa5d commit e13a4d9

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

misc/cgo/test/cgo_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ func Test27660(t *testing.T) { test27660(t) }
5858
func Test28896(t *testing.T) { test28896(t) }
5959
func Test30065(t *testing.T) { test30065(t) }
6060
func Test32579(t *testing.T) { test32579(t) }
61+
func Test31891(t *testing.T) { test31891(t) }
6162
func TestAlign(t *testing.T) { testAlign(t) }
6263
func TestAtol(t *testing.T) { testAtol(t) }
6364
func TestBlocking(t *testing.T) { testBlocking(t) }

misc/cgo/test/issue31891.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2019 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+
#include "_cgo_export.h"
6+
7+
void callIssue31891() {
8+
Issue31891A a;
9+
useIssue31891A(&a);
10+
11+
Issue31891B b;
12+
useIssue31891B(&b);
13+
}

misc/cgo/test/testdata/issue9026/issue9026.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func Test(t *testing.T) {
2929
// Brittle: the assertion may fail spuriously when the algorithm
3030
// changes, but should remain stable otherwise.
3131
got := fmt.Sprintf("%T %T", in, opts)
32-
want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___0"
32+
want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1"
3333
if got != want {
3434
t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
3535
}

misc/cgo/test/testx.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ void callMulti(void);
108108
// issue 28772 part 2 - part 1 in issuex.go
109109
#define issue28772Constant2 2
110110
111+
112+
// issue 31891
113+
typedef struct {
114+
long obj;
115+
} Issue31891A;
116+
117+
typedef struct {
118+
long obj;
119+
} Issue31891B;
120+
121+
void callIssue31891(void);
111122
*/
112123
import "C"
113124

@@ -517,3 +528,15 @@ func test20910(t *testing.T) {
517528
// issue 28772 part 2
518529

519530
const issue28772Constant2 = C.issue28772Constant2
531+
532+
// issue 31891
533+
534+
//export useIssue31891A
535+
func useIssue31891A(c *C.Issue31891A) {}
536+
537+
//export useIssue31891B
538+
func useIssue31891B(c *C.Issue31891B) {}
539+
540+
func test31891(t *testing.T) {
541+
C.callIssue31891()
542+
}

src/cmd/cgo/gcc.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,14 +2189,21 @@ func (c *typeConv) FinishType(pos token.Pos) {
21892189
// Type returns a *Type with the same memory layout as
21902190
// dtype when used as the type of a variable or a struct field.
21912191
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
2192+
return c.loadType(dtype, pos, "")
2193+
}
2194+
2195+
// loadType recursively loads the requested dtype and its dependency graph.
2196+
func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Type {
21922197
// Always recompute bad pointer typedefs, as the set of such
21932198
// typedefs changes as we see more types.
21942199
checkCache := true
21952200
if dtt, ok := dtype.(*dwarf.TypedefType); ok && c.badPointerTypedef(dtt) {
21962201
checkCache = false
21972202
}
21982203

2199-
key := dtype.String()
2204+
// The cache key should be relative to its parent.
2205+
// See issue https://golang.org/issue/31891
2206+
key := parent + " > " + dtype.String()
22002207

22012208
if checkCache {
22022209
if t, ok := c.m[key]; ok {
@@ -2236,7 +2243,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
22362243
// Translate to zero-length array instead.
22372244
count = 0
22382245
}
2239-
sub := c.Type(dt.Type, pos)
2246+
sub := c.loadType(dt.Type, pos, key)
22402247
t.Align = sub.Align
22412248
t.Go = &ast.ArrayType{
22422249
Len: c.intExpr(count),
@@ -2381,7 +2388,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
23812388
c.ptrs[key] = append(c.ptrs[key], t)
23822389

23832390
case *dwarf.QualType:
2384-
t1 := c.Type(dt.Type, pos)
2391+
t1 := c.loadType(dt.Type, pos, key)
23852392
t.Size = t1.Size
23862393
t.Align = t1.Align
23872394
t.Go = t1.Go
@@ -2465,7 +2472,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
24652472
}
24662473
name := c.Ident("_Ctype_" + dt.Name)
24672474
goIdent[name.Name] = name
2468-
sub := c.Type(dt.Type, pos)
2475+
sub := c.loadType(dt.Type, pos, key)
24692476
if c.badPointerTypedef(dt) {
24702477
// Treat this typedef as a uintptr.
24712478
s := *sub

0 commit comments

Comments
 (0)