Commit 68e39030 authored by griesemer's avatar griesemer Committed by Robert Griesemer

cmd/compile/internal/syntax: consider function nesting for error recovery

This re-enables functionality that inadvertently was disabled in the
(long) past.

Also, don't perform branch checks if we had errors in a function
to avoid spurious errors or (worst-case) crashes.

Slightly modified test/fixedbugs/issue14006.go to make sure the
test still reports invalid label errors (the surrounding function
must be syntactically correct).

Change-Id: Id5642930877d7cf3400649094ec75c753b5084b7
Reviewed-on: https://go-review.googlesource.com/69770
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 39edffb6
...@@ -23,6 +23,7 @@ type parser struct { ...@@ -23,6 +23,7 @@ type parser struct {
scanner scanner
first error // first error encountered first error // first error encountered
errcnt int // number of errors encountered
pragma Pragma // pragma flags pragma Pragma // pragma flags
fnest int // function nesting level (for error handling) fnest int // function nesting level (for error handling)
...@@ -57,6 +58,7 @@ func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh P ...@@ -57,6 +58,7 @@ func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh P
) )
p.first = nil p.first = nil
p.errcnt = 0
p.pragma = 0 p.pragma = 0
p.fnest = 0 p.fnest = 0
...@@ -114,6 +116,7 @@ func (p *parser) error_at(pos src.Pos, msg string) { ...@@ -114,6 +116,7 @@ func (p *parser) error_at(pos src.Pos, msg string) {
if p.first == nil { if p.first == nil {
p.first = err p.first = err
} }
p.errcnt++
if p.errh == nil { if p.errh == nil {
panic(p.first) panic(p.first)
} }
...@@ -179,7 +182,6 @@ const stopset uint64 = 1<<_Break | ...@@ -179,7 +182,6 @@ const stopset uint64 = 1<<_Break |
1<<_Defer | 1<<_Defer |
1<<_Fallthrough | 1<<_Fallthrough |
1<<_For | 1<<_For |
1<<_Func |
1<<_Go | 1<<_Go |
1<<_Goto | 1<<_Goto |
1<<_If | 1<<_If |
...@@ -495,17 +497,18 @@ func (p *parser) funcDeclOrNil() *FuncDecl { ...@@ -495,17 +497,18 @@ func (p *parser) funcDeclOrNil() *FuncDecl {
} }
func (p *parser) funcBody() *BlockStmt { func (p *parser) funcBody() *BlockStmt {
// TODO(gri) If we are in a function we should update p.fnest p.fnest++
// accordingly. Currently p.fnest is always zero and thus not errcnt := p.errcnt
// used in error recovery.
// Not enabled because it performs worse for some code without
// more fine tuning (see example in #22164).
// p.fnest++
body := p.blockStmt("") body := p.blockStmt("")
// p.fnest-- p.fnest--
if p.mode&CheckBranches != 0 {
// Don't check branches if there were syntax errors in the function
// as it may lead to spurious errors (e.g., see test/switch2.go) or
// possibly crashes due to incomplete syntax trees.
if p.mode&CheckBranches != 0 && errcnt == p.errcnt {
checkBranches(body, p.errh) checkBranches(body, p.errh)
} }
return body return body
} }
......
...@@ -50,7 +50,10 @@ func f() { ...@@ -50,7 +50,10 @@ func f() {
labelname: // ERROR "missing statement after label" labelname: // ERROR "missing statement after label"
case false: case false:
} }
}
func g() {
var z bool
switch { switch {
case z: case z:
labelname: // ERROR "label labelname defined and not used" labelname: // ERROR "label labelname defined and not used"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment