Compare commits
4 Commits
xgopilot/c
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a74ca940e2 | ||
|
|
0c68ae00c9 | ||
|
|
8d6d1b76f2 | ||
|
|
e47728b053 |
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")
|
||||||
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# go/types Issue Test Cases
|
|
||||||
|
|
||||||
This directory contains test cases for issues with the `go/types` package in llgo.
|
|
||||||
|
|
||||||
## Issue #1357: Scope.Insert segmentation fault
|
|
||||||
|
|
||||||
**Status**: Known issue - requires compiler fix
|
|
||||||
|
|
||||||
**Description**: Calling `types.Scope.Insert()` causes a segmentation fault in llgo but works correctly with standard Go.
|
|
||||||
|
|
||||||
**Root Cause**: Compiler bug in llgo's type metadata generation. When stdlib packages (like `go/types`) access their own unexported map fields with interface values, the generated `*abi.MapType` metadata is invalid/null, causing a segfault in runtime map functions.
|
|
||||||
|
|
||||||
**Test Case**: `scope_insert.go`
|
|
||||||
|
|
||||||
**Expected Behavior** (with standard Go):
|
|
||||||
```bash
|
|
||||||
$ go run scope_insert.go
|
|
||||||
=== Scope Insert Test ===
|
|
||||||
|
|
||||||
✓ Insert successful: x
|
|
||||||
✓ Insert failed as expected: x already exists
|
|
||||||
✓ Insert successful: y
|
|
||||||
|
|
||||||
Scope contains 2 objects
|
|
||||||
✓ Scope length check passed
|
|
||||||
|
|
||||||
All objects:
|
|
||||||
- x: int
|
|
||||||
- y: string
|
|
||||||
```
|
|
||||||
|
|
||||||
**Actual Behavior** (with llgo):
|
|
||||||
```bash
|
|
||||||
$ llgo run scope_insert.go
|
|
||||||
=== Scope Insert Test ===
|
|
||||||
|
|
||||||
signal: segmentation fault
|
|
||||||
```
|
|
||||||
|
|
||||||
**Technical Details**:
|
|
||||||
- The issue is in `ssa/abitype.go` (`abiMapOf` function) and `ssa/datastruct.go` (map access operations)
|
|
||||||
- Type metadata for maps with interface values in stdlib packages is not correctly initialized
|
|
||||||
- The `MapAccess1`/`MapAssign` runtime functions receive null/invalid type metadata
|
|
||||||
- This is a self-referential type generation issue specific to stdlib compilation
|
|
||||||
|
|
||||||
**Workaround**:
|
|
||||||
- Avoid using `go/types`, `go/parser`, and `go/ast` packages in llgo programs
|
|
||||||
- Use `reflect` package for runtime type information
|
|
||||||
- Run code analysis with standard Go compiler
|
|
||||||
|
|
||||||
**Related Issues**:
|
|
||||||
- #642 - Tracking stdlib package implementation status
|
|
||||||
|
|
||||||
**For Developers**:
|
|
||||||
This test case should pass once the compiler bug is fixed. It serves as a regression test.
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println("=== Scope Insert Test ===\n")
|
|
||||||
|
|
||||||
// Create a scope
|
|
||||||
scope := types.NewScope(nil, 0, 0, "test")
|
|
||||||
|
|
||||||
// Test 1: Successful insert
|
|
||||||
obj1 := types.NewVar(0, nil, "x", types.Typ[types.Int])
|
|
||||||
if alt := scope.Insert(obj1); alt != nil {
|
|
||||||
panic(fmt.Sprintf("unexpected: insert failed with conflict: %v", alt))
|
|
||||||
}
|
|
||||||
fmt.Printf("✓ Insert successful: %s\n", obj1.Name())
|
|
||||||
|
|
||||||
// Test 2: Duplicate insert (will fail)
|
|
||||||
obj2 := types.NewVar(0, nil, "x", types.Typ[types.String])
|
|
||||||
if alt := scope.Insert(obj2); alt != nil {
|
|
||||||
fmt.Printf("✓ Insert failed as expected: %s already exists\n", alt.Name())
|
|
||||||
} else {
|
|
||||||
panic("unexpected: duplicate insert should have failed")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test 3: Insert different name
|
|
||||||
obj3 := types.NewVar(0, nil, "y", types.Typ[types.String])
|
|
||||||
if alt := scope.Insert(obj3); alt != nil {
|
|
||||||
panic(fmt.Sprintf("unexpected: insert failed with conflict: %v", alt))
|
|
||||||
}
|
|
||||||
fmt.Printf("✓ Insert successful: %s\n", obj3.Name())
|
|
||||||
|
|
||||||
// View results
|
|
||||||
fmt.Printf("\nScope contains %d objects\n", scope.Len())
|
|
||||||
|
|
||||||
// Verify expected count
|
|
||||||
expectedCount := 2 // x and y
|
|
||||||
if scope.Len() != expectedCount {
|
|
||||||
panic(fmt.Sprintf("unexpected: scope should contain %d objects, but has %d", expectedCount, scope.Len()))
|
|
||||||
}
|
|
||||||
fmt.Printf("✓ Scope length check passed\n")
|
|
||||||
|
|
||||||
fmt.Println("\nAll objects:")
|
|
||||||
for _, name := range scope.Names() {
|
|
||||||
obj := scope.Lookup(name)
|
|
||||||
fmt.Printf(" - %s: %v\n", name, obj.Type())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user