proc: fix result type of division of untyped constants (#3794)

The Go specification says that the result of division of untyped
constants should be an untyped integer constant if both constants are
untyped integers, the go/constant package however does something
different by always producing an untyped floating constant.

Fixes #3793
This commit is contained in:
Alessandro Arzilli 2024-09-05 09:23:21 +02:00 committed by GitHub
parent c2dc6edcfc
commit a63cc8a1a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 7 deletions

@ -415,6 +415,7 @@ func main() {
enum4 := IntConst
enum5 := BoolConst
enum6 := FloatConst
var zeropoint4 float64 = 0.4
var amb1 = 1
runtime.Breakpoint()
@ -426,5 +427,5 @@ func main() {
longslice := make([]int, 100, 100)
runtime.Breakpoint()
fmt.Println(i1, i2, i3, p1, pp1, amb1, s1, s3, a0, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr, ch1, chnil, m1, mnil, m2, m3, m4, m5, upnil, up1, i4, i5, i6, err1, err2, errnil, iface1, iface2, ifacenil, arr1, parr, cpx1, const1, iface3, iface4, recursive1, recursive1.x, iface5, iface2fn1, iface2fn2, bencharr, benchparr, mapinf, mainMenu, b, b2, sd, anonstruct1, anonstruct2, anoniface1, anonfunc, mapanonstruct1, ifacearr, efacearr, ni8, ni16, ni32, ni64, pinf, ninf, nan, zsvmap, zsslice, zsvar, tm, rettm, errtypednil, emptyslice, emptymap, byteslice, bytestypeslice, runeslice, bytearray, bytetypearray, runearray, longstr, nilstruct, as2, as2.NonPointerReceiverMethod, s4, iface2map, issue1578, ll, unread, w2, w3, w4, w5, longarr, longslice, val, m6, m7, cl, tim1, tim2, typedstringvar, namedA1, namedA2, astructName1(namedA2), badslice, tim3, int3chan, longbyteslice, enum1, enum2, enum3, enum4, enum5, enum6)
fmt.Println(i1, i2, i3, p1, pp1, amb1, s1, s3, a0, a1, p2, p3, s2, as1, str1, f1, fn1, fn2, nilslice, nilptr, ch1, chnil, m1, mnil, m2, m3, m4, m5, upnil, up1, i4, i5, i6, err1, err2, errnil, iface1, iface2, ifacenil, arr1, parr, cpx1, const1, iface3, iface4, recursive1, recursive1.x, iface5, iface2fn1, iface2fn2, bencharr, benchparr, mapinf, mainMenu, b, b2, sd, anonstruct1, anonstruct2, anoniface1, anonfunc, mapanonstruct1, ifacearr, efacearr, ni8, ni16, ni32, ni64, pinf, ninf, nan, zsvmap, zsslice, zsvar, tm, rettm, errtypednil, emptyslice, emptymap, byteslice, bytestypeslice, runeslice, bytearray, bytetypearray, runearray, longstr, nilstruct, as2, as2.NonPointerReceiverMethod, s4, iface2map, issue1578, ll, unread, w2, w3, w4, w5, longarr, longslice, val, m6, m7, cl, tim1, tim2, typedstringvar, namedA1, namedA2, astructName1(namedA2), badslice, tim3, int3chan, longbyteslice, enum1, enum2, enum3, enum4, enum5, enum6, zeropoint4)
}

@ -2295,13 +2295,28 @@ func (scope *EvalScope) evalBinary(binop *evalop.Binary, stack *evalStack) {
}
op := node.Op
if typ != nil && (op == token.QUO) {
if op == token.QUO {
if typ != nil {
_, isint := typ.(*godwarf.IntType)
_, isuint := typ.(*godwarf.UintType)
if isint || isuint {
// forces integer division if the result type is integer
op = token.QUO_ASSIGN
}
} else {
if xv.Value != nil && yv.Value != nil && xv.Value.Kind() == constant.Int && yv.Value.Kind() == constant.Int {
// See issue #3793 and the specification at https://go.dev/ref/spec#Constant_expressions
// in particular:
//
// "If the untyped operands of a binary operation (other than a shift)
// are of different kinds, the result is of the operand's kind that
// appears later in this list: integer, rune, floating-point, complex"
//
// However the go/constant package says that to get an integer result
// from a division token.QUO_ASSIGN must be used.
op = token.QUO_ASSIGN
}
}
}
switch op {

@ -718,6 +718,8 @@ func getEvalExpressionTestCases() []varTest {
{"1 + 2i", false, "(1 + 2i)", "(1 + 2i)", "", nil},
{"true", false, "true", "true", "", nil},
{"\"test\"", false, "\"test\"", "\"test\"", "", nil},
{"1/2", false, "0", "0", "", nil},
{"zeropoint4 > 1/2", false, "true", "true", "", nil},
// binary operators
{"i2 + i3", false, "5", "5", "int", nil},