Compare commits
4 Commits
xgopilot/c
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a74ca940e2 | ||
|
|
0c68ae00c9 | ||
|
|
8d6d1b76f2 | ||
|
|
e47728b053 |
@@ -1,71 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// Test 1: int8 overflow wrapping
|
|
||||||
var i8max int8 = 127
|
|
||||||
fmt.Printf("int8(127) + 1 = %d\n", i8max+1)
|
|
||||||
|
|
||||||
// Test 2: int8 arithmetic edge cases
|
|
||||||
var a int8 = 100
|
|
||||||
var b int8 = 50
|
|
||||||
fmt.Printf("int8(100) + int8(50) = %d\n", a+b)
|
|
||||||
|
|
||||||
// Test 3: int8 multiplication overflow
|
|
||||||
var m int8 = 64
|
|
||||||
fmt.Printf("int8(64) * 2 = %d\n", m*2)
|
|
||||||
|
|
||||||
// Test 4: uint32 to float64 to int32 conversion
|
|
||||||
var bigUint32 uint32 = 0xFFFFFFFF
|
|
||||||
fmt.Printf("int32(float64(uint32(0xFFFFFFFF))) = %d\n", int32(float64(bigUint32)))
|
|
||||||
|
|
||||||
// Test 5: untyped constant with typed variable
|
|
||||||
const untypedInt = 42
|
|
||||||
var i32 int32 = 70000
|
|
||||||
fmt.Printf("const(42) + int32(70000) = %d\n", untypedInt+i32)
|
|
||||||
|
|
||||||
// Test 6: signed to unsigned conversion
|
|
||||||
var negInt int32 = -1
|
|
||||||
fmt.Printf("uint32(int32(-1)) = 0x%X\n", uint32(negInt))
|
|
||||||
|
|
||||||
// Test 7: unsigned to signed conversion
|
|
||||||
var bigUint uint32 = 0xFFFFFFFF
|
|
||||||
fmt.Printf("int32(uint32(0xFFFFFFFF)) = %d\n", int32(bigUint))
|
|
||||||
|
|
||||||
// Test 8: sign extension
|
|
||||||
var i8 int8 = -1
|
|
||||||
fmt.Printf("int32(int8(-1)) = %d\n", int32(i8))
|
|
||||||
|
|
||||||
// Test 9: truncation
|
|
||||||
var i64 int64 = 0x123456789ABC
|
|
||||||
fmt.Printf("int32(int64(0x123456789ABC)) = 0x%X\n", uint32(int32(i64)))
|
|
||||||
|
|
||||||
// Test 10: more overflow cases
|
|
||||||
var i8min int8 = -128
|
|
||||||
fmt.Printf("int8(-128) - 1 = %d\n", i8min-1)
|
|
||||||
|
|
||||||
var u8max uint8 = 255
|
|
||||||
fmt.Printf("uint8(255) + 1 = %d\n", u8max+1)
|
|
||||||
|
|
||||||
// Test 11: negation overflow
|
|
||||||
var n1 int8 = -128
|
|
||||||
fmt.Printf("-int8(-128) = %d\n", -n1)
|
|
||||||
|
|
||||||
// Test 12: division edge case
|
|
||||||
var d1 int8 = -128
|
|
||||||
var d2 int8 = -1
|
|
||||||
fmt.Printf("int8(-128) / int8(-1) = %d\n", d1/d2)
|
|
||||||
|
|
||||||
// Test 13: int16 overflow
|
|
||||||
var i16max int16 = 32767
|
|
||||||
fmt.Printf("int16(32767) + 1 = %d\n", i16max+1)
|
|
||||||
|
|
||||||
// Test 14: uint8 truncation from int32
|
|
||||||
var negInt8 int32 = -1
|
|
||||||
fmt.Printf("uint8(int32(-1)) = 0x%X\n", uint8(negInt8))
|
|
||||||
|
|
||||||
// Test 15: zero extension
|
|
||||||
var u8 uint8 = 0xFF
|
|
||||||
fmt.Printf("uint32(uint8(0xFF)) = 0x%X\n", uint32(u8))
|
|
||||||
}
|
|
||||||
49
_demo/go/reflectindirect/reflect-indirect.go
Normal file
49
_demo/go/reflectindirect/reflect-indirect.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
x := 42
|
||||||
|
p := &x
|
||||||
|
|
||||||
|
// Test 1: Non-pointer value - should return same value
|
||||||
|
v1 := reflect.Indirect(reflect.ValueOf(x))
|
||||||
|
if !v1.IsValid() || v1.Interface() != 42 {
|
||||||
|
panic("Non-pointer test failed: expected 42")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 2: Pointer - should dereference
|
||||||
|
v2 := reflect.Indirect(reflect.ValueOf(p))
|
||||||
|
if !v2.IsValid() || v2.Interface() != 42 {
|
||||||
|
panic("Pointer dereference test failed: expected 42")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 3: Nil pointer - should return invalid Value
|
||||||
|
var nilPtr *int
|
||||||
|
v3 := reflect.Indirect(reflect.ValueOf(nilPtr))
|
||||||
|
if v3.IsValid() {
|
||||||
|
panic("Nil pointer test failed: expected invalid Value")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 4: Struct value - should return same value
|
||||||
|
type Person struct {
|
||||||
|
Name string
|
||||||
|
Age int
|
||||||
|
}
|
||||||
|
person := Person{Name: "Alice", Age: 30}
|
||||||
|
v4 := reflect.Indirect(reflect.ValueOf(person))
|
||||||
|
if !v4.IsValid() || v4.Interface().(Person).Name != "Alice" || v4.Interface().(Person).Age != 30 {
|
||||||
|
panic("Struct value test failed: expected Person{Name: Alice, Age: 30}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test 5: Struct pointer - should dereference
|
||||||
|
personPtr := &Person{Name: "Bob", Age: 25}
|
||||||
|
v5 := reflect.Indirect(reflect.ValueOf(personPtr))
|
||||||
|
if !v5.IsValid() || v5.Interface().(Person).Name != "Bob" || v5.Interface().(Person).Age != 25 {
|
||||||
|
panic("Struct pointer test failed: expected Person{Name: Bob, Age: 25}")
|
||||||
|
}
|
||||||
|
|
||||||
|
println("PASS")
|
||||||
|
}
|
||||||
@@ -1759,6 +1759,16 @@ func ValueOf(i any) Value {
|
|||||||
return unpackEface(i)
|
return unpackEface(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Indirect returns the value that v points to.
|
||||||
|
// If v is a nil pointer, Indirect returns a zero Value.
|
||||||
|
// If v is not a pointer, Indirect returns v.
|
||||||
|
func Indirect(v Value) Value {
|
||||||
|
if v.Kind() != Pointer {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return v.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
// arrayAt returns the i-th element of p,
|
// arrayAt returns the i-th element of p,
|
||||||
// an array whose elements are eltSize bytes wide.
|
// an array whose elements are eltSize bytes wide.
|
||||||
// The array pointed at by p must have at least i+1 elements:
|
// The array pointed at by p must have at least i+1 elements:
|
||||||
|
|||||||
@@ -1,311 +0,0 @@
|
|||||||
package gotest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestIntegerOverflow tests that integer overflow wraps correctly
|
|
||||||
// Issue #961: Max int8 + 1 should be -128, not 128
|
|
||||||
func TestIntegerOverflow(t *testing.T) {
|
|
||||||
// Use variables to avoid compile-time constant overflow detection
|
|
||||||
var i8max int8 = 127
|
|
||||||
var i8min int8 = -128
|
|
||||||
var u8max uint8 = 255
|
|
||||||
var i16max int16 = 32767
|
|
||||||
var i16min int16 = -32768
|
|
||||||
var u16max uint16 = 65535
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
result interface{}
|
|
||||||
expected interface{}
|
|
||||||
}{
|
|
||||||
{"int8 max + 1", i8max + 1, int8(-128)},
|
|
||||||
{"int8 max + 2", i8max + 2, int8(-127)},
|
|
||||||
{"int8 min - 1", i8min - 1, int8(127)},
|
|
||||||
{"int8 min - 2", i8min - 2, int8(126)},
|
|
||||||
{"uint8 max + 1", u8max + 1, uint8(0)},
|
|
||||||
{"uint8 max + 2", u8max + 2, uint8(1)},
|
|
||||||
{"int16 max + 1", i16max + 1, int16(-32768)},
|
|
||||||
{"int16 min - 1", i16min - 1, int16(32767)},
|
|
||||||
{"uint16 max + 1", u16max + 1, uint16(0)},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if tt.result != tt.expected {
|
|
||||||
t.Errorf("%s: got %v, want %v", tt.name, tt.result, tt.expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestIntegerOverflowOperations tests various overflow operations
|
|
||||||
func TestIntegerOverflowOperations(t *testing.T) {
|
|
||||||
// Multiplication overflow
|
|
||||||
var m1 int8 = 64
|
|
||||||
if result := m1 * 2; result != -128 {
|
|
||||||
t.Errorf("int8(64) * 2 = %d, want -128", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Addition boundary
|
|
||||||
var a1 int8 = 100
|
|
||||||
var a2 int8 = 50
|
|
||||||
if result := a1 + a2; result != -106 {
|
|
||||||
t.Errorf("int8(100) + int8(50) = %d, want -106", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Negation overflow
|
|
||||||
var n1 int8 = -128
|
|
||||||
if result := -n1; result != -128 {
|
|
||||||
t.Errorf("-int8(-128) = %d, want -128", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Division edge case
|
|
||||||
var d1 int8 = -128
|
|
||||||
var d2 int8 = -1
|
|
||||||
if result := d1 / d2; result != -128 {
|
|
||||||
t.Errorf("int8(-128) / int8(-1) = %d, want -128", result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestFloatToIntConversion tests float-to-int conversions
|
|
||||||
// Note: Go has undefined behavior for out-of-range float-to-int conversions
|
|
||||||
// These tests document the actual behavior we observe
|
|
||||||
func TestFloatToIntConversion(t *testing.T) {
|
|
||||||
// Test normal range conversions (well-defined behavior)
|
|
||||||
t.Run("normal range", func(t *testing.T) {
|
|
||||||
input := 123.456
|
|
||||||
if result := int32(input); result != 123 {
|
|
||||||
t.Errorf("int32(%v) = %d, want 123", input, result)
|
|
||||||
}
|
|
||||||
if result := int8(input); result != 123 {
|
|
||||||
t.Errorf("int8(%v) = %d, want 123", input, result)
|
|
||||||
}
|
|
||||||
if result := uint32(input); result != 123 {
|
|
||||||
t.Errorf("uint32(%v) = %d, want 123", input, result)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Out-of-range conversions have undefined behavior in Go
|
|
||||||
// We just document what happens but don't assert specific values
|
|
||||||
t.Run("large positive overflow - undefined behavior", func(t *testing.T) {
|
|
||||||
input := 1e20
|
|
||||||
result32 := int32(input)
|
|
||||||
result8 := int8(input)
|
|
||||||
resultu32 := uint32(input)
|
|
||||||
t.Logf("int32(1e20) = %d (undefined behavior)", result32)
|
|
||||||
t.Logf("int8(1e20) = %d (undefined behavior)", result8)
|
|
||||||
t.Logf("uint32(1e20) = %d (undefined behavior)", resultu32)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("large negative underflow - undefined behavior", func(t *testing.T) {
|
|
||||||
input := -1e20
|
|
||||||
result32 := int32(input)
|
|
||||||
result8 := int8(input)
|
|
||||||
resultu32 := uint32(input)
|
|
||||||
t.Logf("int32(-1e20) = %d (undefined behavior)", result32)
|
|
||||||
t.Logf("int8(-1e20) = %d (undefined behavior)", result8)
|
|
||||||
t.Logf("uint32(-1e20) = %d (undefined behavior)", resultu32)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("negative to unsigned - undefined behavior", func(t *testing.T) {
|
|
||||||
input := -123.456
|
|
||||||
if result := int32(input); result != -123 {
|
|
||||||
t.Errorf("int32(%v) = %d, want -123", input, result)
|
|
||||||
}
|
|
||||||
if result := int8(input); result != -123 {
|
|
||||||
t.Errorf("int8(%v) = %d, want -123", input, result)
|
|
||||||
}
|
|
||||||
// Negative float to unsigned is undefined behavior
|
|
||||||
resultu32 := uint32(input)
|
|
||||||
t.Logf("uint32(-123.456) = %d (undefined behavior)", resultu32)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUint32ToFloatToInt32 tests the specific bug case from issue #961
|
|
||||||
// Note: Conversion of out-of-range float to int has undefined behavior in Go
|
|
||||||
func TestUint32ToFloatToInt32(t *testing.T) {
|
|
||||||
var bigUint32 uint32 = 0xFFFFFFFF // max uint32
|
|
||||||
fBig := float64(bigUint32)
|
|
||||||
result := int32(fBig)
|
|
||||||
|
|
||||||
// The float64 value of max uint32 (4294967295.0) is larger than max int32,
|
|
||||||
// so the conversion has undefined behavior.
|
|
||||||
// We just document what happens without asserting a specific value.
|
|
||||||
t.Logf("uint32(0xFFFFFFFF) -> float64 -> int32 = %d (undefined behavior)", result)
|
|
||||||
t.Logf("float64 value: %f", fBig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestFloatSpecialValues tests special float values (Inf, NaN)
|
|
||||||
// Note: Conversions of Inf and NaN to int have undefined behavior
|
|
||||||
func TestFloatSpecialValues(t *testing.T) {
|
|
||||||
// Positive infinity - undefined behavior
|
|
||||||
fInf := math.Inf(1)
|
|
||||||
result := int32(fInf)
|
|
||||||
t.Logf("int32(+Inf) = %d (undefined behavior)", result)
|
|
||||||
|
|
||||||
// Negative infinity - undefined behavior
|
|
||||||
fNegInf := math.Inf(-1)
|
|
||||||
result = int32(fNegInf)
|
|
||||||
t.Logf("int32(-Inf) = %d (undefined behavior)", result)
|
|
||||||
|
|
||||||
// NaN - behavior is implementation-defined, but should not panic
|
|
||||||
fNaN := math.NaN()
|
|
||||||
result = int32(fNaN)
|
|
||||||
t.Logf("int32(NaN) = %d (undefined behavior, just ensure no panic)", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestSignedUnsignedConversions tests signed/unsigned type conversions
|
|
||||||
func TestSignedUnsignedConversions(t *testing.T) {
|
|
||||||
// Negative to unsigned
|
|
||||||
var negInt int32 = -1
|
|
||||||
if result := uint32(negInt); result != 0xFFFFFFFF {
|
|
||||||
t.Errorf("uint32(int32(-1)) = 0x%X, want 0xFFFFFFFF", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
if result := uint8(negInt); result != 0xFF {
|
|
||||||
t.Errorf("uint8(int32(-1)) = 0x%X, want 0xFF", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Large unsigned to signed
|
|
||||||
var bigUint uint32 = 0xFFFFFFFF
|
|
||||||
if result := int32(bigUint); result != -1 {
|
|
||||||
t.Errorf("int32(uint32(0xFFFFFFFF)) = %d, want -1", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Truncation
|
|
||||||
var i64 int64 = 0x123456789ABC
|
|
||||||
expected := int32(0x56789ABC) // Lower 32 bits
|
|
||||||
if result := int32(i64); result != expected {
|
|
||||||
t.Errorf("int32(int64(0x123456789ABC)) = 0x%X, want 0x%X", uint32(result), uint32(expected))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestSignExtensionVsZeroExtension tests sign vs zero extension
|
|
||||||
func TestSignExtensionVsZeroExtension(t *testing.T) {
|
|
||||||
// Sign extension for signed types
|
|
||||||
var i8 int8 = -1
|
|
||||||
if result := int16(i8); result != -1 {
|
|
||||||
t.Errorf("int16(int8(-1)) = %d, want -1 (sign extension)", result)
|
|
||||||
}
|
|
||||||
if result := int32(i8); result != -1 {
|
|
||||||
t.Errorf("int32(int8(-1)) = %d, want -1 (sign extension)", result)
|
|
||||||
}
|
|
||||||
if result := int64(i8); result != -1 {
|
|
||||||
t.Errorf("int64(int8(-1)) = %d, want -1 (sign extension)", result)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero extension for unsigned types
|
|
||||||
var u8 uint8 = 0xFF
|
|
||||||
if result := uint16(u8); result != 0xFF {
|
|
||||||
t.Errorf("uint16(uint8(0xFF)) = 0x%X, want 0xFF (zero extension)", result)
|
|
||||||
}
|
|
||||||
if result := uint32(u8); result != 0xFF {
|
|
||||||
t.Errorf("uint32(uint8(0xFF)) = 0x%X, want 0xFF (zero extension)", result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestIntToFloatPrecisionLoss tests precision loss in int-to-float conversions
|
|
||||||
func TestIntToFloatPrecisionLoss(t *testing.T) {
|
|
||||||
// 2^53 + 1 exceeds float64 precision
|
|
||||||
var i1 int64 = 9007199254740993
|
|
||||||
f1 := float64(i1)
|
|
||||||
if int64(f1) == i1 {
|
|
||||||
// This might actually be true on some systems due to rounding
|
|
||||||
t.Logf("int64(9007199254740993) -> float64 preserves precision (unexpected but valid)")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2^24 + 1 exceeds float32 precision
|
|
||||||
var i2 int32 = 16777217
|
|
||||||
f2 := float32(i2)
|
|
||||||
if int32(f2) == i2 {
|
|
||||||
t.Logf("int32(16777217) -> float32 preserves precision (unexpected but valid)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestIssue961Examples tests the exact code examples from issue #961
|
|
||||||
// This ensures LLGo produces the same results as standard Go
|
|
||||||
func TestIssue961Examples(t *testing.T) {
|
|
||||||
t.Run("int8 overflow example", func(t *testing.T) {
|
|
||||||
var i8max int8 = 127
|
|
||||||
result := i8max + 1
|
|
||||||
expected := int8(-128)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("Max int8 + 1: got %d, want %d (should wrap to -128)", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("uint32 to float to int32 example", func(t *testing.T) {
|
|
||||||
var bigUint32 uint32 = 0xFFFFFFFF
|
|
||||||
result := int32(float64(bigUint32))
|
|
||||||
// This conversion has undefined behavior in Go
|
|
||||||
t.Logf("uint32 max -> float64 -> int32: %d (undefined behavior)", result)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("untyped constant with typed variable", func(t *testing.T) {
|
|
||||||
const untypedInt = 42
|
|
||||||
var i32 int32 = 70000
|
|
||||||
result := untypedInt + i32
|
|
||||||
expected := int32(70042)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("untypedInt + i32: got %d (type %T), want %d (type int32)", result, result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("int8 arithmetic edge cases", func(t *testing.T) {
|
|
||||||
var a int8 = 100
|
|
||||||
var b int8 = 50
|
|
||||||
result := a + b
|
|
||||||
expected := int8(-106)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("int8(100) + int8(50): got %d, want %d", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("int8 multiplication overflow", func(t *testing.T) {
|
|
||||||
var m int8 = 64
|
|
||||||
result := m * 2
|
|
||||||
expected := int8(-128)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("int8(64) * 2: got %d, want %d", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("signed to unsigned conversion", func(t *testing.T) {
|
|
||||||
var negInt int32 = -1
|
|
||||||
result := uint32(negInt)
|
|
||||||
expected := uint32(0xFFFFFFFF)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("uint32(int32(-1)): got 0x%X, want 0x%X", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("unsigned to signed conversion", func(t *testing.T) {
|
|
||||||
var bigUint uint32 = 0xFFFFFFFF
|
|
||||||
result := int32(bigUint)
|
|
||||||
expected := int32(-1)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("int32(uint32(0xFFFFFFFF)): got %d, want %d", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("sign extension", func(t *testing.T) {
|
|
||||||
var i8 int8 = -1
|
|
||||||
result := int32(i8)
|
|
||||||
expected := int32(-1)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("int32(int8(-1)): got %d, want %d (sign extension)", result, expected)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("truncation", func(t *testing.T) {
|
|
||||||
var i64 int64 = 0x123456789ABC
|
|
||||||
result := int32(i64)
|
|
||||||
expected := int32(0x56789ABC)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("int32(int64(0x123456789ABC)): got 0x%X, want 0x%X (truncation)", uint32(result), uint32(expected))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -1,179 +0,0 @@
|
|||||||
package gotest
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
// TestUntypedConstantWithTypedVariable tests untyped constants in operations with typed variables
|
|
||||||
// Issue #961: Program crashes when using untyped constants with typed variables
|
|
||||||
func TestUntypedConstantWithTypedVariable(t *testing.T) {
|
|
||||||
const untypedInt = 42
|
|
||||||
const untypedFloat = 3.14
|
|
||||||
const untypedComplex = 1 + 2i
|
|
||||||
|
|
||||||
// Test with int32
|
|
||||||
var i32 int32 = 70000
|
|
||||||
result := untypedInt + i32
|
|
||||||
expected := int32(70042)
|
|
||||||
if result != expected {
|
|
||||||
t.Errorf("untypedInt(42) + int32(70000) = %d (type %T), want %d (type int32)", result, result, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with int16 (no overflow)
|
|
||||||
var i16 int16 = 100
|
|
||||||
result16 := untypedInt + i16
|
|
||||||
expected16 := int16(142)
|
|
||||||
if result16 != expected16 {
|
|
||||||
t.Errorf("untypedInt(42) + int16(100) = %d (type %T), want %d (type int16)", result16, result16, expected16)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with float32
|
|
||||||
var f32 float32 = 3.14159
|
|
||||||
resultF32 := untypedFloat + f32
|
|
||||||
expectedF32 := float32(6.28159)
|
|
||||||
if resultF32 < expectedF32-0.00001 || resultF32 > expectedF32+0.00001 {
|
|
||||||
t.Errorf("untypedFloat(3.14) + float32(3.14159) = %f (type %T), want ~%f (type float32)", resultF32, resultF32, expectedF32)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test with complex64
|
|
||||||
var c64 complex64 = 1 + 2i
|
|
||||||
resultC64 := untypedComplex + c64
|
|
||||||
expectedC64 := complex64(2 + 4i)
|
|
||||||
if resultC64 != expectedC64 {
|
|
||||||
t.Errorf("untypedComplex(1+2i) + complex64(1+2i) = %v (type %T), want %v (type complex64)", resultC64, resultC64, expectedC64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedConstantArithmetic tests arithmetic with untyped constants
|
|
||||||
func TestUntypedConstantArithmetic(t *testing.T) {
|
|
||||||
const a = 100
|
|
||||||
const b = 200
|
|
||||||
|
|
||||||
// Basic operations
|
|
||||||
if c := a + b; c != 300 {
|
|
||||||
t.Errorf("100 + 200 = %d, want 300", c)
|
|
||||||
}
|
|
||||||
if d := a * b; d != 20000 {
|
|
||||||
t.Errorf("100 * 200 = %d, want 20000", d)
|
|
||||||
}
|
|
||||||
if e := b / a; e != 2 {
|
|
||||||
t.Errorf("200 / 100 = %d, want 2", e)
|
|
||||||
}
|
|
||||||
if f := b % a; f != 0 {
|
|
||||||
t.Errorf("200 %% 100 = %d, want 0", f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedConstantExpression tests complex constant expressions
|
|
||||||
func TestUntypedConstantExpression(t *testing.T) {
|
|
||||||
const c1 = 1 << 10
|
|
||||||
const c2 = c1 * 1024
|
|
||||||
const c3 = c2 / 3
|
|
||||||
|
|
||||||
if c1 != 1024 {
|
|
||||||
t.Errorf("1 << 10 = %d, want 1024", c1)
|
|
||||||
}
|
|
||||||
if c2 != 1048576 {
|
|
||||||
t.Errorf("(1 << 10) * 1024 = %d, want 1048576", c2)
|
|
||||||
}
|
|
||||||
if c3 != 349525 {
|
|
||||||
t.Errorf("c2 / 3 = %d, want 349525", c3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestMixedUntypedTypedExpressions tests expressions mixing untyped and typed
|
|
||||||
func TestMixedUntypedTypedExpressions(t *testing.T) {
|
|
||||||
const uConst = 10
|
|
||||||
|
|
||||||
var v1 int8 = 5
|
|
||||||
var v2 int16 = 10
|
|
||||||
var v3 int32 = 20
|
|
||||||
|
|
||||||
// These should take the type of the typed variable
|
|
||||||
result1 := uConst + v1
|
|
||||||
if _, ok := interface{}(result1).(int8); !ok {
|
|
||||||
t.Errorf("const(10) + int8(5) should be int8, got %T", result1)
|
|
||||||
}
|
|
||||||
if result1 != 15 {
|
|
||||||
t.Errorf("const(10) + int8(5) = %d, want 15", result1)
|
|
||||||
}
|
|
||||||
|
|
||||||
result2 := uConst + v2
|
|
||||||
if _, ok := interface{}(result2).(int16); !ok {
|
|
||||||
t.Errorf("const(10) + int16(10) should be int16, got %T", result2)
|
|
||||||
}
|
|
||||||
if result2 != 20 {
|
|
||||||
t.Errorf("const(10) + int16(10) = %d, want 20", result2)
|
|
||||||
}
|
|
||||||
|
|
||||||
result3 := uConst + v3
|
|
||||||
if _, ok := interface{}(result3).(int32); !ok {
|
|
||||||
t.Errorf("const(10) + int32(20) should be int32, got %T", result3)
|
|
||||||
}
|
|
||||||
if result3 != 30 {
|
|
||||||
t.Errorf("const(10) + int32(20) = %d, want 30", result3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedBool tests untyped boolean constants
|
|
||||||
func TestUntypedBool(t *testing.T) {
|
|
||||||
const untypedTrue = true
|
|
||||||
const untypedFalse = false
|
|
||||||
|
|
||||||
var b1 bool = untypedTrue
|
|
||||||
var b2 bool = untypedFalse
|
|
||||||
|
|
||||||
if !b1 {
|
|
||||||
t.Error("untypedTrue should be true")
|
|
||||||
}
|
|
||||||
if b2 {
|
|
||||||
t.Error("untypedFalse should be false")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedString tests untyped string constants
|
|
||||||
func TestUntypedString(t *testing.T) {
|
|
||||||
const untypedString = "hello"
|
|
||||||
var s1 string = untypedString
|
|
||||||
|
|
||||||
if s1 != "hello" {
|
|
||||||
t.Errorf("untypedString = %q, want %q", s1, "hello")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedRune tests untyped rune constants
|
|
||||||
func TestUntypedRune(t *testing.T) {
|
|
||||||
const untypedRune = 'A'
|
|
||||||
|
|
||||||
var r1 rune = untypedRune
|
|
||||||
var r2 int32 = untypedRune
|
|
||||||
|
|
||||||
if r1 != 'A' {
|
|
||||||
t.Errorf("untypedRune as rune = %c, want 'A'", r1)
|
|
||||||
}
|
|
||||||
if r2 != 'A' {
|
|
||||||
t.Errorf("untypedRune as int32 = %d, want %d", r2, int32('A'))
|
|
||||||
}
|
|
||||||
if r1 != r2 {
|
|
||||||
t.Errorf("rune and int32 should be the same: %d != %d", r1, r2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestUntypedZeroValues tests untyped zero constants
|
|
||||||
func TestUntypedZeroValues(t *testing.T) {
|
|
||||||
const zero = 0
|
|
||||||
const zeroFloat = 0.0
|
|
||||||
const emptyString = ""
|
|
||||||
|
|
||||||
var iz int32 = zero
|
|
||||||
var fz float64 = zeroFloat
|
|
||||||
var sz string = emptyString
|
|
||||||
|
|
||||||
if iz != 0 {
|
|
||||||
t.Errorf("untyped 0 -> int32 = %d, want 0", iz)
|
|
||||||
}
|
|
||||||
if fz != 0.0 {
|
|
||||||
t.Errorf("untyped 0.0 -> float64 = %f, want 0.0", fz)
|
|
||||||
}
|
|
||||||
if sz != "" {
|
|
||||||
t.Errorf("untyped \"\" -> string = %q, want \"\"", sz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user