Compare commits

...

2 Commits

Author SHA1 Message Date
xgopilot
ac8109ecd2 Move gotypesissue test to _demo folder
Moved test files from _cmptest/gotypesissue/ to _demo/gotypesissue/ as requested.

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: luoliwoshang <luoliwoshang@users.noreply.github.com>
2025-10-20 05:57:13 +00:00
xgopilot
78247e16ad Add regression test for issue #1357: go/types Scope.Insert segfault
This commit adds a documented test case for the segmentation fault that
occurs when using go/types.Scope.Insert() in llgo. The issue is caused
by a compiler bug in type metadata generation for stdlib packages.

The test case includes:
- Reproduction code (scope_insert.go)
- Detailed documentation (README.md) explaining the root cause
- Expected vs actual behavior
- Technical details for future developers
- Workarounds for users

This serves as a regression test that should pass once the compiler
bug in ssa/abitype.go is fixed.

Related: #642

Generated with [codeagent](https://github.com/qbox/codeagent)
Co-authored-by: luoliwoshang <luoliwoshang@users.noreply.github.com>
2025-10-20 04:10:08 +00:00
2 changed files with 106 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
# 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.

View File

@@ -0,0 +1,51 @@
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())
}
}