diff --git a/src/cmd/compile/internal/syntax/scanner.go b/src/cmd/compile/internal/syntax/scanner.go index edd60609a0..c2de9ce686 100644 --- a/src/cmd/compile/internal/syntax/scanner.go +++ b/src/cmd/compile/internal/syntax/scanner.go @@ -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' { diff --git a/src/cmd/compile/internal/syntax/scanner_test.go b/src/cmd/compile/internal/syntax/scanner_test.go index ed240df069..4d04e62875 100644 --- a/src/cmd/compile/internal/syntax/scanner_test.go +++ b/src/cmd/compile/internal/syntax/scanner_test.go @@ -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 index 0000000000..6a627d9b5e --- /dev/null +++ b/test/fixedbugs/issue15611.go @@ -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