]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: avoid worklist nondeterminism.
authorAlan Donovan <adonovan@google.com>
Thu, 30 Oct 2014 18:01:14 +0000 (14:01 -0400)
committerAlan Donovan <adonovan@google.com>
Thu, 30 Oct 2014 18:01:14 +0000 (14:01 -0400)
+ Regression test.

Fixes #9026.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/162490043

misc/cgo/test/cgo_test.go
misc/cgo/test/issue9026.go [new file with mode: 0644]
src/cmd/cgo/gcc.go

index 3b289ba7b505392d29bb795e88e79a83e0d3ee55..fbdfac87acb8ef69be9e4fe295c4ba7373a6550f 100644 (file)
@@ -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) }
diff --git a/misc/cgo/test/issue9026.go b/misc/cgo/test/issue9026.go
new file mode 100644 (file)
index 0000000..b174404
--- /dev/null
@@ -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)
+       }
+}
index d77d56c22abc8c3b4a1b59259e0dbc5ba59ec996..abdd369d7139c1e522e3631505e64076bb80038d 100644 (file)
@@ -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: