aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/syntax')
-rw-r--r--src/cmd/compile/internal/syntax/parser.go36
1 files changed, 27 insertions, 9 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
}