]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: better errors and recovery for invalid character literals
authorRobert Griesemer <gri@golang.org>
Thu, 16 Feb 2017 20:52:01 +0000 (12:52 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 16 Feb 2017 21:46:43 +0000 (21:46 +0000)
Fixes #15611.

Change-Id: I352b145026466cafef8cf87addafbd30716bda24
Reviewed-on: https://go-review.googlesource.com/37138
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/syntax/scanner.go
src/cmd/compile/internal/syntax/scanner_test.go
test/fixedbugs/issue15611.go [new file with mode: 0644]

index edd60609a0851ed20bc8321b27f4b49a1a08d96c..c2de9ce68612e3e41a40f3212b6daaa2e355017d 100644 (file)
@@ -466,6 +466,53 @@ done:
        s.tok = _Literal
 }
 
+func (s *scanner) rune() {
+       s.startLit()
+
+       ok := true // only report errors if we're ok so far
+       n := 0
+       for ; ; n++ {
+               r := s.getr()
+               if r == '\'' {
+                       break
+               }
+               if r == '\\' {
+                       if !s.escape('\'') {
+                               ok = false
+                       }
+                       continue
+               }
+               if r == '\n' {
+                       s.ungetr() // assume newline is not part of literal
+                       if ok {
+                               s.error("newline in character literal")
+                               ok = false
+                       }
+                       break
+               }
+               if r < 0 {
+                       if ok {
+                               s.errh(s.line, s.col, "invalid character literal (missing closing ')")
+                               ok = false
+                       }
+                       break
+               }
+       }
+
+       if ok {
+               if n == 0 {
+                       s.error("empty character literal or unescaped ' in character literal")
+               } else if n != 1 {
+                       s.errh(s.line, s.col, "invalid character literal (more than one character)")
+               }
+       }
+
+       s.nlsemi = true
+       s.lit = string(s.stopLit())
+       s.kind = RuneLit
+       s.tok = _Literal
+}
+
 func (s *scanner) stdString() {
        s.startLit()
 
@@ -518,38 +565,6 @@ func (s *scanner) rawString() {
        s.tok = _Literal
 }
 
-func (s *scanner) rune() {
-       s.startLit()
-
-       r := s.getr()
-       ok := false
-       if r == '\'' {
-               s.error("empty character literal or unescaped ' in character literal")
-       } else if r == '\n' {
-               s.ungetr() // assume newline is not part of literal
-               s.error("newline in character literal")
-       } else {
-               ok = true
-               if r == '\\' {
-                       ok = s.escape('\'')
-               }
-       }
-
-       r = s.getr()
-       if r != '\'' {
-               // only report error if we're ok so far
-               if ok {
-                       s.error("missing '")
-               }
-               s.ungetr()
-       }
-
-       s.nlsemi = true
-       s.lit = string(s.stopLit())
-       s.kind = RuneLit
-       s.tok = _Literal
-}
-
 func (s *scanner) skipLine(r rune) {
        for r >= 0 {
                if r == '\n' {
index ed240df069da9ba868c0dfa2867a3ff7dea8959b..4d04e6287511b4bd09fc095e74b412ffb2db596e 100644 (file)
@@ -292,9 +292,9 @@ func TestScanErrors(t *testing.T) {
 
                {`''`, "empty character literal or unescaped ' in character literal", 1, 1},
                {"'\n", "newline in character literal", 1, 1},
-               {`'\`, "missing '", 1, 2},
-               {`'\'`, "missing '", 1, 3},
-               {`'\x`, "missing '", 1, 3},
+               {`'\`, "invalid character literal (missing closing ')", 1, 0},
+               {`'\'`, "invalid character literal (missing closing ')", 1, 0},
+               {`'\x`, "invalid character literal (missing closing ')", 1, 0},
                {`'\x'`, "non-hex character in escape sequence: '", 1, 3},
                {`'\y'`, "unknown escape sequence", 1, 2},
                {`'\x0'`, "non-hex character in escape sequence: '", 1, 4},
@@ -302,7 +302,8 @@ func TestScanErrors(t *testing.T) {
                {`'\377' /*`, "comment not terminated", 1, 7}, // valid octal escape
                {`'\378`, "non-octal character in escape sequence: 8", 1, 4},
                {`'\400'`, "octal escape value > 255: 256", 1, 5},
-               {`'xx`, "missing '", 1, 2},
+               {`'xx`, "invalid character literal (missing closing ')", 1, 0},
+               {`'xx'`, "invalid character literal (more than one character)", 1, 0},
 
                {"\"\n", "newline in string", 1, 1},
                {`"`, "string not terminated", 1, 0},
diff --git a/test/fixedbugs/issue15611.go b/test/fixedbugs/issue15611.go
new file mode 100644 (file)
index 0000000..6a627d9
--- /dev/null
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// These error messages are for the invalid literals on lines 19 and 20:
+
+// ERROR "newline in character literal"
+// ERROR "invalid character literal \(missing closing '\)"
+
+const (
+       _ = ''     // ERROR "empty character literal or unescaped ' in character literal"
+       _ = 'f'
+       _ = 'foo'  // ERROR "invalid character literal \(more than one character\)"
+//line issue15611.go:11
+       _ = '
+       _ = '
\ No newline at end of file