diff options
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/syntax/parser.go | 36 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/expr.go | 5 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/signature.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/typexpr.go | 6 |
4 files changed, 32 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 14a737c414..8278685943 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -650,7 +650,7 @@ func (p *parser) typeDecl(group *Group) Decl { // d.Name "[" pname ... // d.Name "[" pname ptype ... // d.Name "[" pname ptype "," ... - d.TParamList = p.paramList(pname, ptype, _Rbrack, true) // ptype may be nil + d.TParamList = p.paramList(pname, ptype, _Rbrack, true, false) // ptype may be nil d.Alias = p.gotAssign() d.Type = p.typeOrNil() } else { @@ -800,7 +800,7 @@ func (p *parser) funcDeclOrNil() *FuncDecl { var context string if p.got(_Lparen) { context = "method" - rcvr := p.paramList(nil, nil, _Rparen, false) + rcvr := p.paramList(nil, nil, _Rparen, false, false) switch len(rcvr) { case 0: p.error("method has no receiver") @@ -1469,12 +1469,12 @@ func (p *parser) funcType(context string) ([]*Field, *FuncType) { p.syntaxError("empty type parameter list") p.next() } else { - tparamList = p.paramList(nil, nil, _Rbrack, true) + tparamList = p.paramList(nil, nil, _Rbrack, true, false) } } p.want(_Lparen) - typ.ParamList = p.paramList(nil, nil, _Rparen, false) + typ.ParamList = p.paramList(nil, nil, _Rparen, false, true) typ.ResultList = p.funcResult() return tparamList, typ @@ -1582,7 +1582,7 @@ func (p *parser) funcResult() []*Field { } if p.got(_Lparen) { - return p.paramList(nil, nil, _Rparen, false) + return p.paramList(nil, nil, _Rparen, false, false) } pos := p.pos() @@ -1793,7 +1793,7 @@ func (p *parser) methodDecl() *Field { // A type argument list looks like a parameter list with only // types. Parse a parameter list and decide afterwards. - list := p.paramList(nil, nil, _Rbrack, false) + list := p.paramList(nil, nil, _Rbrack, false, false) if len(list) == 0 { // The type parameter list is not [] but we got nothing // due to other errors (reported by paramList). Treat @@ -1962,10 +1962,11 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { p.next() t.Elem = p.typeOrNil() if t.Elem == nil { - t.Elem = p.badExpr() + f.Type = p.badExpr() p.syntaxError("... is missing type") + } else { + f.Type = t } - f.Type = t return f } @@ -1995,7 +1996,7 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field { // If name != nil, it is the first name after "(" or "[". // If typ != nil, name must be != nil, and (name, typ) is the first field in the list. // In the result list, either all fields have a name, or no field has a name. -func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool) (list []*Field) { +func (p *parser) paramList(name *Name, typ Expr, close token, requireNames, dddok bool) (list []*Field) { if trace { defer p.trace("paramList")() } @@ -2109,6 +2110,23 @@ func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool) } } + // check use of ... + first := true // only report first occurrence + for i, f := range list { + if t, _ := f.Type.(*DotsType); t != nil && (!dddok || i+1 < len(list)) { + if first { + first = false + if dddok { + p.errorAt(t.pos, "can only use ... with final parameter") + } else { + p.errorAt(t.pos, "invalid use of ...") + } + } + // use T instead of invalid ...T + f.Type = t.Elem + } + } + return } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 2bf42d1c6f..28a5d78872 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1016,9 +1016,8 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty check.ident(x, e, nil, false) case *syntax.DotsType: - // dots are handled explicitly where they are legal - // (array composite literals and parameter lists) - check.error(e, BadDotDotDotSyntax, "invalid use of '...'") + // dots are handled explicitly where they are valid + check.error(e, InvalidSyntaxTree, "invalid use of ...") goto Error case *syntax.BasicLit: diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index de4f1eaa20..622eb1383d 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -344,7 +344,7 @@ func (check *Checker) collectParams(list []*syntax.Field, variadicOk bool) (name if variadicOk && i == len(list)-1 { variadic = true } else { - check.softErrorf(t, MisplacedDotDotDot, "can only use ... with final parameter in list") + check.error(t, InvalidSyntaxTree, "invalid use of ...") // ignore ... and continue } } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e9b5ca9aa6..0964c53fe0 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -321,10 +321,8 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) { return typ case *syntax.DotsType: - // dots are handled explicitly where they are legal - // (array composite literals and parameter lists) - check.error(e, InvalidDotDotDot, "invalid use of '...'") - check.use(e.Elem) + // dots are handled explicitly where they are valid + check.error(e, InvalidSyntaxTree, "invalid use of ...") case *syntax.StructType: typ := new(Struct) |
