return
}
- var t *types.Type
- if n.Right != nil {
- t = n.Right.Type
- } else {
- t = n.Left.Type
- }
-
// Evaluate RHS.
rhs := n.Right
if rhs != nil {
}
}
}
+
+ if isblank(n.Left) {
+ // _ = rhs
+ // Just evaluate rhs for side-effects.
+ if rhs != nil {
+ s.expr(rhs)
+ }
+ return
+ }
+
+ var t *types.Type
+ if n.Right != nil {
+ t = n.Right.Type
+ } else {
+ t = n.Left.Type
+ }
+
var r *ssa.Value
deref := !canSSAType(t)
if deref {
return v
}
- dowidth(from)
- dowidth(to)
+ from.AssertWidthCalculated()
+ to.AssertWidthCalculated()
if from.Width != to.Width {
s.Fatalf("CONVNOP width mismatch %v (%d) -> %v (%d)\n", from, from.Width, to, to.Width)
return nil
return
}
t := left.Type
- dowidth(t)
+ t.AssertWidthCalculated()
if s.canSSA(left) {
if deref {
s.Fatalf("can SSA LHS %v but not RHS %s", left, right)
}
rcvr = s.newValue1(ssa.OpIData, types.Types[TUINTPTR], i)
}
- dowidth(fn.Type)
+ fn.Type.AssertWidthCalculated()
stksize := fn.Type.ArgWidth() // includes receiver
// Run all argument assignments. The arg slots have already
// canSSA reports whether variables of type t are SSA-able.
func canSSAType(t *types.Type) bool {
- dowidth(t)
+ t.AssertWidthCalculated()
if t.Width > int64(4*Widthptr) {
// 4*Widthptr is an arbitrary constant. We want it
// to be at least 3*Widthptr so slices can be registerized.
n.Esc = EscNever
n.Name.Curfn = e.curfn
e.curfn.Func.Dcl = append(e.curfn.Func.Dcl, n)
-
- dowidth(t)
+ t.AssertWidthCalculated()
return n
}
continue
}
as[i] = assignconv(n, t.Elem(), "append")
+ checkwidth(as[i].Type) // ensure width is calculated for backend
}
}
case OCONV:
ok |= Erv
saveorignode(n)
+ checkwidth(n.Type) // ensure width is calculated for backend
n.Left = typecheck(n.Left, Erv)
n.Left = convlit1(n.Left, n.Type, true, noReuse)
t := n.Left.Type
if n.Left.Typecheck() == 0 {
n.Left = typecheck(n.Left, Erv|Easgn)
}
+ if !isblank(n.Left) {
+ checkwidth(n.Left.Type) // ensure width is calculated for backend
+ }
}
func checkassignto(src *types.Type, dst *Node) {
}
// paramstoheap returns code to allocate memory for heap-escaped parameters
-// and to copy non-result prameters' values from the stack.
+// and to copy non-result parameters' values from the stack.
func paramstoheap(params *types.Type) []*Node {
var nn []*Node
for _, t := range params.Fields().Slice() {
return t.Align > 0
}
+// AssertWidthCalculated calls Fatalf if t's width has not yet been calculated.
+func (t *Type) AssertWidthCalculated() {
+ if !t.WidthCalculated() {
+ Fatalf("width not calculated: %v", t)
+ }
+}
+
// ArgWidth returns the total aligned argument size for a function.
// It includes the receiver, parameters, and results.
func (t *Type) ArgWidth() int64 {
}
func (t *Type) Size() int64 {
- Dowidth(t)
+ t.AssertWidthCalculated()
return t.Width
}
func (t *Type) Alignment() int64 {
- Dowidth(t)
+ t.AssertWidthCalculated()
return int64(t.Align)
}
--- /dev/null
+// 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.
+
+// Issue 20145: some func types weren't dowidth-ed by the front end,
+// leading to races in the backend.
+
+package p
+
+func f() {
+ _ = (func())(nil)
+}