Commit 5411953d authored by Robert Griesemer's avatar Robert Griesemer

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