Skip to content

Commit

Permalink
fixes nim-lang#14126 [backport:1.2] (nim-lang#14390)
Browse files Browse the repository at this point in the history
* fixes nim-lang#14126 [backport:1.2]

* used more logic to optimize it further; updated Nimble version
  • Loading branch information
Araq authored and EchoPouet committed Jun 13, 2020
1 parent d89ffc6 commit 3e760b1
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
29 changes: 24 additions & 5 deletions compiler/ccgcalls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,30 @@ proc canRaiseDisp(p: BProc; n: PNode): bool =
# we have to be *very* conservative:
result = canRaiseConservative(n)

proc leftAppearsOnRightSide(le, ri: PNode): bool =
proc preventNrvo(p: BProc; le, ri: PNode): bool =
proc locationEscapes(p: BProc; le: PNode): bool =
var n = le
while true:
# do NOT follow nkHiddenDeref here!
case n.kind
of nkSym:
# we don't own the location so it escapes:
return n.sym.owner != p.prc
of nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
nkCheckedFieldExpr:
n = n[0]
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
n = n[1]
else:
# cannot analyse the location; assume the worst
return true

if le != nil:
for i in 1..<ri.len:
let r = ri[i]
if isPartOf(le, r) != arNo: return true
return canRaiseDisp(p, ri[0]) and
(p.nestedTryStmts.len > 0 or locationEscapes(p, le))

proc hasNoInit(call: PNode): bool {.inline.} =
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags
Expand All @@ -51,7 +70,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
if isInvalidReturnType(p.config, typ[0]):
if params != nil: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
# Great, we can use 'd':
if d.k == locNone: getTemp(p, typ[0], d, needsInit=true)
elif d.k notin {locTemp} and not hasNoInit(ri):
Expand Down Expand Up @@ -150,7 +169,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
result = "($4*)($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), dest]
of tyString, tySequence:
let atyp = skipTypes(a.t, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and atyp.kind == tyString and
if formalType.skipTypes(abstractInst).kind == tyVar and atyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if atyp.kind == tyVar and not compileToCpp(p.module):
Expand All @@ -166,7 +185,7 @@ proc openArrayLoc(p: BProc, formalType: PType, n: PNode): Rope =
result = "$1, $1Len_0" % [rdLoc(a)]
of tyString, tySequence:
let ntyp = skipTypes(n.typ, abstractInst)
if formalType.skipTypes(abstractInst).kind == tyVar and ntyp.kind == tyString and
if formalType.skipTypes(abstractInst).kind == tyVar and ntyp.kind == tyString and
optSeqDestructors in p.config.globalOptions:
linefmt(p, cpsStmts, "#nimPrepareStrMutationV2($1);$n", [byRefLoc(p, a)])
if ntyp.kind == tyVar and not compileToCpp(p.module):
Expand Down Expand Up @@ -292,7 +311,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
if isInvalidReturnType(p.config, typ[0]):
if ri.len > 1: pl.add(~", ")
# beware of 'result = p(result)'. We may need to allocate a temporary:
if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri):
# Great, we can use 'd':
if d.k == locNone:
getTemp(p, typ[0], d, needsInit=true)
Expand Down
2 changes: 1 addition & 1 deletion koch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#

const
NimbleStableCommit = "6f2b1ace922e565f7f48a69648e16a002a5d15e3" # master
NimbleStableCommit = "63695f490728e3935692c29f3d71944d83bb1e83" # master

when not defined(windows):
const
Expand Down
48 changes: 45 additions & 3 deletions tests/ccgbugs/tcodegenbug1.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ discard """
obj.inner.id = 7
id = 7
obj = (inner: (kind: Just, id: 7))
2'''
2
(a: "1", b: "2", c: "3")
caught
(a: "1", b: "", c: "3")'''
"""

# bug #6960
Expand Down Expand Up @@ -129,12 +132,51 @@ import macros
func myfunc(obj: MyObject): MyResult {.raises: [].} =
template index: auto =
case obj.kind:
of Float: $obj.index
of Float: $obj.index
of Fixed: "Fixed"
macro to_str(a: untyped): string =
result = newStrLitNode(a.repr)
result = newStrLitNode(a.repr)
result.val[0] = index
result.val[1] = to_str(obj.kind + Ola)

let x = MyObject(someInt: 10, kind: Fixed)
echo myfunc(x).val.len

# bug #14126

type X = object
a, b, c: string

proc f(): X =
result.a = "a"
result.b = "b"
raise (ref ValueError)()

proc ohmanNoNRVO =
var x: X
x.a = "1"
x.b = "2"
x.c = "3"

try:
x = f()
except:
discard

echo x
doAssert x.c == "3", "shouldn't modify x if f raises"

ohmanNoNRVO()

proc ohmanNoNRVO2(x: var X) =
x.a = "1"
x.c = "3"
x = f()

var xgg: X
try:
ohmanNoNRVO2(xgg)
except:
echo "caught"
echo xgg
doAssert xgg.c == "3", "this assert will fail"

0 comments on commit 3e760b1

Please sign in to comment.