Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gccgo: nointerface on exported inlined method causes bad type descriptor #30862

Closed
thanm opened this issue Mar 15, 2019 · 2 comments
Closed

gccgo: nointerface on exported inlined method causes bad type descriptor #30862

thanm opened this issue Mar 15, 2019 · 2 comments
Milestone

Comments

@thanm
Copy link
Contributor

thanm commented Mar 15, 2019

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

$ go version
go version devel +e5ba612637 Thu Mar 7 14:12:01 2019 -0500 linux/amd64
$ gccgo --version
gccgo (GCC) 9.0.1 20190304 (experimental)

Does this issue reproduce with the latest release?

Yes

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

linux/amd64

go env Output
$ go env
GOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/ssd2/go1"
GOPROXY=""
GORACE=""
GOROOT="/ssd2/go"
GOTMPDIR=""
GCCGO="/ssd/gcc-trunk/cross/bin/gccgo"
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-build042808661=/tmp/go-build -gno-record-gcc-switches"

What did you do?

There is a problem with gccgo regarding how it handles exported inlinable methods that are marked with the //go:nointerface flag. Here are a couple of packages that will reproduce the problem:

In $GOPATH/src/noitfimp:

package noitfimp

var pl int

type NoitfStruct struct {
	F int
	G int
}

//go:nointerface
func (t *NoitfStruct) GMethod() int {
	return t.G
}

func (t *NoitfStruct) FMethod() int {
	return t.F
}

//go:nointerface
func (t *NoitfStruct) NoInterfaceMethod() {}

and then in $GOPATH/src/noitfmain:

package noitfmain

import (
	"noitfimp"
)

type EmbedImported struct {
	noitfimp.NoitfStruct
}

func Test() []string {
	bad := []string{}
	x := interface{}(new(noitfimp.NoitfStruct))
	if _, ok := x.(interface {
		NoInterfaceMethod()
	}); ok {
		bad = append(bad, "fail 1")
	}

	x = interface{}(new(EmbedImported))
	if _, ok := x.(interface {
		NoInterfaceMethod()
	}); ok {
		bad = append(bad, "fail 2")
	}
	return bad
}

and then finally a driver program in $GOPATH/src/noitfdriver:

package main

import (
	"fmt"
	"noitfmain"
	"os"
)

func main() {
	bad := noitfmain.Test()
	if len(bad) > 0 {
		for _, s := range bad {
			fmt.Fprintf(os.Stderr, "test failed: %s\n", s)
		}
		os.Exit(1)
	}
}

Then compiler and run the final package (e.g. "go run -compiler gccgo itfdriver").

What did you expect to see?

Empty result from itfmain.Test

What did you see instead?

When executed, prints "test failed: fail 2".

It appears that the 'go:nointerface' property is being lost somehow when the imported type noitfimp.NoitfStruct is embedded into the itfmain type EmbedImported. If I look at the generated assembly, I can see that an additional method NoInterfaceMethod is being incorrectly attached to the type (other than FMethod).

The problem appears to be related to inlining -- in package noitfimp the method in question is empty, meaning that the body gets written out to the export data. If I modify the method body to include more complex statement (for example, a defer) then the problem goes away.

@thanm thanm added this to the Gccgo milestone Mar 15, 2019
@thanm thanm self-assigned this Mar 15, 2019
@gopherbot
Copy link

Change https://golang.org/cl/167742 mentions this issue: compiler: preserve nointerface property when inlining methods

@gopherbot
Copy link

Change https://golang.org/cl/167744 mentions this issue: test: new test for issue 30862

kraj pushed a commit to kraj/gcc that referenced this issue Mar 15, 2019
    
    When an inline function (with body) is imported from another package,
    make that the "nointerface" property (if set) is preserved.
    
    Fixes golang/go#30862.
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/167742


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@269713 138bc75d-0d04-0410-961f-82ee72b054a4
gopherbot pushed a commit that referenced this issue Mar 15, 2019
New test case, inspired by gccgo issue 30862.

Updates #30862.

Change-Id: I5e494b877e4fd142b8facb527471fe1fdef39c61
Reviewed-on: https://go-review.googlesource.com/c/go/+/167744
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
@golang golang locked and limited conversation to collaborators Mar 14, 2020
@rsc rsc unassigned thanm Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants