diff --git a/codebuild.go b/codebuild.go index b3f5c435..67e9f198 100644 --- a/codebuild.go +++ b/codebuild.go @@ -120,18 +120,97 @@ type Label struct { type funcBodyCtx struct { codeBlockCtx - fn *Func - labels map[string]*Label + fn *Func + labels map[string]*Label + usedVars map[*types.Var]bool } func (p *funcBodyCtx) checkLabels(cb *CodeBuilder) { for name, l := range p.labels { if !l.used { - cb.handleCodeErrorf(l.Pos(), l.Pos(), "label %s defined and not used", name) + pos := l.Pos() + cb.handleCodeErrorf(pos, pos+token.Pos(len(name)), "label %s defined and not used", name) } } } +// markVarUsed marks a variable as used. +func (p *funcBodyCtx) markVarUsed(v *types.Var) { + if p.usedVars != nil { + p.usedVars[v] = true + } +} + +// markVarUsedByElem marks a variable as used by looking up the variable from +// the element's Val (which should be an *ast.Ident) in the current scope. +func (p *CodeBuilder) markVarUsedByElem(arg *internal.Elem) { + if ident, ok := arg.Val.(*ast.Ident); ok && ident.Name != "_" { + if _, obj := p.Scope().LookupParent(ident.Name, ident.Pos()); obj != nil { + if v, ok := obj.(*types.Var); ok { + p.current.markVarUsed(v) + } + } + } +} + +func (p *funcBodyCtx) checkUnusedVars(cb *CodeBuilder) { + if p.fn == nil { + return + } + sig := p.fn.Type().(*types.Signature) + skipVars := buildSkipVars(sig) + p.checkUnusedVarsInScope(cb, p.scope, skipVars) +} + +func buildSkipVars(sig *types.Signature) map[*types.Var]bool { + skipVars := make(map[*types.Var]bool) + if recv := sig.Recv(); recv != nil { + skipVars[recv] = true + } + params := sig.Params() + for i := 0; i < params.Len(); i++ { + skipVars[params.At(i)] = true + } + results := sig.Results() + for i := 0; i < results.Len(); i++ { + skipVars[results.At(i)] = true + } + return skipVars +} + +func (p *funcBodyCtx) checkUnusedVarsInScope(cb *CodeBuilder, scope *types.Scope, skipVars map[*types.Var]bool) { + const funcLitScopePrefix = "func " + + for _, name := range scope.Names() { + obj := scope.Lookup(name) + if !obj.Pos().IsValid() { + continue + } + v, ok := obj.(*types.Var) + if !ok { + continue + } + // Skip receiver, parameters, and results. + if skipVars[v] { + continue + } + if !p.usedVars[v] { + pos := v.Pos() + cb.handleCodeErrorf(pos, pos+token.Pos(len(name)), "%s declared and not used", name) + } + } + // Recursively check child scopes, but skip function literal scopes + // (they are handled when the closure is compiled). + for i := 0; i < scope.NumChildren(); i++ { + child := scope.Child(i) + // Skip function literal scopes. + if strings.HasPrefix(child.String(), funcLitScopePrefix) { + continue + } + p.checkUnusedVarsInScope(cb, child, skipVars) + } +} + type CodeError struct { Fset dbgPositioner Pos, End token.Pos @@ -270,12 +349,13 @@ func (p *CodeBuilder) Pkg() *Package { func (p *CodeBuilder) startFuncBody(fn *Func, src []ast.Node, old *funcBodyCtx) *CodeBuilder { p.current.fn, old.fn = fn, p.current.fn p.current.labels, old.labels = nil, p.current.labels + p.current.usedVars, old.usedVars = make(map[*types.Var]bool), p.current.usedVars p.startBlockStmt(fn, src, "func "+fn.Name(), &old.codeBlockCtx) scope := p.current.scope sig := fn.Type().(*types.Signature) insertParams(scope, sig.Params()) insertParams(scope, sig.Results()) - if recv := sig.Recv(); recv != nil { + if recv := sig.Recv(); recv != nil && recv.Name() != "_" { scope.Insert(recv) } return p @@ -292,8 +372,18 @@ func insertParams(scope *types.Scope, params *types.Tuple) { func (p *CodeBuilder) endFuncBody(old funcBodyCtx) []ast.Stmt { p.current.checkLabels(p) + p.current.checkUnusedVars(p) + // Merge current usedVars into parent for multi-level closure propagation. + // This ensures variables used in deeply nested closures are marked as used + // in all ancestor functions. + if old.usedVars != nil { + for v := range p.current.usedVars { + old.usedVars[v] = true + } + } p.current.fn = old.fn p.current.labels = old.labels + p.current.usedVars = old.usedVars stmts, _ := p.endBlockStmt(&old.codeBlockCtx) return stmts } @@ -707,10 +797,12 @@ func (p *CodeBuilder) NewAutoVar(pos, end token.Pos, name string, pv **types.Var p.emitStmt(stmt) typ := &unboundType{ptypes: []*ast.Expr{&spec.Type}} *pv = types.NewVar(pos, p.pkg.Types, name, typ) - if old := p.current.scope.Insert(*pv); old != nil { - oldPos := p.fset.Position(old.Pos()) - p.panicCodeErrorf( - pos, end, "%s redeclared in this block\n\tprevious declaration at %v", name, oldPos) + if name != "_" { + if old := p.current.scope.Insert(*pv); old != nil { + oldPos := p.fset.Position(old.Pos()) + p.panicCodeErrorf( + pos, end, "%s redeclared in this block\n\tprevious declaration at %v", name, oldPos) + } } return p } @@ -1426,6 +1518,10 @@ func (p *CodeBuilder) Val(v interface{}, src ...ast.Node) *CodeBuilder { } } } + // Mark variable as used for unused variable detection. + if va, ok := v.(*types.Var); ok { + p.current.markVarUsed(va) + } return p.pushVal(v, getSrc(src)) } @@ -2027,6 +2123,8 @@ func (p *CodeBuilder) IncDec(op token.Token, src ...ast.Node) *CodeBuilder { } pkg := p.pkg arg := p.stk.Pop() + // IncDec reads the variable value, so mark it as used. + p.markVarUsedByElem(arg) if t, ok := arg.Type.(*refType).typ.(*types.Named); ok { op := lookupMethod(t, name) if op != nil { @@ -2060,6 +2158,8 @@ var ( // AssignOp func func (p *CodeBuilder) AssignOp(op token.Token, src ...ast.Node) *CodeBuilder { args := p.stk.GetArgs(2) + // Compound assignment (+=, -=, etc.) reads the variable, so mark it as used. + p.markVarUsedByElem(args[0]) stmt := callAssignOp(p.pkg, op, args, src) p.emitStmt(stmt) p.stk.PopN(2) @@ -2276,7 +2376,12 @@ func (p *CodeBuilder) UnaryOp(op token.Token, params ...interface{}) *CodeBuilde if debugInstr { log.Println("UnaryOp", op, "flags:", flags) } - ret, err := doUnaryOp(p, op, p.stk.GetArgs(1), flags) + args := p.stk.GetArgs(1) + // Taking address of a variable counts as using it. + if op == token.AND { + p.markVarUsedByElem(args[0]) + } + ret, err := doUnaryOp(p, op, args, flags) if err != nil { panic(err) } diff --git a/error_msg_test.go b/error_msg_test.go index 1a816d3f..55d97fd4 100644 --- a/error_msg_test.go +++ b/error_msg_test.go @@ -725,6 +725,7 @@ func TestErrMissingReturn(t *testing.T) { ret := pkg.NewParam(position(1, 10), "", types.Typ[types.Int]) newFunc(pkg, 1, 5, 3, 1, nil, "foo", nil, types.NewTuple(ret), false).BodyStart(pkg). NewVar(types.Typ[types.Int], "x"). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). End(source("}", 3, 1)) }) // Function with return value, has if but no else @@ -798,6 +799,7 @@ func TestMissingReturnValid(t *testing.T) { pkg = newMainPackage() newFunc(pkg, 1, 5, 3, 1, nil, "foo", nil, nil, false).BodyStart(pkg). NewVar(types.Typ[types.Int], "x"). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). End() // Closure with return - should not error @@ -810,6 +812,243 @@ func TestMissingReturnValid(t *testing.T) { End() } +func newMainPackageWithUnusedVarCheck() *gogen.Package { + conf := &gogen.Config{ + Fset: gblFset, + Importer: gblImp, + NodeInterpreter: nodeInterp{}, + DbgPositioner: nodeInterp{}, + } + return gogen.NewPackage("", "main", conf) +} + +func TestErrUnusedVar(t *testing.T) { + // Simple unused variable + t.Run("SimpleUnusedVar", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + codeErrorTestEx(t, pkg, "./foo.gop:2:5: x declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 3, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + DefineVarStart(position(2, 5), "x").Val(0).EndInit(1). + End() + }) + }) + + // Unused variable in nested scope (if block) + t.Run("UnusedVarInNestedScope", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + codeErrorTestEx(t, pkg, "./foo.gop:3:5: y declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 5, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + If().Val(true).Then(). + /**/ DefineVarStart(position(3, 5), "y").Val(0).EndInit(1). + /**/ End(). + End() + }) + }) + + // Multiple unused variables - first one is reported + t.Run("MultipleUnusedVars", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + codeErrorTestEx(t, pkg, "./foo.gop:2:5: a declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 4, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + DefineVarStart(position(2, 5), "a").Val(0).EndInit(1). + DefineVarStart(position(3, 5), "b").Val(0).EndInit(1). + End() + }) + }) + + // Unused variable in for range loop + t.Run("UnusedVarInForRange", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + tySlice := types.NewSlice(types.Typ[types.Int]) + codeErrorTestEx(t, pkg, "./foo.gop:3:5: k declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 5, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + NewVarStart(tySlice, "a").ZeroLit(tySlice).EndInit(1). + ForRange("k", "v").VarVal("a").RangeAssignThen(position(3, 5)). + /**/ Val(pkg.Builtin().Ref("println")).VarVal("v").Call(1).EndStmt(). + /**/ End(). + End() + }) + }) + + // Unused variable in type switch + t.Run("UnusedVarInTypeSwitch", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + v := pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface) + codeErrorTestEx(t, pkg, "./foo.gop:3:2: x declared and not used", func(pkg *gogen.Package) { + pkg.NewFunc(nil, "foo", types.NewTuple(v), nil, false).BodyStart(pkg). + TypeSwitch("x").VarVal("v").TypeAssertThen(). + /**/ TypeCase().Typ(types.Typ[types.Int]).Then(source("case int:", 3, 2)). + /****/ Val(pkg.Builtin().Ref("println")).Val("int").Call(1).EndStmt(). + /**/ End(). + /**/ End(). + End() + }) + }) + + // Unused variable in select case + t.Run("UnusedVarInSelect", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + tyXchg := types.NewChan(types.SendRecv, types.Typ[types.Int]) + codeErrorTestEx(t, pkg, "./foo.gop:4:7: x declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 7, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + NewVarStart(tyXchg, "xchg").ZeroLit(tyXchg).EndInit(1). + Select(). + /**/ CommCase().DefineVarStart(position(4, 7), "x").VarVal("xchg").UnaryOp(token.ARROW).EndInit(1).Then(). + /****/ Val(pkg.Builtin().Ref("println")).Val("received").Call(1).EndStmt(). + /**/ End(). + /**/ End(). + End() + }) + }) + + // Unused variable in for loop init + t.Run("UnusedVarInForInit", func(t *testing.T) { + pkg := newMainPackageWithUnusedVarCheck() + codeErrorTestEx(t, pkg, "./foo.gop:2:5: i declared and not used", func(pkg *gogen.Package) { + newFunc(pkg, 1, 5, 5, 1, nil, "foo", nil, nil, false).BodyStart(pkg). + For().DefineVarStart(position(2, 5), "i").Val(0).EndInit(1). + /**/ None().Then(). + /**/ Break(nil). + /**/ End(). + End() + }) + }) +} + +func TestUnusedVarValid(t *testing.T) { + // Create a package with unused variable check enabled + conf := &gogen.Config{ + Fset: gblFset, + Importer: gblImp, + NodeInterpreter: nodeInterp{}, + DbgPositioner: nodeInterp{}, + } + pkg := gogen.NewPackage("", "main", conf) + + // Variable is used - should not error + pkg.NewFunc(nil, "test1", nil, nil, false).BodyStart(pkg). + NewVar(types.Typ[types.Int], "x"). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). + End() + + // Variable used in expression - should not error + pkg.NewFunc(nil, "test2", nil, nil, false).BodyStart(pkg). + NewVar(types.Typ[types.Int], "y"). + VarRef(nil).VarVal("y").Val(1).BinaryOp(token.ADD).Assign(1).EndStmt(). + End() + + // Function parameter - should not be checked + ret := pkg.NewParam(token.NoPos, "result", types.Typ[types.Int]) + pkg.NewFunc(nil, "test3", nil, types.NewTuple(ret), false).BodyStart(pkg). + Val(0).Return(1). + End() + + // Variable used in single-level closure - should not error + pkg.NewFunc(nil, "test4", nil, nil, false).BodyStart(pkg). + DefineVarStart(token.NoPos, "x").Val(1).EndInit(1). + NewClosure(nil, nil, false).BodyStart(pkg). + Val(pkg.Builtin().Ref("println")).VarVal("x").Call(1).EndStmt(). + End().Call(0).EndStmt(). + End() + + // Variable used in double-level nested closure - should not error + pkg.NewFunc(nil, "test5", nil, nil, false).BodyStart(pkg). + DefineVarStart(token.NoPos, "y").Val(2).EndInit(1). + NewClosure(nil, nil, false).BodyStart(pkg). + NewClosure(nil, nil, false).BodyStart(pkg). + Val(pkg.Builtin().Ref("println")).VarVal("y").Call(1).EndStmt(). + End().Call(0).EndStmt(). + End().Call(0).EndStmt(). + End() + + // Variable used in triple-level nested closure - should not error + pkg.NewFunc(nil, "test6", nil, nil, false).BodyStart(pkg). + DefineVarStart(token.NoPos, "z").Val(3).EndInit(1). + NewClosure(nil, nil, false).BodyStart(pkg). + NewClosure(nil, nil, false).BodyStart(pkg). + NewClosure(nil, nil, false).BodyStart(pkg). + Val(pkg.Builtin().Ref("println")).VarVal("z").Call(1).EndStmt(). + End().Call(0).EndStmt(). + End().Call(0).EndStmt(). + End().Call(0).EndStmt(). + End() + + // For range variables used - should not error + pkg.NewFunc(nil, "test7", nil, nil, false).BodyStart(pkg). + NewVar(types.NewSlice(types.Typ[types.Int]), "a"). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). + ForRange("k", "v").VarVal("a").RangeAssignThen(token.NoPos). + /**/ Val(pkg.Builtin().Ref("println")).VarVal("k").VarVal("v").Call(2).EndStmt(). + /**/ End(). + End() + + // Type switch variable used - should not error + v := pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface) + pkg.NewFunc(nil, "test8", types.NewTuple(v), nil, false).BodyStart(pkg). + TypeSwitch("x").VarVal("v").TypeAssertThen(). + /**/ TypeCase().Typ(types.Typ[types.Int]).Then(). + /****/ Val(pkg.Builtin().Ref("println")).VarVal("x").Call(1).EndStmt(). + /**/ End(). + /**/ End(). + End() + + // Select receive variable used - should not error + tyXchg := types.NewChan(types.SendRecv, types.Typ[types.Int]) + pkg.NewFunc(nil, "test9", nil, nil, false).BodyStart(pkg). + NewVar(tyXchg, "xchg"). + VarRef(nil).VarVal("xchg").Assign(1).EndStmt(). + Select(). + /**/ CommCase().DefineVarStart(0, "x").VarVal("xchg").UnaryOp(token.ARROW).EndInit(1).Then(). + /****/ Val(pkg.Builtin().Ref("println")).VarVal("x").Call(1).EndStmt(). + /**/ End(). + /**/ End(). + End() + + // For loop init variable used - should not error + pkg.NewFunc(nil, "test10", nil, nil, false).BodyStart(pkg). + For().DefineVarStart(0, "i").Val(0).EndInit(1). + /**/ VarVal("i").Val(10).BinaryOp(token.LSS).Then(). + /**/ Val(pkg.Builtin().Ref("println")).VarVal("i").Call(1).EndStmt(). + /**/ Post(). + /**/ VarRef(ctxRef(pkg, "i")).VarVal("i").Val(1).BinaryOp(token.ADD).Assign(1).EndStmt(). + /**/ End(). + End() + + // Blank identifier in type switch - should not error + v2 := pkg.NewParam(token.NoPos, "v", gogen.TyEmptyInterface) + pkg.NewFunc(nil, "test11", types.NewTuple(v2), nil, false).BodyStart(pkg). + TypeSwitch("_").VarVal("v").TypeAssertThen(). + /**/ TypeCase().Typ(types.Typ[types.Int]).Then(source("case int:", 3, 2)). + /****/ Val(pkg.Builtin().Ref("println")).Val("int").Call(1).EndStmt(). + /**/ End(). + /**/ End(). + End() + + // Blank identifier as receiver - should not error + tyT := pkg.NewType("T").InitType(pkg, types.Typ[types.Int]) + recv := pkg.NewParam(position(1, 7), "_", tyT) + pkg.NewFunc(recv, "method", nil, nil, false).BodyStart(pkg). + End() + + // Blank identifier as parameter - should not error + blankParam := pkg.NewParam(position(1, 10), "_", types.Typ[types.Int]) + pkg.NewFunc(nil, "test12", types.NewTuple(blankParam), nil, false).BodyStart(pkg). + End() + + // Blank identifier in for range - should not error + tySlice2 := types.NewSlice(types.Typ[types.Int]) + pkg.NewFunc(nil, "test13", nil, nil, false).BodyStart(pkg). + NewVarStart(tySlice2, "s").ZeroLit(tySlice2).EndInit(1). + ForRange("_", "v").VarVal("s").RangeAssignThen(position(3, 5)). + /**/ Val(pkg.Builtin().Ref("println")).VarVal("v").Call(1).EndStmt(). + /**/ End(). + End() + + // Blank identifier as function name - should not error + pkg.NewFunc(nil, "_", nil, nil, false).BodyStart(pkg). + End() +} + func TestErrRecv(t *testing.T) { tySlice := types.NewSlice(gogen.TyByte) codeErrorTest(t, "./foo.gop:1:9: invalid receiver type []byte ([]byte is not a defined type)", func(pkg *gogen.Package) { diff --git a/package_test.go b/package_test.go index 48a46934..80e93af5 100644 --- a/package_test.go +++ b/package_test.go @@ -479,11 +479,13 @@ func TestMake(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVarStart(tySlice, "a").Val(pkg.Builtin().Ref("make")). /**/ Typ(tySlice).Val(0).Val(2).Call(3).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { var a []int = make([]int, 0, 2) + _ = a } `) } @@ -494,11 +496,13 @@ func TestNew(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVarStart(types.NewPointer(tyInt), "a").Val(pkg.Builtin().Ref("new")). Val(ctxRef(pkg, "int")).Call(1).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { var a *int = new(int) + _ = a } `) } @@ -510,12 +514,16 @@ func TestTypeConv(t *testing.T) { // TypeCast pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVarStart(tyInt, "a").Typ(tyInt).Val(0).Call(1).EndInit(1). NewVarStart(tyPInt, "b").Typ(tyPInt).Val(nil).Call(1).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { var a uint32 = uint32(0) var b *uint32 = (*uint32)(nil) + _ = a + _ = b } `) } @@ -527,6 +535,7 @@ func TestTypeConvBool(t *testing.T) { // TypeCast pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVarStart(tyBool, "a").Val(false).EndInit(1). NewVarStart(tyInt, "b").Typ(tyInt).VarVal("a").Call(1).EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -539,6 +548,7 @@ func main() { return 0 } }() + _ = b } `) } @@ -592,6 +602,9 @@ func TestRecv(t *testing.T) { NewVar(tyChan, "a"). NewVarStart(types.Typ[types.Uint], "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1). DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true, nil).EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). + VarRef(nil).VarVal("ok").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -599,6 +612,9 @@ func main() { var a chan uint var b uint = <-a c, ok := <-a + _ = b + _ = c + _ = ok } `) } @@ -611,6 +627,9 @@ func TestRecv2(t *testing.T) { NewVar(typ, "a"). NewVarStart(types.Typ[types.Uint], "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1). DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true).EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). + VarRef(nil).VarVal("ok").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -620,6 +639,9 @@ func main() { var a T var b uint = <-a c, ok := <-a + _ = b + _ = c + _ = ok } `) } @@ -633,6 +655,9 @@ func TestRecv3(t *testing.T) { NewVar(typ, "a"). NewVarStart(tyUint, "b").VarVal("a").UnaryOp(token.ARROW).EndInit(1). DefineVarStart(0, "c", "ok").VarVal("a").UnaryOp(token.ARROW, true).EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). + VarRef(nil).VarVal("ok").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -643,6 +668,9 @@ func main() { var a T var b Uint = <-a c, ok := <-a + _ = b + _ = c + _ = ok } `) } @@ -658,6 +686,7 @@ func TestZeroLit(t *testing.T) { /******/ Val(ctxRef(pkg, "ret")).Val("Hi").IndexRef(1).Val(1).Assign(1). /******/ Return(0). /**/ End().Call(0).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -667,6 +696,7 @@ func main() { ret["Hi"] = 1 return }() + _ = a } `) } @@ -707,6 +737,15 @@ func TestZeroLitAllTypes(t *testing.T) { NewVarStart(tyUP, "g").ZeroLit(tyUP).EndInit(1). NewVarStart(gogen.TyEmptyInterface, "h").ZeroLit(gogen.TyEmptyInterface).EndInit(1). NewVarStart(tyArray, "i").ZeroLit(tyArray).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). + VarRef(nil).VarVal("d").Assign(1).EndStmt(). + VarRef(nil).VarVal("e").Assign(1).EndStmt(). + VarRef(nil).VarVal("f").Assign(1).EndStmt(). + VarRef(nil).VarVal("g").Assign(1).EndStmt(). + VarRef(nil).VarVal("h").Assign(1).EndStmt(). + VarRef(nil).VarVal("i").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -722,6 +761,15 @@ func main() { var g unsafe.Pointer = nil var h interface{} = nil var i [10]int = [10]int{} + _ = a + _ = b + _ = c + _ = d + _ = e + _ = f + _ = g + _ = h + _ = i } `) } @@ -937,12 +985,18 @@ func TestTypeAssert(t *testing.T) { pkg.NewFunc(nil, "foo", params, nil, false).BodyStart(pkg, source("{}", 1, 5)). DefineVarStart(0, "x").VarVal("v").TypeAssert(types.Typ[types.Int], false).EndInit(1). DefineVarStart(0, "y", "ok").VarVal("v").TypeAssert(types.Typ[types.String], true).EndInit(1). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). + VarRef(nil).VarVal("y").Assign(1).EndStmt(). + VarRef(nil).VarVal("ok").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func foo(v interface{}) { x := v.(int) y, ok := v.(string) + _ = x + _ = y + _ = ok } `) } @@ -964,6 +1018,7 @@ func TestTypeSwitch(t *testing.T) { /****/ End(). /**/ TypeCase().Typ(types.Typ[types.Bool]).Then(). /******/ NewVarStart(types.Typ[types.Bool], "x").Val(ctxRef(pkg, "t")).EndInit(1). + /******/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). /****/ End(). /****/ TypeDefaultThen(). /******/ Val(ctxRef(pkg, "bar")).VarRef(ctxRef(pkg, "t")).UnaryOp(token.AND).Call(1).EndStmt(). @@ -979,6 +1034,7 @@ func foo(v interface{}) { bar(&t) case bool: var x bool = t + _ = x default: bar(&t) } @@ -1019,12 +1075,15 @@ func TestSelect(t *testing.T) { /**/ Select(). /****/ CommCase().DefineVarStart(0, "x").Val(ctxRef(pkg, "xchg")).UnaryOp(token.ARROW).EndInit(1).Then(). /******/ NewVarStart(types.Typ[types.Int], "t").Val(ctxRef(pkg, "x")).EndInit(1). + /******/ VarRef(nil).VarVal("t").Assign(1).EndStmt(). /****/ End(). /****/ CommCase().Val(ctxRef(pkg, "xchg")).Val(1).Send().Then(). /******/ DefineVarStart(0, "x").Val(1).EndInit(1). + /******/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). /****/ End(). /****/ CommDefaultThen(). /******/ DefineVarStart(0, "x").Val("Hi").EndInit(1). + /******/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). /****/ End(). /**/ End(). End() @@ -1035,10 +1094,13 @@ func main() { select { case x := <-xchg: var t int = x + _ = t case xchg <- 1: x := 1 + _ = x default: x := "Hi" + _ = x } } `) @@ -1243,12 +1305,18 @@ func TestBlockStmt(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). Block(). /**/ NewVar(types.Typ[types.String], "x", "y"). + /**/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). + /**/ VarRef(nil).VarVal("y").Assign(1).EndStmt(). End(). Block(). /**/ DefineVarStart(token.NoPos, "x", "y").Val(1).Val(4.0).EndInit(2). + /**/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). + /**/ VarRef(nil).VarVal("y").Assign(1).EndStmt(). End(). VBlock(). /**/ DefineVarStart(token.NoPos, "x", "y").Val(10).Val(100).EndInit(2). + /**/ VarRef(nil).VarVal("x").Assign(1).EndStmt(). + /**/ VarRef(nil).VarVal("y").Assign(1).EndStmt(). /**/ Debug(func(cb *gogen.CodeBuilder) { if !cb.InVBlock() { t.Fatal("InVBlock: false?") @@ -1266,11 +1334,17 @@ func TestBlockStmt(t *testing.T) { func main() { { var x, y string + _ = x + _ = y } { x, y := 1, 4.0 + _ = x + _ = y } x, y := 10, 100 + _ = x + _ = y } `) safeRun(t, func() { @@ -1512,6 +1586,10 @@ func TestVarDeclInFunc(t *testing.T) { NewVar(types.Typ[types.String], "x", "y"). NewVarStart(nil, "a", "_").Val(1).Val(2).BinaryOp(token.ADD).Val("Hi").EndInit(2). NewVarStart(nil, "n", "_").Val(fmt.Ref("Println")).Val(2).Call(1).EndInit(1). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). + VarRef(nil).VarVal("y").Assign(1).EndStmt(). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). + VarRef(nil).VarVal("n").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -1521,6 +1599,10 @@ func main() { var x, y string var a, _ = 1 + 2, "Hi" var n, _ = fmt.Println(2) + _ = x + _ = y + _ = a + _ = n } `) } @@ -1531,6 +1613,8 @@ func TestDefineVar(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVar(types.Typ[types.Int], "n"). DefineVarStart(0, "n", "err").Val(fmt.Ref("Println")).Val(2).Call(1).EndInit(1). + VarRef(nil).VarVal("n").Assign(1).EndStmt(). + VarRef(nil).VarVal("err").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -1539,6 +1623,8 @@ import "fmt" func main() { var n int n, err := fmt.Println(2) + _ = n + _ = err } `) } @@ -1687,6 +1773,7 @@ func TestBuiltinFunc(t *testing.T) { /**/ Assign(1).EndStmt(). VarRef(n).Val(builtin.Ref("len")).Val(a).Call(1).Assign(1).EndStmt(). VarRef(n).Val(builtin.Ref("cap")).Val(array).Call(1).Assign(1).EndStmt(). + VarRef(nil).Val(n).Assign(1).EndStmt(). End() pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End() domTest(t, pkg, `package main @@ -1697,6 +1784,7 @@ func foo(v []int, array [10]int) { a = append(v, 1, 2) n = len(a) n = cap(array) + _ = n } func main() { } @@ -1798,11 +1886,13 @@ func TestCopyString(t *testing.T) { pkg.NewFunc(nil, "foo", gogen.NewTuple(pkg.NewParam(token.NoPos, "a", tySlice)), nil, false).BodyStart(pkg). NewVarStart(types.Typ[types.Int], "n").Val(builtin.Ref("copy")). VarVal("a").Val("Hi").Call(2).EndInit(1). + VarRef(nil).VarVal("n").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func foo(a []uint8) { var n int = copy(a, "Hi") + _ = n } `) } @@ -1823,7 +1913,7 @@ func TestUnsafeFunc(t *testing.T) { VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Sizeof")).VarVal("a").Call(1).Assign(1).EndStmt(). VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Alignof")).VarVal("a").Call(1).Assign(1).EndStmt(). VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Offsetof")).VarVal("a").MemberVal("y").Call(1).Assign(1).EndStmt(). - Val(builtin.Ref("println")).VarRef(ctxRef(pkg, "r")).Call(1).EndStmt(). + Val(builtin.Ref("println")).VarVal("r").Call(1).EndStmt(). End() domTest(t, pkg, `package main @@ -1858,7 +1948,7 @@ func TestUnsafeFunc2(t *testing.T) { NewVar(types.NewSlice(tyInt), "r2"). VarRef(ctxRef(pkg, "r")).Val(unsafe.Ref("Add")).VarVal("a").Val(10).Call(2).Assign(1).EndStmt(). VarRef(ctxRef(pkg, "r2")).Val(unsafe.Ref("Slice")).Val(ctxRef(pkg, "ar")).Val(0).Index(1, false).UnaryOp(token.AND).Val(3).Call(2).Assign(1).EndStmt(). - Val(builtin.Ref("println")).VarRef(ctxRef(pkg, "r")).VarRef(ctxRef(pkg, "r2")).Call(2).EndStmt(). + Val(builtin.Ref("println")).VarVal("r").VarVal("r2").Call(2).EndStmt(). End() domTest(t, pkg, `package main @@ -2850,6 +2940,8 @@ func TestOverloadFunc(t *testing.T) { VarRef(g).Val(builtin.Ref("real")).Val(c64).Call(1).Assign(1).EndStmt(). VarRef(x).Val(builtin.Ref("complex")).Val(0).Val(f).Call(2).Assign(1).EndStmt(). VarRef(y).Val(builtin.Ref("complex")).Val(g).Val(1).Call(2).Assign(1).EndStmt(). + VarRef(nil).Val(x).Assign(1).EndStmt(). + VarRef(nil).Val(y).Assign(1).EndStmt(). End() pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End() domTest(t, pkg, `package main @@ -2863,6 +2955,8 @@ func foo(c64 complex64, c128 complex128) { g = real(c64) x = complex(0, f) y = complex(g, 1) + _ = x + _ = y } func main() { } @@ -2922,6 +3016,8 @@ func TestOverloadMethod2(t *testing.T) { cb.Member("attr", gogen.MemberFlagMethodAlias) }). Val("key").Call(1).EndInit(1).EndStmt(). + VarRef(nil).VarVal("val").Assign(1).EndStmt(). + VarRef(nil).VarVal("err").Assign(1).EndStmt(). Val(v). Debug(func(cb *gogen.CodeBuilder) { cb.Member("len", gogen.MemberFlagAutoProperty) @@ -2934,6 +3030,8 @@ import "github.com/goplus/gogen/internal/foo" func bar(v foo.NodeSet) { val, err := v.Attr__0("key") + _ = val + _ = err v.Len__0() v = v.Attr__1("key", "val") } @@ -2954,6 +3052,8 @@ func TestOverloadInterfaceMethod(t *testing.T) { cb.Member("attr", gogen.MemberFlagMethodAlias) }). Val("key").Call(1).EndInit(1).EndStmt(). + VarRef(nil).VarVal("val").Assign(1).EndStmt(). + VarRef(nil).VarVal("err").Assign(1).EndStmt(). Val(v). Debug(func(cb *gogen.CodeBuilder) { cb.Member("len", gogen.MemberFlagAutoProperty) @@ -2966,6 +3066,8 @@ import "github.com/goplus/gogen/internal/foo" func bar(v foo.NodeSeter) { val, err := v.Attr__0("key") + _ = val + _ = err v.Len__0() v = v.Attr__1("key", "val") } @@ -3140,6 +3242,12 @@ func TestSlice(t *testing.T) { NewVarStart(tyString, "d").Val(y).Val(1).Val(3).Slice(false).EndInit(1). NewVarStart(tySlice, "e").Val(p).None().Val(5).Slice(false).EndInit(1). NewVarStart(tySlice, "f").Val(z).None().Val(5).Slice(false).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). + VarRef(nil).VarVal("d").Assign(1).EndStmt(). + VarRef(nil).VarVal("e").Assign(1).EndStmt(). + VarRef(nil).VarVal("f").Assign(1).EndStmt(). End() pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).End() @@ -3152,6 +3260,12 @@ func foo(p *[10]int, x []int, y string, z [10]int) { var d string = y[1:3] var e []int = p[:5] var f []int = z[:5] + _ = a + _ = b + _ = c + _ = d + _ = e + _ = f } func main() { } @@ -3166,6 +3280,8 @@ func TestIndex(t *testing.T) { ret := pkg.NewParam(token.NoPos, "", types.Typ[types.Int]) pkg.NewFunc(nil, "foo", gogen.NewTuple(x, y), gogen.NewTuple(ret), false).BodyStart(pkg). DefineVarStart(0, "v", "ok").Val(y).Val("a").Index(1, true).EndInit(1). + VarRef(nil).VarVal("v").Assign(1).EndStmt(). + VarRef(nil).VarVal("ok").Assign(1).EndStmt(). Val(x).Val(0).Index(1, false).Return(1). End() @@ -3174,6 +3290,8 @@ func TestIndex(t *testing.T) { func foo(x []int, y map[string]int) int { v, ok := y["a"] + _ = v + _ = ok return x[0] } func main() { @@ -3217,12 +3335,14 @@ func TestStar(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). DefineVarStart(0, "a").Typ(tyInt).Star().Val(nil).Call(1).EndInit(1). NewVarStart(tyInt, "b").VarVal("a").Star().EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { a := (*uint32)(nil) var b uint32 = *a + _ = b } `) } @@ -3254,6 +3374,7 @@ func TestAssign(t *testing.T) { Val("Hi").Val(3).Val(true).Val('!').Val(1.2).Val(&ast.BasicLit{Kind: token.FLOAT, Value: "12.3"}). Assign(6).EndStmt(). VarRef(c).Val(b).Assign(1).EndStmt(). + VarRef(nil).VarRef(nil).VarRef(nil).VarRef(nil).VarRef(nil).VarRef(nil).Val(a).Val(c).Val(d).Val(e).Val(f).Val(g).Assign(6).EndStmt(). End() domTest(t, pkg, `package main @@ -3267,6 +3388,7 @@ func main() { var g float64 a, b, d, e, f, g = "Hi", 3, true, '!', 1.2, 12.3 c = b + _, _, _, _, _, _ = a, c, d, e, f, g } `) } @@ -3280,6 +3402,7 @@ func TestAssignFnCall(t *testing.T) { VarRef(n).VarRef(err). Val(fmt.Ref("Println")).Val("Hello").Call(1). Assign(2, 1).EndStmt(). + VarRef(nil).VarRef(nil).Val(n).Val(err).Assign(2).EndStmt(). End() domTest(t, pkg, `package main @@ -3289,6 +3412,7 @@ func main() { var n int var err error n, err = fmt.Println("Hello") + _, _ = n, err } `) } @@ -3302,6 +3426,7 @@ func TestAssignUnderscore(t *testing.T) { VarRef(nil).VarRef(err). Val(fmt.Ref("Println")).Val("Hello").Call(1). Assign(2, 1).EndStmt(). + VarRef(nil).Val(err).Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -3310,6 +3435,7 @@ import "fmt" func main() { var err error _, err = fmt.Println("Hello") + _ = err } `) } @@ -3324,6 +3450,7 @@ func TestOperator(t *testing.T) { VarRef(b).Val(a).Val("!").BinaryOp(token.ADD).Assign(1).EndStmt(). VarRef(c).Val(&ast.BasicLit{Kind: token.INT, Value: "13"}).Assign(1).EndStmt(). VarRef(d).Val(c).UnaryOp(token.SUB).Assign(1).EndStmt(). + VarRef(nil).VarRef(nil).Val(b).Val(d).Assign(2).EndStmt(). End() domTest(t, pkg, `package main @@ -3336,6 +3463,7 @@ func main() { b = a + "!" c = 13 d = -c + _, _ = b, d } `) } @@ -3346,12 +3474,14 @@ func TestOperatorComplex(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewAutoVar(token.NoPos, token.NoPos, "a", &a). VarRef(a).Val(123.1).Val(&ast.BasicLit{Kind: token.IMAG, Value: "3i"}).BinaryOp(token.SUB).Assign(1).EndStmt(). + VarRef(nil).Val(a).Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { var a complex128 a = 123.1 - 3i + _ = a } `) } @@ -3362,12 +3492,14 @@ func TestBinaryOpUntyped(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewAutoVar(token.NoPos, token.NoPos, "a", &a). VarRef(a).Val("Hi").Val("!").BinaryOp(token.ADD).Assign(1).EndStmt(). + VarRef(nil).Val(a).Assign(1).EndStmt(). End() domTest(t, pkg, `package main func main() { var a string a = "Hi" + "!" + _ = a } `) } @@ -3419,6 +3551,8 @@ func TestBinaryOpCmpNil(t *testing.T) { VarVal("a").Val(nil).BinaryOp(token.NEQ).EndInit(1). NewVarStart(types.Typ[types.Bool], "c"). Val(nil).VarVal("a").BinaryOp(token.EQL).EndInit(1). + VarRef(nil).VarVal("b").Assign(1).EndStmt(). + VarRef(nil).VarVal("c").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -3426,6 +3560,8 @@ func main() { var a []interface{} var b bool = a != nil var c bool = nil == a + _ = b + _ = c } `) } @@ -3466,6 +3602,7 @@ func TestClosureAutoParamRet(t *testing.T) { /******/ VarRef(ctxRef(pkg, "ret")).Val(pkg.Builtin().Ref("append")).Val(ctxRef(pkg, "ret")).Val(1).Call(2).Assign(1). /******/ Return(0). /**/ End().Call(0).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -3474,6 +3611,7 @@ func main() { ret = append(ret, 1) return }() + _ = a } `) } @@ -3514,6 +3652,7 @@ func TestCallInlineClosure(t *testing.T) { /**/ Val(ctxRef(pkg, "n")).Return(1). /**/ End(). EndInit(1). + VarRef(nil).VarVal("n").Assign(1).EndStmt(). ZeroLit(gogen.TyError).Return(1). End() domTest(t, pkg, `package main @@ -3532,6 +3671,7 @@ func foo() error { _autoGo_2: } n := _autoGo_1 + _ = n return nil } `) @@ -3545,8 +3685,7 @@ func TestCallInlineClosureAssign(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). Val(fmt.Ref("Println")). CallInlineClosureStart(sig, 0, false). - /**/ NewVar(types.Universe.Lookup("error").Type(), "err"). - /**/ VarRef(ret).VarRef(ctxRef(pkg, "err")).Val(fmt.Ref("Println")).Val("Hi").Call(1).Assign(2, 1). + /**/ VarRef(ret).VarRef(nil).Val(fmt.Ref("Println")).Val("Hi").Call(1).Assign(2, 1). /**/ Return(0). /**/ End(). Call(1).EndStmt(). @@ -3558,8 +3697,7 @@ import "fmt" func main() { var _autoGo_1 int { - var err error - _autoGo_1, err = fmt.Println("Hi") + _autoGo_1, _ = fmt.Println("Hi") goto _autoGo_2 _autoGo_2: } @@ -3578,7 +3716,7 @@ func TestCallInlineClosureEllipsis(t *testing.T) { Val(fmt.Ref("Println")). Val(1).SliceLit(types.NewSlice(gogen.TyEmptyInterface), 1). CallInlineClosureStart(sig, 1, true). - /**/ DefineVarStart(0, "n", "err").Val(fmt.Ref("Println")).Val(x).Call(1, true).EndInit(1). + /**/ DefineVarStart(0, "n", "_").Val(fmt.Ref("Println")).Val(x).Call(1, true).EndInit(1). /**/ Val(ctxRef(pkg, "n")).Return(1). /**/ End(). Call(1).EndStmt(). @@ -3591,7 +3729,7 @@ func main() { var _autoGo_1 int { var _autoGo_2 []interface{} = []interface{}{1} - n, err := fmt.Println(_autoGo_2...) + n, _ := fmt.Println(_autoGo_2...) _autoGo_1 = n goto _autoGo_3 _autoGo_3: @@ -3617,6 +3755,8 @@ func TestExample(t *testing.T) { Val(fmt.Ref("Println")). /**/ VarVal("a").VarVal("b").VarVal("c"). // fmt.Println(a, b, c) /**/ Call(3).EndStmt(). + VarRef(nil).VarVal("x").Assign(1).EndStmt(). + VarRef(nil).VarVal("y").Assign(1).EndStmt(). NewClosure(gogen.NewTuple(v), nil, false).BodyStart(pkg). /**/ Val(fmt.Ref("Println")).Val(v).Call(1).EndStmt(). // fmt.Println(v) /**/ End(). @@ -3631,6 +3771,8 @@ func main() { var c = b var x, y interface{} fmt.Println(a, b, c) + _ = x + _ = y func(v string) { fmt.Println(v) }("Hello") diff --git a/stmt.go b/stmt.go index b051f169..c0eceb10 100644 --- a/stmt.go +++ b/stmt.go @@ -379,11 +379,11 @@ func (p *typeCaseStmt) Then(cb *CodeBuilder, src ...ast.Node) { } cb.stk.PopN(n) } - if pss.name != "" { + if pss.name != "" && pss.name != "_" { if n != 1 { // default, or case with multi expr typ = pss.xType } - name := types.NewParam(token.NoPos, cb.pkg.Types, pss.name, typ) + name := types.NewParam(getSrcPos(getSrc(src)), cb.pkg.Types, pss.name, typ) cb.current.scope.Insert(name) } } @@ -529,7 +529,7 @@ func (p *forRangeStmt) RangeAssignThen(cb *CodeBuilder, pos token.Pos) { if name == "_" { continue } - if scope.Insert(types.NewVar(token.NoPos, pkg.Types, name, typs[i])) != nil { + if scope.Insert(types.NewVar(pos, pkg.Types, name, typs[i])) != nil { log.Panicln("TODO: variable already defined -", name) } } diff --git a/typeparams_test.go b/typeparams_test.go index 85cd0806..4a7aae0f 100644 --- a/typeparams_test.go +++ b/typeparams_test.go @@ -459,6 +459,8 @@ type ( pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). NewVarStart(types.NewPointer(tyDataInt), "data").Typ(tyData).Typ(tyInt).Index(1, false).Star().Val(nil).Call(1).EndInit(1). NewVarStart(types.NewPointer(tySliceInt), "slice").Typ(tySlice).Typ(tyIntSlice).Typ(tyInt).Index(2, false).Star().Val(nil).Call(1).EndInit(1). + VarRef(nil).VarVal("data").Assign(1).EndStmt(). + VarRef(nil).VarVal("slice").Assign(1).EndStmt(). End() if isLeastGo122() { domTest(t, pkg, `package main @@ -468,6 +470,8 @@ import "foo" func main() { var data *foo.DataInt = (*foo.Data[int])(nil) var slice *foo.SliceInt = (*foo.Slice[[]int, int])(nil) + _ = data + _ = slice } `) } else { @@ -478,6 +482,8 @@ import "foo" func main() { var data *foo.Data[int] = (*foo.Data[int])(nil) var slice *foo.Slice[[]int, int] = (*foo.Slice[[]int, int])(nil) + _ = data + _ = slice } `) } @@ -553,6 +559,11 @@ var MyInts = Int{1,2,3,4} NewVarStart(tyInt, "n7").Val(fnAdd).Typ(tyString).Typ(tyInt).Index(2, false).Val("hello").Val(1).Val(2).Val(3).SliceLit(tyIntSlice, 3).CallWith(2, gogen.InstrFlagEllipsis).EndInit(1). NewVarStart(tyIntPointer, "p1").Val(fnLoader).Typ(tyIntPointer).Index(1, false).Val(nil).Val(1).Call(2).EndInit(1). NewVarStart(tyIntPointer, "p2").Val(fnLoader).Typ(tyIntPointer).Typ(tyInt).Index(2, false).Val(nil).Val(1).Call(2).EndInit(1). + VarRef(nil).VarVal("s1").Assign(1).EndStmt().VarRef(nil).VarVal("s2").Assign(1).EndStmt(). + VarRef(nil).VarVal("v1").Assign(1).EndStmt().VarRef(nil).VarVal("v2").Assign(1).EndStmt().VarRef(nil).VarVal("v3").Assign(1).EndStmt(). + VarRef(nil).VarVal("n1").Assign(1).EndStmt().VarRef(nil).VarVal("n2").Assign(1).EndStmt().VarRef(nil).VarVal("n3").Assign(1).EndStmt().VarRef(nil).VarVal("n4").Assign(1).EndStmt(). + VarRef(nil).VarVal("n5").Assign(1).EndStmt().VarRef(nil).VarVal("n6").Assign(1).EndStmt().VarRef(nil).VarVal("n7").Assign(1).EndStmt(). + VarRef(nil).VarVal("p1").Assign(1).EndStmt().VarRef(nil).VarVal("p2").Assign(1).EndStmt(). NewAutoVar(0, 0, "fn1", &fn1).VarRef(fn1).Val(fnLoader).Typ(tyIntPointer).Typ(tyInt).Index(2, false).Assign(1, 1).EndStmt(). Val(fn1).Val(nil).Val(1).Call(2).EndStmt(). End() @@ -579,6 +590,20 @@ func main() { var n7 int = foo.Add[string, int]("hello", []int{1, 2, 3}...) var p1 *int = foo.Loader[*int](nil, 1) var p2 *int = foo.Loader[*int, int](nil, 1) + _ = s1 + _ = s2 + _ = v1 + _ = v2 + _ = v3 + _ = n1 + _ = n2 + _ = n3 + _ = n4 + _ = n5 + _ = n6 + _ = n7 + _ = p1 + _ = p2 var fn1 func(p1 *int, p2 int) *int fn1 = foo.Loader[*int, int] fn1(nil, 1) diff --git a/unsafe_test.go b/unsafe_test.go index f989e92b..43e4e2b4 100644 --- a/unsafe_test.go +++ b/unsafe_test.go @@ -36,6 +36,7 @@ func TestUnsafeSlice(t *testing.T) { NewVarStart(types.NewPointer(types.Typ[types.Int]), "p"). Val(pkg.Unsafe().Ref("SliceData")).VarVal("s").CallWith(1, 0). EndInit(1). + VarRef(nil).VarVal("p").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -46,6 +47,7 @@ func main() { var v = [3]int{1, 2, 3} var s []int = unsafe.Slice(&v[0], 3) var p *int = unsafe.SliceData(s) + _ = p } `) } @@ -62,6 +64,7 @@ func TestUnsafeString(t *testing.T) { NewVarStart(types.NewPointer(types.Typ[types.Byte]), "p"). Val(pkg.Unsafe().Ref("StringData")).VarVal("s").CallWith(1, 0). EndInit(1). + VarRef(nil).VarVal("p").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -72,6 +75,7 @@ func main() { var v = [3]uint8{'a', 'b', 'c'} var s string = unsafe.String(&v[0], 3) var p *uint8 = unsafe.StringData(s) + _ = p } `) } diff --git a/xgo_test.go b/xgo_test.go index 87faaa64..d3a681f3 100644 --- a/xgo_test.go +++ b/xgo_test.go @@ -71,7 +71,7 @@ func TestConvertToClosure(t *testing.T) { t.Fatal("closure has no src node") } - p.EndInit(1).End() + p.EndInit(1).VarRef(nil).VarVal("x").Assign(1).EndStmt().End() domTest(t, pkg, `package main @@ -79,6 +79,7 @@ func main() { x := func() int { return 1 } + _ = x } `) } @@ -99,6 +100,7 @@ func TestFmtPrintln(t *testing.T) { pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). DefineVarStart(token.NoPos, "p").Val(ctxRef(pkg, "println")).EndInit(1). VarRef(ctxRef(pkg, "p")).Val(ctxRef(pkg, "println")).Assign(1).EndStmt(). + VarRef(nil).VarVal("p").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -107,6 +109,7 @@ import "fmt" func main() { p := fmt.Println p = fmt.Println + _ = p } `) } @@ -295,6 +298,8 @@ func TestCastIntTwoValue(t *testing.T) { Val(ng.Ref("Gop_bigrat")).Val(1).Call(1). CallWith(1, gogen.InstrFlagTwoValue). EndInit(1). + VarRef(nil).VarVal("v").Assign(1).EndStmt(). + VarRef(nil).VarVal("inRange").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -305,6 +310,8 @@ import ( func main() { v, inRange := builtin.Gop_bigrat_Cast__0(big.NewInt(1)).Gop_Rcast__0() + _ = v + _ = inRange } `) } @@ -318,6 +325,8 @@ func TestCastBigIntTwoValue(t *testing.T) { Val(ng.Ref("Gop_bigrat")).Val(1).Call(1). CallWith(1, gogen.InstrFlagTwoValue). EndInit(1). + VarRef(nil).VarVal("v").Assign(1).EndStmt(). + VarRef(nil).VarVal("inRange").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -328,6 +337,8 @@ import ( func main() { v, inRange := builtin.Gop_bigint_Cast__7(builtin.Gop_bigrat_Cast__0(big.NewInt(1))) + _ = v + _ = inRange } `) } @@ -752,6 +763,7 @@ func TestUntypedBigRat2(t *testing.T) { v := new(big.Rat).SetFrac(one, denom) pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg). DefineVarStart(0, "a").UntypedBigRat(v).EndInit(1). + VarRef(nil).VarVal("a").Assign(1).EndStmt(). End() domTest(t, pkg, `package main @@ -765,6 +777,7 @@ func main() { v, _ := new(big.Int).SetString("340282366920938463463374607431768211456", 10) return v }())) + _ = a } `) }