aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/syntax/parser.go36
-rw-r--r--src/cmd/compile/internal/types2/expr.go5
-rw-r--r--src/cmd/compile/internal/types2/signature.go2
-rw-r--r--src/cmd/compile/internal/types2/typexpr.go6
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)