mirror of
https://github.com/golang/go
synced 2024-11-27 02:51:24 -07:00
cmd/cgo: avoid worklist nondeterminism.
+ Regression test. Fixes #9026. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/162490043
This commit is contained in:
parent
f21a02a179
commit
09f6f05c1f
@ -62,5 +62,6 @@ func Test8517(t *testing.T) { test8517(t) }
|
||||
func Test8811(t *testing.T) { test8811(t) }
|
||||
func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) }
|
||||
func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
|
||||
func Test9026(t *testing.T) { test9026(t) }
|
||||
|
||||
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
|
||||
|
33
misc/cgo/test/issue9026.go
Normal file
33
misc/cgo/test/issue9026.go
Normal file
@ -0,0 +1,33 @@
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
typedef struct {} git_merge_file_input;
|
||||
|
||||
typedef struct {} git_merge_file_options;
|
||||
|
||||
int git_merge_file(
|
||||
git_merge_file_input *in,
|
||||
git_merge_file_options *opts) {}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func test9026(t *testing.T) {
|
||||
var in C.git_merge_file_input
|
||||
var opts *C.git_merge_file_options
|
||||
C.git_merge_file(&in, opts)
|
||||
|
||||
// Test that the generated type names are deterministic.
|
||||
// (Previously this would fail about 10% of the time.)
|
||||
//
|
||||
// Brittle: the assertion may fail spuriously when the algorithm
|
||||
// changes, but should remain stable otherwise.
|
||||
got := fmt.Sprintf("%T %T", in, opts)
|
||||
want := "cgotest._Ctype_struct___12 *cgotest._Ctype_struct___13"
|
||||
if got != want {
|
||||
t.Errorf("Non-deterministic type names: got %s, want %s", got, want)
|
||||
}
|
||||
}
|
@ -944,6 +944,8 @@ type typeConv struct {
|
||||
|
||||
// Map from types to incomplete pointers to those types.
|
||||
ptrs map[dwarf.Type][]*Type
|
||||
// Keys of ptrs in insertion order (deterministic worklist)
|
||||
ptrKeys []dwarf.Type
|
||||
|
||||
// Predeclared types.
|
||||
bool ast.Expr
|
||||
@ -1061,16 +1063,17 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
|
||||
func (c *typeConv) FinishType(pos token.Pos) {
|
||||
// Completing one pointer type might produce more to complete.
|
||||
// Keep looping until they're all done.
|
||||
for len(c.ptrs) > 0 {
|
||||
for dtype := range c.ptrs {
|
||||
// Note Type might invalidate c.ptrs[dtype].
|
||||
t := c.Type(dtype, pos)
|
||||
for _, ptr := range c.ptrs[dtype] {
|
||||
ptr.Go.(*ast.StarExpr).X = t.Go
|
||||
ptr.C.Set("%s*", t.C)
|
||||
}
|
||||
delete(c.ptrs, dtype)
|
||||
for len(c.ptrKeys) > 0 {
|
||||
dtype := c.ptrKeys[0]
|
||||
c.ptrKeys = c.ptrKeys[1:]
|
||||
|
||||
// Note Type might invalidate c.ptrs[dtype].
|
||||
t := c.Type(dtype, pos)
|
||||
for _, ptr := range c.ptrs[dtype] {
|
||||
ptr.Go.(*ast.StarExpr).X = t.Go
|
||||
ptr.C.Set("%s*", t.C)
|
||||
}
|
||||
c.ptrs[dtype] = nil // retain the map key
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,6 +1240,9 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
||||
// Placeholder initialization; completed in FinishType.
|
||||
t.Go = &ast.StarExpr{}
|
||||
t.C.Set("<incomplete>*")
|
||||
if _, ok := c.ptrs[dt.Type]; !ok {
|
||||
c.ptrKeys = append(c.ptrKeys, dt.Type)
|
||||
}
|
||||
c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
|
||||
|
||||
case *dwarf.QualType:
|
||||
|
Loading…
Reference in New Issue
Block a user