Commit 7a26d9fc authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile/internal/syntax: don't panic if no error handler is provided

If no error handler is provided, terminate parsing with first error
and report that error.

Fixes #17697.

Change-Id: I9070faf7239bd53725de141507912b92ded3474b
Reviewed-on: https://go-review.googlesource.com/32456
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent 53fc330e
...@@ -28,6 +28,8 @@ type parser struct { ...@@ -28,6 +28,8 @@ type parser struct {
nerrors int // error count nerrors int // error count
} }
type parserError string // for error recovery if no error handler was installed
func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) { func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) {
p.scanner.init(src, func(pos, line int, msg string) { p.scanner.init(src, func(pos, line int, msg string) {
p.nerrors++ p.nerrors++
...@@ -35,7 +37,7 @@ func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) { ...@@ -35,7 +37,7 @@ func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) {
errh(pos, line, msg) errh(pos, line, msg)
return return
} }
panic(fmt.Sprintf("%d: %s\n", line, msg)) panic(parserError(fmt.Sprintf("%d: %s\n", line, msg)))
}, pragh) }, pragh)
p.fnest = 0 p.fnest = 0
......
...@@ -155,3 +155,10 @@ func verifyPrint(filename string, ast1 *File) { ...@@ -155,3 +155,10 @@ func verifyPrint(filename string, ast1 *File) {
panic("not equal") panic("not equal")
} }
} }
func TestIssue17697(t *testing.T) {
_, err := ReadBytes(nil, nil, nil, 0) // return with parser error, don't panic
if err == nil {
t.Errorf("no error reported")
}
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package syntax package syntax
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
...@@ -52,18 +53,31 @@ func ReadBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (* ...@@ -52,18 +53,31 @@ func ReadBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*
return Read(&bytesReader{src}, errh, pragh, mode) return Read(&bytesReader{src}, errh, pragh, mode)
} }
func Read(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (*File, error) { func Read(src io.Reader, errh ErrorHandler, pragh PragmaHandler, mode Mode) (ast *File, err error) {
defer func() {
if p := recover(); p != nil {
if msg, ok := p.(parserError); ok {
err = errors.New(string(msg))
return
}
panic(p)
}
}()
var p parser var p parser
p.init(src, errh, pragh) p.init(src, errh, pragh)
p.next() p.next()
ast := p.file() ast = p.file()
// TODO(gri) This isn't quite right: Even if there's an error handler installed
// we should report an error if parsing found syntax errors. This also
// requires updating the noder's ReadFile call.
if errh == nil && p.nerrors > 0 { if errh == nil && p.nerrors > 0 {
return nil, fmt.Errorf("%d syntax errors", p.nerrors) ast = nil
err = fmt.Errorf("%d syntax errors", p.nerrors)
} }
return ast, nil return
} }
func Write(w io.Writer, n *File) error { func Write(w io.Writer, n *File) error {
......
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