Skip to content

Commit

Permalink
proc: fix result type of division of untyped constants (go-delve#3794)
Browse files Browse the repository at this point in the history
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 go-delve#3793
  • Loading branch information
aarzilli committed Sep 5, 2024
1 parent c2dc6ed commit a63cc8a
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
3 changes: 2 additions & 1 deletion _fixtures/testvariables2.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ func main() {
enum4 := IntConst
enum5 := BoolConst
enum6 := FloatConst
var zeropoint4 float64 = 0.4

var amb1 = 1
runtime.Breakpoint()
Expand All @@ -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)
}
27 changes: 21 additions & 6 deletions pkg/proc/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -2295,12 +2295,27 @@ func (scope *EvalScope) evalBinary(binop *evalop.Binary, stack *evalStack) {
}

op := node.Op
if typ != nil && (op == token.QUO) {
_, isint := typ.(*godwarf.IntType)
_, isuint := typ.(*godwarf.UintType)
if isint || isuint {
// forces integer division if the result type is integer
op = token.QUO_ASSIGN
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
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/proc/variables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down

0 comments on commit a63cc8a

Please sign in to comment.