From 5411953df50ce83ee8e23ca33a8a16335ad95cf2 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 29 Aug 2019 14:31:40 -0700 Subject: [PATCH] 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 --- src/cmd/compile/internal/gc/noder.go | 57 +++++++++++++++++----------- test/fixedbugs/issue32133.go | 43 +++++++++++++++++++++ 2 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 test/fixedbugs/issue32133.go diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 93d355278e..a60b854b2c 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -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") diff --git a/test/fixedbugs/issue32133.go b/test/fixedbugs/issue32133.go new file mode 100644 index 0000000000..13e4658a0f --- /dev/null +++ b/test/fixedbugs/issue32133.go @@ -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 + ` \ No newline at end of file -- 2.48.1