go cmd/compile: 错误,报告的行号不正确,如果它出现在0xFFFFF之后,

tjvv9vkg  于 2个月前  发布在  Go
关注(0)|答案(3)|浏览(42)

你使用的Go版本是什么( go version )?

$ go version
go version go1.13.7 linux/amd64

这个问题在最新版本的发布中是否重现?

是的。

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/icza/.cache/go-build"
GOENV="/home/icza/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY="xxx"
GONOSUMDB="xxx"
GOOS="linux"
GOPATH="/home/icza/gows"
GOPRIVATE="xxx"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build104015454=/tmp/go-build -gno-record-gcc-switches"

你做了什么?

创建一个有效的 .go 源文件,该文件具有超过 1048574 行( 0xFFFFF )。并在末尾添加一些“垃圾”以使其无效,导致编译失败。尝试构建它( go build big.go )或运行它( go run big.go ),go工具检测到错误并显示错误消息,其中行号被错误地截断,例如:

./big.go:1048574:2: syntax error: unexpected invalid after top level declaration

这是一个简单的Go应用程序,它创建了一个 big.go 文件,该文件大约有两倍多的行数(它有一个原始字符串字面量,其中包含2*0xFFFFF个空行):

package main

import (
	"bytes"
	"io/ioutil"
	"strings"
)

func main() {
	src := &bytes.Buffer{}
	src.WriteString(`package main
func main() { println(len(s)) }
const s=`)
	src.WriteString("`")
	src.WriteString(strings.Repeat("\n", 2*0xFFFFF))
	src.WriteString("`")

	// This is the garbage to make compilation fail:
	src.WriteString("invalid")

	if err := ioutil.WriteFile("big.go", src.Bytes(), 0666); err != nil {
		panic(err)
	}
}

如果我们减少生成的行数,例如:

src.WriteString(strings.Repeat("\n", 10_000))

我们会得到正确的行号( 10003 ):

./big.go:10003:2: syntax error: unexpected invalid after top level declaration

你期望看到什么?

我期望在检测到错误的正确位置打印出正确的行号( 2*0xFFFFFF+3 = 2097153 ):

./big.go:2097153:2: syntax error: unexpected invalid after top level declaration

你看到了什么?

显示的错误行号被错误地截断为 1048574 :

./big.go:1048574:2: syntax error: unexpected invalid after top level declaration

**注意:**这个问题在StackOverflow上报告: https://stackoverflow.com/questions/59951140/go-compiler-error-line-number-is-incorrect

nnt7mjpx

nnt7mjpx1#

我认为限制行号是可以的,但我们不应该报告错误的行号。我们应该说我们不知道。
(我认为没有必要强迫编译器使用更多的内存,以便为每个人的编译速度变慢,从而为非常大的文件提供更好的错误信息。这样的文件通常是机器生成的,因此要么没有错误,要么有很多错误。)

ffscu2ro

ffscu2ro2#

我将更改问题标题以符合@ianlancetaylor提到的建议。感谢您报告此问题。

fzwojiic

fzwojiic3#

嘿,我做了一些调查,如果大家同意的话,我打算创建一个PR。
1048574 == 1 << 20 - 2 的限制来自这里
我做了以下更改

<<<<<<<
lineBits, lineMax     = 20, 1<<lineBits - 2
=======
lineBits, lineMax     = 23, 1<<lineBits - 2
>>>>>>>

并使用 ./make.bash 重新编译了工具链。
结果是,在我的Go 1.13中,这个问题仍然存在。
通过上述更改和重新编译的工具链,正确的错误行被报告。

➜  build-invalid-file ./make.bash
➜  build-invalid-file go version
go version go1.13.7 darwin/amd64
➜  build-invalid-file go run big.go
# command-line-arguments
./big.go:1048574:2: syntax error: unexpected invalid after top level declaration
➜  build-invalid-file /Users/.../..../go/bin/go run big.go
# command-line-arguments
./big.go:2097153:2: syntax error: unexpected invalid after top level declaration

makeLico 函数强制执行这个限制,它在MakePos中被使用。

  • "after top level declaration"* 消息源自这里(伪装成语法错误),报告的行来自 p.pos()

这个 p.pos() 方法使用了 posAt,它使用了原始的 MakePos 函数。
抱歉写了这么多冗长的回答,但我认为这概述了发生错误的途径和原因。
我喜欢Ian关于 不改变上限 的建议,但当报告的行达到这个上限时打印另一个消息。
我觉得这可能是 errorAtsyntaxErrorAt 中的一个小改动(?),在返回之前进行简单的检查。如果位置等于限制,它将返回不同的消息。
我会想出一个合适的建议并回到这个帖子。

相关问题