Skip to content

cmd/go: cgo functions rewritten only with -gcflags=-L #67741

@ianlancetaylor

Description

@ianlancetaylor

Go version

tip

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/iant/.cache/go-build'
GOENV='/home/iant/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/iant/gopath/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/iant/gopath'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org'
GOROOT='/home/iant/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/iant/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='devel go1.23-377646589d Fri May 24 22:23:55 2024 +0000'
GODEBUG=''
GOTELEMETRY='on'
GOTELEMETRYDIR='/home/iant/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build3319284758=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Build this package:

package p

import "C"

func F() *C.char {
	s, err := C.CString("hi")
	if err != nil {
		println(err)
	}
	return s
}

What did you see happen?

With no -gcflags option:

# command-line-arguments
$WORK/b001/_cgo_gotypes.go:75:6: _Cfunc_CString redeclared in this block
	$WORK/b001/_cgo_gotypes.go:53:6: other declaration of _Cfunc_CString
foo.go:6:12: undefined: _C2func_CString

With -gcflags=-L:

# command-line-arguments
$WORK/b001/_cgo_gotypes.go:75:6: C.CString redeclared in this block
	$WORK/b001/_cgo_gotypes.go:53:6: other declaration of C.CString
foo.go:6:12: undefined: C.CString

What did you expect to see?

I don't expect -gcflags=L to change the function name reported by the compiler. The -L option is documented as "Show complete file path in error messages." Why should that change the function name?

This turns out to happen because of some code in cmd/go/internal/work/shell.go. That code looks for lines that match the regexp \[[^\[\]]+\.(cgo1|cover)\.go:[0-9]+(:[0-9]+)?\]. With -gcflags=-L, the compiler emits lines like

./foo.go:6:12[/tmp/go-build1291356211/b001/foo.cgo1.go:9:28]: undefined: _C2func_CString

That matches the regexp. In that case cmd/go strips the line in square brackets, and then translates _C2func_ to C.. That was introduced in https://go.dev/cl/7231075 for the Go 1.1 release. From looking at the source code, it does appear that at that time the compiler always printed the original file name in square brackets if a //line directive had been used. Today that only happens if the -L option has been used.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions