]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add Type.WidthCalculated
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 23 Mar 2017 18:29:37 +0000 (11:29 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 28 Mar 2017 18:06:09 +0000 (18:06 +0000)
Prior to this CL, Type.Width != 0 was the mark
of a Type whose Width had been calculated.
As a result, dowidth always recalculated
the width of struct{}.
This, combined with the prohibition on calculating
the width of a FuncArgsStruct and the use of
struct{} as a function argument,
meant that there were circumstances in which
it was forbidden to call dowidth on a type.
This inhibits refactoring to call dowidth automatically,
rather than explicitly.
Instead add a helper method, Type.WidthCalculated,
and implement as Type.Align > 0.
Type.Width is not a good candidate for tracking
whether the width has been calculated;
0 is a value type width, and Width is subject to
too much magic value game-playing.

For good measure, add a test for #11354.

Change-Id: Ie9a9fb5d924e7a2010c1904ae5e38ed4a38eaeb2
Reviewed-on: https://go-review.googlesource.com/38468
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/type.go
test/fixedbugs/issue11354.go [new file with mode: 0644]

index 10d86f5fdbd31b09771413d59b3b41157241d180..935e012194f6a552510e7f4297a52dc7728d619e 100644 (file)
@@ -159,14 +159,6 @@ func dowidth(t *Type) {
                return
        }
 
-       if t.Width > 0 {
-               if t.Align == 0 {
-                       // See issue 11354
-                       Fatalf("zero alignment with nonzero size %v", t)
-               }
-               return
-       }
-
        if t.Width == -2 {
                if !t.Broke() {
                        t.SetBroke(true)
@@ -177,6 +169,10 @@ func dowidth(t *Type) {
                return
        }
 
+       if t.WidthCalculated() {
+               return
+       }
+
        // break infinite recursion if the broken recursive type
        // is referenced again
        if t.Broke() && t.Width == 0 {
@@ -266,7 +262,7 @@ func dowidth(t *Type) {
                if t1.Elem().Width >= 1<<16 {
                        yyerror("channel element type too large (>64kB)")
                }
-               t.Width = 1
+               w = 1 // anything will do
 
        case TMAP: // implemented as pointer
                w = int64(Widthptr)
@@ -353,7 +349,7 @@ func dowidth(t *Type) {
 
        t.Width = w
        if t.Align == 0 {
-               if w > 8 || w&(w-1) != 0 {
+               if w > 8 || w&(w-1) != 0 || w == 0 {
                        Fatalf("invalid alignment for %v", t)
                }
                t.Align = uint8(w)
index 49d222507bf11f9328c4e864cda3dcd7e9a98dac..476a80b1b9d84233fbd9dc6377b63af7fdac1ace 100644 (file)
@@ -891,6 +891,10 @@ func (t *Type) isDDDArray() bool {
        return t.Extra.(*ArrayType).Bound < 0
 }
 
+func (t *Type) WidthCalculated() bool {
+       return t.Align > 0
+}
+
 // ArgWidth returns the total aligned argument size for a function.
 // It includes the receiver, parameters, and results.
 func (t *Type) ArgWidth() int64 {
diff --git a/test/fixedbugs/issue11354.go b/test/fixedbugs/issue11354.go
new file mode 100644 (file)
index 0000000..3980e8f
--- /dev/null
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type X int
+
+var foo = map[int]X{}
+
+var bar = map[int][8]X{}
+
+func main() {}