Fixes 9716 [backport] (#9790)

* reuse temporary variable
* fixes #9716 [backport]
* Declare local vars in safer place
This commit is contained in:
Yuriy Glukhov
2018-11-24 11:50:48 +02:00
committed by Andreas Rumpf
parent 47d0582ebf
commit 410fd1deae
4 changed files with 30 additions and 14 deletions

View File

@@ -307,11 +307,13 @@ proc genSingleVar(p: BProc, a: PNode) =
proc genClosureVar(p: BProc, a: PNode) =
var immediateAsgn = a.sons[2].kind != nkEmpty
var v: TLoc
initLocExpr(p, a.sons[0], v)
genLineDir(p, a)
if immediateAsgn:
var v: TLoc
initLocExpr(p, a.sons[0], v)
genLineDir(p, a)
loadInto(p, a.sons[0], a.sons[2], v)
else:
constructLoc(p, v)
proc genVarStmt(p: BProc, n: PNode) =
for it in n.sons:
@@ -609,7 +611,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
lineF(p, cpsStmts, "throw $1;$n", [e])
else:
lineCg(p, cpsStmts, "#raiseExceptionEx((#Exception*)$1, $2, $3, $4, $5);$n",
[e, makeCString(typ.sym.name.s),
[e, makeCString(typ.sym.name.s),
makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s),
makeCString(toFileName(p.config, t.info)), rope(toLinenumber(t.info))])
else:

View File

@@ -1009,7 +1009,7 @@ proc stateFromGotoState(n: PNode): int =
assert(n.kind == nkGotoState)
result = n[0].intVal.int
proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
# This transforms 3 patterns:
########################## 1
# yield e
@@ -1051,7 +1051,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
result.add(retStmt)
else:
for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i])
n[i] = ctx.transformStateAssignments(n[i])
of nkSkip:
discard
@@ -1071,7 +1071,7 @@ proc tranformStateAssignments(ctx: var Ctx, n: PNode): PNode =
else:
for i in 0 ..< n.len:
n[i] = ctx.tranformStateAssignments(n[i])
n[i] = ctx.transformStateAssignments(n[i])
proc skipStmtList(ctx: Ctx; n: PNode): PNode =
result = n
@@ -1220,18 +1220,20 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
# while true:
# block :stateLoop:
# gotoState :state
# local vars decl (if needed)
# body # Might get wrapped in try-except
let loopBody = newNodeI(nkStmtList, n.info)
result = newTree(nkWhileStmt, newSymNode(ctx.g.getSysSym(n.info, "true")), loopBody)
result.info = n.info
let localVars = newNodeI(nkStmtList, n.info)
if not ctx.stateVarSym.isNil:
let varSect = newNodeI(nkVarSection, n.info)
addVar(varSect, newSymNode(ctx.stateVarSym))
loopBody.add(varSect)
localVars.add(varSect)
if not ctx.tempVars.isNil:
loopBody.add(ctx.tempVars)
localVars.add(ctx.tempVars)
let blockStmt = newNodeI(nkBlockStmt, n.info)
blockStmt.add(newSymNode(ctx.stateLoopLabel))
@@ -1240,7 +1242,7 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
gs.add(ctx.newStateAccess())
gs.add(ctx.g.newIntLit(n.info, ctx.states.len - 1))
var blockBody = newTree(nkStmtList, gs, n)
var blockBody = newTree(nkStmtList, gs, localVars, n)
if ctx.hasExceptions:
blockBody = ctx.wrapIntoTryExcept(blockBody)
@@ -1292,7 +1294,6 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
# should folllow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info)
var n = n.toStmtList
@@ -1320,7 +1321,7 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode =
result.add(s)
result.add(body)
result = ctx.tranformStateAssignments(result)
result = ctx.transformStateAssignments(result)
result = ctx.wrapIntoStateLoop(result)
# echo "TRANSFORM TO STATES: "

View File

@@ -218,7 +218,7 @@ when defineSsl:
var data = await recv(socket.fd.AsyncFD, BufferSize, flags)
let length = len(data)
if length > 0:
let ret = bioWrite(socket.bioIn, addr data[0], data.len.cint)
let ret = bioWrite(socket.bioIn, addr data[0], length.cint)
if ret < 0:
raiseSSLError()
elif length == 0:

View File

@@ -403,7 +403,7 @@ block: # yield in blockexpr
test(it, 1, 2, 3)
block: #8851
block: #8851
type
Foo = ref object of RootObj
template someFoo(): Foo =
@@ -454,5 +454,18 @@ block: #9694 - yield in ObjConstr
test(it, 1, 2)
block: #9716
iterator it(): int {.closure.} =
var a = 0
for i in 1 .. 3:
var a: int # Make sure the "local" var is reset
var b: string # ditto
yield 1
a += 5
b &= "hello"
doAssert(a == 5)
doAssert(b == "hello")
test(it, 1, 1, 1)
echo "ok"