ctxCallee // call-only expressions are ok
ctxMultiOK // multivalue function returns are ok
ctxAssign // assigning to expression
- ctxCompLit // type in composite literal
)
// type checks the whole tree of an expression.
if n.Left == nil {
t = types.NewSlice(r.Type)
} else if n.Left.Op == ODDD {
- if top&ctxCompLit == 0 {
- if !n.Diag() {
- n.SetDiag(true)
- yyerror("use of [...] array outside of array literal")
- }
- n.Type = nil
- return n
+ if !n.Diag() {
+ n.SetDiag(true)
+ yyerror("use of [...] array outside of array literal")
}
- t = types.NewDDDArray(r.Type)
+ n.Type = nil
+ return n
} else {
n.Left = indexlit(typecheck(n.Left, ctxExpr))
l := n.Left
setTypeNode(n, t)
n.Left = nil
n.Right = nil
- if !t.IsDDDArray() {
- checkwidth(t)
- }
+ checkwidth(t)
case OTMAP:
ok |= ctxType
// type or expr
case ODEREF:
- n.Left = typecheck(n.Left, ctxExpr|ctxType|top&ctxCompLit)
+ n.Left = typecheck(n.Left, ctxExpr|ctxType)
l := n.Left
t := l.Type
if t == nil {
if l.Op == OTYPE {
ok |= ctxType
setTypeNode(n, types.NewPtr(l.Type))
- // Ensure l.Type gets dowidth'd for the backend. Issue 20174.
- // Don't checkwidth [...] arrays, though, since they
- // will be replaced by concrete-sized arrays. Issue 20333.
- if !l.Type.IsDDDArray() {
- checkwidth(l.Type)
- }
n.Left = nil
+ // Ensure l.Type gets dowidth'd for the backend. Issue 20174.
+ checkwidth(l.Type)
break
}
n.Left = defaultlit(n.Left, nil)
l = n.Left
if l.Op == OTYPE {
- if n.IsDDD() || l.Type.IsDDDArray() {
+ if n.IsDDD() {
if !l.Type.Broke() {
yyerror("invalid use of ... in type conversion to %v", l.Type)
}
}
// Save original node (including n.Right)
- norig := n.copy()
+ n.Orig = n.copy()
setlineno(n.Right)
- n.Right = typecheck(n.Right, ctxType|ctxCompLit)
- l := n.Right // sic
- t := l.Type
+
+ // Need to handle [...]T arrays specially.
+ if n.Right.Op == OTARRAY && n.Right.Left != nil && n.Right.Left.Op == ODDD {
+ n.Right.Right = typecheck(n.Right.Right, ctxType)
+ if n.Right.Right.Type == nil {
+ n.Type = nil
+ return n
+ }
+ elemType := n.Right.Right.Type
+
+ length := typecheckarraylit(elemType, -1, n.List.Slice())
+
+ n.Op = OARRAYLIT
+ n.Type = types.NewArray(elemType, length)
+ n.Right = nil
+ return n
+ }
+
+ n.Right = typecheck(n.Right, ctxType)
+ t := n.Right.Type
if t == nil {
n.Type = nil
return n
}
- nerr := nerrors
n.Type = t
switch t.Etype {
n.Type = nil
case TARRAY:
- if t.IsDDDArray() {
- length := typecheckarraylit(t.Elem(), -1, n.List.Slice())
- t.SetNumElem(length)
- } else {
- typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
- }
+ typecheckarraylit(t.Elem(), t.NumElem(), n.List.Slice())
n.Op = OARRAYLIT
n.Right = nil
n.Right = nil
}
- if nerr != nerrors {
- return n
- }
-
- n.Orig = norig
return n
}
return t
}
-// NewDDDArray returns a new [...]T array Type.
-func NewDDDArray(elem *Type) *Type {
- t := New(TARRAY)
- t.Extra = &Array{Elem: elem, Bound: -1}
- t.SetNotInHeap(elem.NotInHeap())
- return t
-}
-
// NewChan returns a new chan Type with direction dir.
func NewChan(elem *Type, dir ChanDir) *Type {
t := New(TCHAN)
t.Methods().Set(methods)
}
-func (t *Type) IsDDDArray() bool {
- if t.Etype != TARRAY {
- return false
- }
- return t.Extra.(*Array).Bound < 0
-}
-
func (t *Type) WidthCalculated() bool {
return t.Align > 0
}
func (t *Type) NumElem() int64 {
t.wantEtype(TARRAY)
- at := t.Extra.(*Array)
- if at.Bound < 0 {
- Fatalf("NumElem array %v does not have bound yet", t)
- }
- return at.Bound
-}
-
-// SetNumElem sets the number of elements in an array type.
-// The only allowed use is on array types created with NewDDDArray.
-// For other uses, create a new array with NewArray instead.
-func (t *Type) SetNumElem(n int64) {
- t.wantEtype(TARRAY)
- at := t.Extra.(*Array)
- if at.Bound >= 0 {
- Fatalf("SetNumElem array %v already has bound %d", t, at.Bound)
- }
- at.Bound = n
+ return t.Extra.(*Array).Bound
}
type componentsIncludeBlankFields bool