From: Robert Griesemer Date: Fri, 24 Mar 2017 18:43:08 +0000 (-0700) Subject: cmd/compile: be slightly more tolerant in case of certain syntax errors X-Git-Tag: go1.9beta1~988 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=5e954047bcb77b219629676db3e5d057bed48360;p=gostls13.git cmd/compile: be slightly more tolerant in case of certain syntax errors Avoid construction of incorrect syntax trees in presence of errors. For #19663. Change-Id: I43025a3cf0fe02cae9a57e8bb9489b5f628c3fd7 Reviewed-on: https://go-review.googlesource.com/38604 Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot Reviewed-by: Matthew Dempsky --- diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 77c6759fbb..3db049c85f 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -686,9 +686,9 @@ func structfield(n *Node) *Field { case string: f.Note = u default: - yyerror("field annotation must be string") + yyerror("field tag must be a string") case nil: - // noop + // no-op } if n.Left != nil && n.Left.Op == ONAME { diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 884790da1e..8e9004d6e9 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -748,7 +748,7 @@ func loadsys() { func importfile(f *Val, indent []byte) *Pkg { path_, ok := f.U.(string) if !ok { - yyerror("import statement not a string") + yyerror("import path must be a string") return nil } diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 39532689e2..b57146d83b 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -192,7 +192,7 @@ func (p *parser) advance(followlist ...token) { } // compute follow set - // TODO(gri) the args are constants - do as constant expressions? + // (not speed critical, advance is only called in error situations) var followset uint64 = 1 << _EOF // never skip over EOF for _, tok := range followlist { followset |= 1 << tok @@ -281,7 +281,7 @@ func (p *parser) file() *File { case _Func: p.next() - f.DeclList = append(f.DeclList, p.funcDecl()) + f.DeclList = appendDecl(f.DeclList, p.funcDecl()) default: if p.tok == _Lbrace && len(f.DeclList) > 0 && emptyFuncDecl(f.DeclList[len(f.DeclList)-1]) { @@ -323,7 +323,7 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl { if p.got(_Lparen) { g := new(Group) for p.tok != _EOF && p.tok != _Rparen { - list = append(list, f(g)) + list = appendDecl(list, f(g)) if !p.osemi(_Rparen) { break } @@ -332,7 +332,14 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl { return list } - return append(list, f(nil)) + return appendDecl(list, f(nil)) +} + +func appendDecl(list []Decl, d Decl) []Decl { + if d != nil { + return append(list, d) + } + return list } func (p *parser) importDecl(group *Group) Decl { @@ -353,11 +360,11 @@ func (p *parser) importDecl(group *Group) Decl { d.LocalPkgName = n p.next() } - if p.tok == _Literal && p.kind == StringLit { - d.Path = p.oliteral() - } else { - p.syntax_error("missing import path; require quoted string") + d.Path = p.oliteral() + if d.Path == nil { + p.syntax_error("missing import path") p.advance(_Semi, _Rparen) + return nil } d.Group = group @@ -400,6 +407,7 @@ func (p *parser) typeDecl(group *Group) Decl { if d.Type == nil { p.syntax_error("in type declaration") p.advance(_Semi, _Rparen) + return nil } d.Group = group d.Pragma = p.pragma @@ -443,18 +451,16 @@ func (p *parser) funcDecl() *FuncDecl { f := new(FuncDecl) f.pos = p.pos() - badRecv := false if p.tok == _Lparen { rcvr := p.paramList() switch len(rcvr) { case 0: p.error("method has no receiver") - badRecv = true - case 1: - f.Recv = rcvr[0] default: p.error("method has multiple receivers") - badRecv = true + fallthrough + case 1: + f.Recv = rcvr[0] } } @@ -491,9 +497,6 @@ func (p *parser) funcDecl() *FuncDecl { // p.error("can only use //go:noescape with external func implementations") // } - if badRecv { - return nil // TODO(gri) better solution - } return f } diff --git a/src/cmd/compile/internal/syntax/syntax.go b/src/cmd/compile/internal/syntax/syntax.go index db2bcb4a0c..25fafcf077 100644 --- a/src/cmd/compile/internal/syntax/syntax.go +++ b/src/cmd/compile/internal/syntax/syntax.go @@ -40,8 +40,9 @@ type Pragma uint16 type PragmaHandler func(pos src.Pos, text string) Pragma // Parse parses a single Go source file from src and returns the corresponding -// syntax tree. If there are errors, Parse will return the first error found. -// The base argument is only used for position information. +// syntax tree. If there are errors, Parse will return the first error found, +// and a possibly partially constructed syntax tree, or nil if no correct package +// clause was found. The base argument is only used for position information. // // If errh != nil, it is called with each error encountered, and Parse will // process as much source as possible. If errh is nil, Parse will terminate diff --git a/test/fixedbugs/bug217.go b/test/fixedbugs/bug217.go index aafc260463..ea836b9b6d 100644 --- a/test/fixedbugs/bug217.go +++ b/test/fixedbugs/bug217.go @@ -13,3 +13,5 @@ func () x() // ERROR "no receiver" func (a b, c d) x() // ERROR "multiple receiver" +type b int + diff --git a/test/fixedbugs/issue18393.go b/test/fixedbugs/issue18393.go index cbcc9804b6..c16ff4df97 100644 --- a/test/fixedbugs/issue18393.go +++ b/test/fixedbugs/issue18393.go @@ -17,7 +17,7 @@ import 42 // error on line 20 var x // error on line 24, not 30 -// ERROR "missing import path" +// ERROR "import path must be a string" diff --git a/test/import5.go b/test/import5.go index d9673cfe9f..8fdc8c3757 100644 --- a/test/import5.go +++ b/test/import5.go @@ -21,7 +21,7 @@ import _ "go/parser" //import "greek/αβ" // Import paths must be strings. -import 42 // ERROR "missing import path; require quoted string" -import 'a' // ERROR "missing import path; require quoted string" -import 3.14 // ERROR "missing import path; require quoted string" -import 0.25i // ERROR "missing import path; require quoted string" +import 42 // ERROR "import path must be a string" +import 'a' // ERROR "import path must be a string" +import 3.14 // ERROR "import path must be a string" +import 0.25i // ERROR "import path must be a string"