Skip to content

cmd/cgo: Conflicting types for generated symbols prevent LTO-enabled compilation #43830

@dbenoit17

Description

@dbenoit17

What version of Go are you using (go version)?

$ go version
go version go1.15.7 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOHOSTOS="linux"

What did you do?

Enable link time optimization CFLAGS when building a Go program containing an //export directive.

package main

import "fmt"
import "C"

//export add
func add(x int32, y int32) int32 {
  return x + y
}

func main() {
  fmt.Println(add(1,1))
}

The above program builds normally using go build without additional CFLAGS. However, building with CGO_CFLAGS='-flto -ffat-lto-objects' go build produces the following error.

_cgo_export.c:21:13: error: variable ‘_cgoexp_c166a99bca60_add’ redeclared as function
cgo-generated-wrappers:1:5: note: previously declared here
lto1: fatal error: errors during merging of translation units
compilation terminated.
lto-wrapper: fatal error: /usr/bin/gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status

This is due to the same symbol name being used in separate contexts as both a function and an integer.

What did you expect to see?

Program builds when enabling link time optimization via CFLAGs.

What did you see instead?

Generated intermediate C code for //export is incompatible with link time optimization.

Notes

Additional conflicting symbols may be created if the program binds the value of an exported function's C handle to a Go variable. The following program demonstrates the behavior.

package main

import "fmt"

// extern int add(int, int);
import "C"

//export add
func add(a int32, b int32) int32 {
  return a + b
}

func main() {
  fn := C.add
  fmt.Printf("%v\n", fn)
}

When built with CGO_CFLAGS='-flto -ffat-lto-objects' go build, the linker yields the following error.

cgo-generated-wrappers:1:13: error: function ‘add’ redeclared as variable
_cgo_export.c:24:9: note: previously declared here
_cgo_export.c:21:13: error: variable ‘_cgoexp_2526879f8d2a_add’ redeclared as function
cgo-generated-wrappers:4:5: note: previously declared here
lto1: fatal error: errors during merging of translation units
compilation terminated.
lto-wrapper: fatal error: /usr/bin/gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status

The interesting aspect to note is the redeclaration of the add symbol in addition to the previously encountered _cgoexp*_add symbol. This comes from introducing the assignment statement of C.add to the variable fn, and causes cgo to emit an additional pair of matching symbols with conflicting types via another code path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.help wanted

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions