]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: don't panic if no error handler is provided
authorRobert Griesemer <gri@golang.org>
Mon, 31 Oct 2016 23:58:15 +0000 (16:58 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 1 Nov 2016 05:18:47 +0000 (05:18 +0000)
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: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/parser_test.go
src/cmd/compile/internal/syntax/syntax.go

index fcf4f5b692050a1ae4b2afcf109ac8b5a05f685a..1ed20651b1088e688b6f56feb8355d944b173da9 100644 (file)
@@ -28,6 +28,8 @@ type parser struct {
        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) {
        p.scanner.init(src, func(pos, line int, msg string) {
                p.nerrors++
@@ -35,7 +37,7 @@ func (p *parser) init(src io.Reader, errh ErrorHandler, pragh PragmaHandler) {
                        errh(pos, line, msg)
                        return
                }
-               panic(fmt.Sprintf("%d: %s\n", line, msg))
+               panic(parserError(fmt.Sprintf("%d: %s\n", line, msg)))
        }, pragh)
 
        p.fnest = 0
index 8e6b77d0c687eed9655d0bec3f931368cf407186..780f10835cff7b8dcfef4b6fd0b6a9e9ccd3831a 100644 (file)
@@ -155,3 +155,10 @@ func verifyPrint(filename string, ast1 *File) {
                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")
+       }
+}
index 49831d0fbd03efeff2072cd00ff1b722a227b737..71fc097c3b2ec14a64b16cd543fbbacc7f855107 100644 (file)
@@ -5,6 +5,7 @@
 package syntax
 
 import (
+       "errors"
        "fmt"
        "io"
        "os"
@@ -52,18 +53,31 @@ func ReadBytes(src []byte, errh ErrorHandler, pragh PragmaHandler, mode 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
        p.init(src, errh, pragh)
-
        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 {
-               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 {