Commit 448246ad authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: don't exit early because of hidden error messages

Non-syntax errors are always counted to determine if to exit
early, but then deduplication eliminates them. This can lead
to situations which report "too many errors" and only one
error is shown.

De-duplicate non-syntax errors early, at least the ones that
appear consecutively, and only count the ones actually being
shown. This doesn't work perfectly as they may not appear in
sequence, but it's cheap and good enough.

Fixes #14136.

Change-Id: I7b11ebb2e1e082f0d604b88e544fe5ba967af1d7
Reviewed-on: https://go-review.googlesource.com/23259Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent dc4427f3
...@@ -87,46 +87,53 @@ func linestr(line int32) string { ...@@ -87,46 +87,53 @@ func linestr(line int32) string {
return Ctxt.Line(int(line)) return Ctxt.Line(int(line))
} }
func yyerrorl(line int32, format string, args ...interface{}) { // lasterror keeps track of the most recently issued error.
adderr(line, format, args...) // It is used to avoid multiple error messages on the same
// line.
hcrash() var lasterror struct {
nerrors++ syntax int32 // line of last syntax error
if nsavederrors+nerrors >= 10 && Debug['e'] == 0 { other int32 // line of last non-syntax error
Flusherrors() msg string // error message of last non-syntax error
fmt.Printf("%v: too many errors\n", linestr(line))
errorexit()
}
} }
var yyerror_lastsyntax int32 func yyerrorl(line int32, format string, args ...interface{}) {
func Yyerror(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...) msg := fmt.Sprintf(format, args...)
if strings.HasPrefix(msg, "syntax error") { if strings.HasPrefix(msg, "syntax error") {
nsyntaxerrors++ nsyntaxerrors++
// only one syntax error per line, no matter what error
// only one syntax error per line if lasterror.syntax == line {
if yyerror_lastsyntax == lineno {
return return
} }
yyerror_lastsyntax = lineno lasterror.syntax = line
} else {
yyerrorl(lineno, "%s", msg) // only one of multiple equal non-syntax errors per line
return // (Flusherrors shows only one of them, so we filter them
// here as best as we can (they may not appear in order)
// so that we don't count them here and exit early, and
// then have nothing to show for.)
if lasterror.other == line && lasterror.msg == msg {
return
}
lasterror.other = line
lasterror.msg = msg
} }
adderr(lineno, "%s", msg) adderr(line, "%s", msg)
hcrash() hcrash()
nerrors++ nerrors++
if nsavederrors+nerrors >= 10 && Debug['e'] == 0 { if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
Flusherrors() Flusherrors()
fmt.Printf("%v: too many errors\n", linestr(lineno)) fmt.Printf("%v: too many errors\n", linestr(line))
errorexit() errorexit()
} }
} }
func Yyerror(format string, args ...interface{}) {
yyerrorl(lineno, format, args...)
}
func Warn(fmt_ string, args ...interface{}) { func Warn(fmt_ string, args ...interface{}) {
adderr(lineno, fmt_, args...) adderr(lineno, fmt_, args...)
......
// errorcheck
// Copyright 2016 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.
// Test that > 10 non-syntax errors on the same line
// don't lead to early exit. Specifically, here test
// that we see the initialization error for variable
// s.
package main
type T struct{}
func main() {
t := T{X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1, X: 1} // ERROR "unknown T field"
var s string = 1 // ERROR "cannot use 1"
}
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