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 <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Tobias Klauser 2020-03-30 00:38:09 +02:00 committed by Tobias Klauser
parent 3ee782b11d
commit a265c2c448
5 changed files with 82 additions and 3 deletions

View file

@ -2243,7 +2243,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
// Translate to zero-length array instead.
count = 0
}
sub := c.loadType(dt.Type, pos, key)
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
t.Go = &ast.ArrayType{
Len: c.intExpr(count),
@ -2388,7 +2388,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
c.ptrs[key] = append(c.ptrs[key], t)
case *dwarf.QualType:
t1 := c.loadType(dt.Type, pos, key)
t1 := c.Type(dt.Type, pos)
t.Size = t1.Size
t.Align = t1.Align
t.Go = t1.Go
@ -2472,7 +2472,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
}
name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name
sub := c.loadType(dt.Type, pos, key)
akey := ""
if c.anonymousStructTypedef(dt) {
// only load type recursively for typedefs of anonymous
// structs, see issues 37479 and 37621.
akey = key
}
sub := c.loadType(dt.Type, pos, akey)
if c.badPointerTypedef(dt) {
// Treat this typedef as a uintptr.
s := *sub
@ -2993,6 +2999,13 @@ func fieldPrefix(fld []*ast.Field) string {
return prefix
}
// anonymousStructTypedef reports whether dt is a C typedef for an anonymous
// struct.
func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
st, ok := dt.Type.(*dwarf.StructType)
return ok && st.StructName == ""
}
// badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
// A typedef is bad if C code sometimes stores non-pointers in this type.
// TODO: Currently our best solution is to find these manually and list them as