mirror of https://github.com/golang/go.git
cmd/compile: add Type.WidthCalculated
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>
This commit is contained in:
parent
f5c1926e93
commit
8dafdb1be1
|
|
@ -159,14 +159,6 @@ func dowidth(t *Type) {
|
||||||
return
|
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.Width == -2 {
|
||||||
if !t.Broke() {
|
if !t.Broke() {
|
||||||
t.SetBroke(true)
|
t.SetBroke(true)
|
||||||
|
|
@ -177,6 +169,10 @@ func dowidth(t *Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t.WidthCalculated() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// break infinite recursion if the broken recursive type
|
// break infinite recursion if the broken recursive type
|
||||||
// is referenced again
|
// is referenced again
|
||||||
if t.Broke() && t.Width == 0 {
|
if t.Broke() && t.Width == 0 {
|
||||||
|
|
@ -266,7 +262,7 @@ func dowidth(t *Type) {
|
||||||
if t1.Elem().Width >= 1<<16 {
|
if t1.Elem().Width >= 1<<16 {
|
||||||
yyerror("channel element type too large (>64kB)")
|
yyerror("channel element type too large (>64kB)")
|
||||||
}
|
}
|
||||||
t.Width = 1
|
w = 1 // anything will do
|
||||||
|
|
||||||
case TMAP: // implemented as pointer
|
case TMAP: // implemented as pointer
|
||||||
w = int64(Widthptr)
|
w = int64(Widthptr)
|
||||||
|
|
@ -353,7 +349,7 @@ func dowidth(t *Type) {
|
||||||
|
|
||||||
t.Width = w
|
t.Width = w
|
||||||
if t.Align == 0 {
|
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)
|
Fatalf("invalid alignment for %v", t)
|
||||||
}
|
}
|
||||||
t.Align = uint8(w)
|
t.Align = uint8(w)
|
||||||
|
|
|
||||||
|
|
@ -891,6 +891,10 @@ func (t *Type) isDDDArray() bool {
|
||||||
return t.Extra.(*ArrayType).Bound < 0
|
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.
|
// ArgWidth returns the total aligned argument size for a function.
|
||||||
// It includes the receiver, parameters, and results.
|
// It includes the receiver, parameters, and results.
|
||||||
func (t *Type) ArgWidth() int64 {
|
func (t *Type) ArgWidth() int64 {
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
||||||
Loading…
Reference in New Issue