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: improperly ordered evaluation of "x, z := f(&x), f(&x)" #24448

Open
go101 opened this issue Mar 19, 2018 · 5 comments
Open

gccgo: improperly ordered evaluation of "x, z := f(&x), f(&x)" #24448

go101 opened this issue Mar 19, 2018 · 5 comments
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@go101
Copy link

go101 commented Mar 19, 2018

This is an issue separated from #23188.

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

go version go1.10 linux/amd64

Does this issue reproduce with the latest release?

yes

Description

sorry, this issue is a little complex, so I don't use the issue report template.

First, the behaviors of gc and gccgo are different for the following program.

package main

import "fmt"

func f(p *int) int {
	*p = 123
	return *p
}

func main() {
	var x int
	y, z := x, f(&x)
	fmt.Println(y, z) // gc: 123 123.  gccgo: 0 123
}

But, the behaviors of the two compiler are the same for the following modified version.
I think here gccgo is inconsistent with itself.

package main

import "fmt"

func f(p *int) int {
	*p = 123
	return *p
}

func main() {
	var x int
	x, z := x, f(&x)
	fmt.Println(x, z)// both: 123 123
}

There is certainly a bug in gccgo (may be also not, as spec really doesn't specify the order).
Whether or not it is a bug for gc is not specified in Go spec.
However, I think, it is best to specify the order in Go spec (if it is possible).

@go101
Copy link
Author

go101 commented Mar 19, 2018

Another example:

package main

import "fmt"

func f(p *int) int {
	*p++
	return *p
}

func main() {
	var x int
	x, z := f(&x), f(&x)
	fmt.Println(x, z) // gc: 1 2.  gccgo: 2 1
}

It looks this order is specified in Go spec and it looks the order in gccgo is wrong.

But the behaviors of the following one are the same.

package main

import "fmt"

func f(p *int) int {
	*p++
	return *p
}

func main() {
	var x int
	y, z := f(&x), f(&x)
	fmt.Println(y, z) // both: 1 2
}

BTW, the example provided in Go spec is not perfect.
It looks the indexing of x can only happen after i() and before j(), it is not not specified.
The description will be better it is modified as (by removing indexing of)

the function calls and communication happen in the order f(), h(), i(), j(), <-c, g(), and k().
However, the order of those events compared to the evaluation and x and
the evaluation of y is not specified. 

@mvdan
Copy link
Member

mvdan commented Mar 19, 2018

/cc @mdempsky @ianlancetaylor

@andybons andybons added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 19, 2018
@ianlancetaylor
Copy link
Contributor

To be honest, it's confusing when you use several different test cases with different behaviors in the same issue.

It's not yet clear to me that there are any bugs here at all. What matters with regard to order of evaluation is what the spec says. When the order of evaluation is not specified the spec, any order is permitted. So in the original message, although you say that gccgo is not consistent with itself, that may be true but it is not a bug. It would also not be a bug if gccgo chose one implementation one time and a different implementation another time; at least, it would not be a bug in how gccgo implements the spec.

So the only question here is: what does the spec require? And do the compilers implement that?

@mdempsky
Copy link
Member

For the first example,

x, z := x, f(&x)

the spec doesn't specify whether x or f(&x) is evaluated first. That is, either of these two orderings are permitted:

  1.  t0 := x
     t1 := f(&x)
     x, z := t0, t1
    
  2.  t1 := f(&x)
     t0 := x
     x, z := t0, t1
    

gccgo uses the former, and gc uses the latter.

As for the second example,

x, z := f(&x), f(&x)

the spec requires they be evaluated left to right. That is, it must be equivalent to

t0 := f(&x)
t1 := f(&x)
x, z := t0, t1

It sounds like gc gets this right, but gccgo does not.

@mdempsky mdempsky added the NeedsFix The path to resolution is known, but the work has not been done. label Mar 19, 2018
@gopherbot gopherbot removed the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 19, 2018
@mdempsky mdempsky changed the title cmd/compile: inconsistent behaviors between gc and gccgo on the evaluation order of right items in an assignment gccgo: improperly ordered evaluation of "x, z := f(&x), f(&x)" Mar 19, 2018
@mdempsky
Copy link
Member

mdempsky commented Mar 19, 2018

Just for clarity, this is the example that I believe gc gets right, but gccgo is misevaluating:

package main

import "fmt"

func f(p *int) int {
	*p++
	return *p
}

func main() {
	var x int
	x, z := f(&x), f(&x)
	fmt.Println(x, z) // gc: 1 2.  gccgo: 2 1
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants