diff --git a/runtime/internal/runtime/z_error.go b/runtime/internal/runtime/z_error.go index 6f1976051d..b0dfd6463f 100644 --- a/runtime/internal/runtime/z_error.go +++ b/runtime/internal/runtime/z_error.go @@ -57,7 +57,7 @@ func AssertIndexRange(b bool) { func AssertDivideByZero(b bool) { if b { - panic(errorString("integer divide by zero").Error()) + panic(errorString("integer divide by zero")) } } diff --git a/ssa/expr.go b/ssa/expr.go index ecc19ca215..d97996c80c 100644 --- a/ssa/expr.go +++ b/ssa/expr.go @@ -1470,7 +1470,7 @@ func (b Builder) BuiltinCall(fn string, args ...Expr) (ret Expr) { return b.Advance(args[0], args[1]) case "Sizeof": // instance of generic function - return b.Prog.Val(int(b.Prog.SizeOf(args[0].Type))) + return b.Prog.IntVal(b.Prog.SizeOf(args[0].Type), b.Prog.Uintptr()) case "Alignof": // instance of generic function return b.Prog.Val(int(b.Prog.td.ABITypeAlignment(args[0].ll))) diff --git a/test/go/generic_unsafe_sizeof_arithmetic_test.go b/test/go/generic_unsafe_sizeof_arithmetic_test.go new file mode 100644 index 0000000000..e8fd90c5ab --- /dev/null +++ b/test/go/generic_unsafe_sizeof_arithmetic_test.go @@ -0,0 +1,78 @@ +package gotest + +import ( + "strings" + "testing" + "unsafe" +) + +func genericUnsafeSizeofShift[T any]() int64 { + return 1 << unsafe.Sizeof(*new(T)) +} + +func genericUnsafeSizeofDiv[T any]() uintptr { + return 1 / unsafe.Sizeof(*new(T)) +} + +func genericUnsafeSizeofAdd[T any]() int64 { + return 1<<63 - 1 + int64(unsafe.Sizeof(*new(T))) +} + +func genericUnsafeSizeofAny[T any]() any { + return unsafe.Sizeof(*new(T)) +} + +func TestGenericUnsafeSizeofArithmetic(t *testing.T) { + const minInt64 = -1 << 63 + + tests := []struct { + name string + got int64 + want int64 + }{ + {name: "shift 62", got: genericUnsafeSizeofShift[[62]byte](), want: 1 << 62}, + {name: "shift 63", got: genericUnsafeSizeofShift[[63]byte](), want: minInt64}, + {name: "shift 64", got: genericUnsafeSizeofShift[[64]byte](), want: 0}, + {name: "shift 100", got: genericUnsafeSizeofShift[[100]byte](), want: 0}, + {name: "shift large", got: genericUnsafeSizeofShift[[1e6]byte](), want: 0}, + } + for _, tt := range tests { + if tt.got != tt.want { + t.Fatalf("%s = %d, want %d", tt.name, tt.got, tt.want) + } + } + + if got := genericUnsafeSizeofAdd[[1]byte](); got != minInt64 { + t.Fatalf("add overflow = %d, want %d", got, minInt64) + } + if got := genericUnsafeSizeofAny[[1]byte](); got != uintptr(1) { + t.Fatalf("Sizeof boxed value = %v (%T), want uintptr(1)", got, got) + } + + expectGenericUnsafeSizeofDivideByZero(t, func() { + _ = genericUnsafeSizeofDiv[[0]byte]() + }) +} + +func expectGenericUnsafeSizeofDivideByZero(t *testing.T, f func()) { + t.Helper() + defer func() { + err := recover() + if err == nil { + t.Fatal("divide by zero did not panic") + } + runtimeErr, ok := err.(interface{ RuntimeError() }) + if !ok { + t.Fatalf("panic type = %T, want runtime.Error", err) + } + _ = runtimeErr + msgErr, ok := err.(error) + if !ok { + t.Fatalf("panic type = %T, want error", err) + } + if got := msgErr.Error(); !strings.Contains(got, "divide by zero") { + t.Fatalf("panic = %q, want divide by zero", got) + } + }() + f() +} diff --git a/test/goroot/xfail.yaml b/test/goroot/xfail.yaml index a5a66d10b4..d7525d7c60 100644 --- a/test/goroot/xfail.yaml +++ b/test/goroot/xfail.yaml @@ -3664,10 +3664,6 @@ xfails: directive: run case: fixedbugs/issue53635.go reason: current main goroot run failure on darwin/arm64 - - platform: darwin/arm64 - directive: run - case: fixedbugs/issue60601.go - reason: current main goroot run failure on darwin/arm64 - version: go1.24 platform: darwin/arm64 directive: run @@ -3862,10 +3858,6 @@ xfails: directive: run case: fixedbugs/issue53635.go reason: current main goroot run failure on linux/amd64 - - platform: linux/amd64 - directive: run - case: fixedbugs/issue60601.go - reason: current main goroot run failure on linux/amd64 - version: go1.24 platform: linux/amd64 directive: run