1
0
mirror of https://github.com/golang/go synced 2024-11-16 21:04:45 -07:00

cmd/compile: avoid follow-on errors for literals with syntax errors

- only convert literal strings if there were no syntax errors
  (some of the conversion routines exit if there is an error)
- mark nodes for literals with syntax errors to avoid follow-on
  errors
- don't attempt to import packages whose path had syntax errors

Fixes #32133.

Change-Id: I1803ad48c65abfecf6f48ddff1e27eded5e282c5
Reviewed-on: https://go-review.googlesource.com/c/go/+/192437
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Robert Griesemer 2019-08-29 14:31:40 -07:00
parent 117400ec09
commit 5411953df5
2 changed files with 77 additions and 23 deletions

View File

@ -309,6 +309,10 @@ func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
}
func (p *noder) importDecl(imp *syntax.ImportDecl) {
if imp.Path.Bad {
return // avoid follow-on errors if there was a syntax error
}
val := p.basicLit(imp.Path)
ipkg := importfile(&val)
@ -602,7 +606,9 @@ func (p *noder) expr(expr syntax.Expr) *Node {
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
return nodlit(p.basicLit(expr))
n := nodlit(p.basicLit(expr))
n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
return n
case *syntax.CompositeLit:
n := p.nod(expr, OCOMPLIT, nil, nil)
if expr.Type != nil {
@ -1351,55 +1357,60 @@ func checkLangCompat(lit *syntax.BasicLit) {
}
func (p *noder) basicLit(lit *syntax.BasicLit) Val {
// TODO: Don't try to convert if we had syntax errors (conversions may fail).
// Use dummy values so we can continue to compile. Eventually, use a
// form of "unknown" literals that are ignored during type-checking so
// we can continue type-checking w/o spurious follow-up errors.
// We don't use the errors of the conversion routines to determine
// if a literal string is valid because the conversion routines may
// accept a wider syntax than the language permits. Rely on lit.Bad
// instead.
switch s := lit.Value; lit.Kind {
case syntax.IntLit:
checkLangCompat(lit)
x := new(Mpint)
x.SetString(s)
if !lit.Bad {
x.SetString(s)
}
return Val{U: x}
case syntax.FloatLit:
checkLangCompat(lit)
x := newMpflt()
x.SetString(s)
if !lit.Bad {
x.SetString(s)
}
return Val{U: x}
case syntax.ImagLit:
checkLangCompat(lit)
x := newMpcmplx()
x.Imag.SetString(strings.TrimSuffix(s, "i"))
if !lit.Bad {
x.Imag.SetString(strings.TrimSuffix(s, "i"))
}
return Val{U: x}
case syntax.RuneLit:
var r rune
if u, err := strconv.Unquote(s); err == nil && len(u) > 0 {
// Package syntax already reported any errors.
// Check for them again though because 0 is a
// better fallback value for invalid rune
// literals than 0xFFFD.
x := new(Mpint)
x.Rune = true
if !lit.Bad {
u, _ := strconv.Unquote(s)
var r rune
if len(u) == 1 {
r = rune(u[0])
} else {
r, _ = utf8.DecodeRuneInString(u)
}
x.SetInt64(int64(r))
}
x := new(Mpint)
x.SetInt64(int64(r))
x.Rune = true
return Val{U: x}
case syntax.StringLit:
if len(s) > 0 && s[0] == '`' {
// strip carriage returns from raw string
s = strings.Replace(s, "\r", "", -1)
var x string
if !lit.Bad {
if len(s) > 0 && s[0] == '`' {
// strip carriage returns from raw string
s = strings.Replace(s, "\r", "", -1)
}
x, _ = strconv.Unquote(s)
}
// Ignore errors because package syntax already reported them.
u, _ := strconv.Unquote(s)
return Val{U: u}
return Val{U: x}
default:
panic("unhandled BasicLit kind")

View File

@ -0,0 +1,43 @@
// errorcheck
// Copyright 2019 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
// errors for the //line-adjusted code below
// ERROR "newline in string"
// ERROR "newline in character literal"
// ERROR "newline in string"
// ERROR "string not terminated"
//line :10:1
import "foo
//line :19:1
func _() {
0x // ERROR "hexadecimal literal has no digits"
}
func _() {
0x1.0 // ERROR "hexadecimal mantissa requires a 'p' exponent"
}
func _() {
0_i // ERROR "'_' must separate successive digits"
}
func _() {
//line :11:1
'
}
func _() {
//line :12:1
"
}
func _() {
//line :13:1
`