Skip to content

Commit

Permalink
fixes nim-lang#22354; Wrong C++ codegen for default parameter values …
Browse files Browse the repository at this point in the history
…in ORC (nim-lang#22819)

fixes nim-lang#22354

It skips `nkHiddenAddr`. No need to hoist `var parameters` without side
effects. Besides, it saves lots of temporary variables in ORC.
  • Loading branch information
ringabout authored Oct 13, 2023
1 parent 8990626 commit 61145b1
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 30 deletions.
4 changes: 2 additions & 2 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2927,7 +2927,7 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode)
if defExpr.kind == nkSym and defExpr.sym.kind == skParam and defExpr.sym.owner == call[0].sym:
let paramPos = defExpr.sym.position + 1

if call[paramPos].kind != nkSym:
if call[paramPos].skipAddr.kind != nkSym:
let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), c.idgen,
c.p.owner, letSection.info, c.p.owner.options)
hoistedVarSym.typ = call[paramPos].typ
Expand All @@ -2939,7 +2939,7 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode)

call[paramPos] = newSymNode(hoistedVarSym) # Refer the original arg to its hoisted sym

# arg we refer to is a sym, wether introduced by hoisting or not doesn't matter, we simply reuse it
# arg we refer to is a sym, whether introduced by hoisting or not doesn't matter, we simply reuse it
defExpr = call[paramPos]
else:
for i in 0..<defExpr.safeLen:
Expand Down
75 changes: 47 additions & 28 deletions tests/ccgbugs2/tcodegen.nim
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
discard """
targets: "c cpp"
"""

# bug #19094
type
X = object
filler: array[2048, int]
innerAddress: uint

proc initX(): X =
result.innerAddress = cast[uint](result.addr)

proc initXInPlace(x: var X) =
x.innerAddress = cast[uint](x.addr)

block: # NRVO1
var x = initX()
let innerAddress = x.innerAddress
let outerAddress = cast[uint](x.addr)
doAssert(innerAddress == outerAddress) # [OK]

block: # NRVO2
var x: X
initXInPlace(x)
let innerAddress = x.innerAddress
let outerAddress = cast[uint](x.addr)
doAssert(innerAddress == outerAddress) # [OK]
discard """
targets: "c cpp"
"""

# bug #19094
type
X = object
filler: array[2048, int]
innerAddress: uint

proc initX(): X =
result.innerAddress = cast[uint](result.addr)

proc initXInPlace(x: var X) =
x.innerAddress = cast[uint](x.addr)

block: # NRVO1
var x = initX()
let innerAddress = x.innerAddress
let outerAddress = cast[uint](x.addr)
doAssert(innerAddress == outerAddress) # [OK]

block: # NRVO2
var x: X
initXInPlace(x)
let innerAddress = x.innerAddress
let outerAddress = cast[uint](x.addr)
doAssert(innerAddress == outerAddress) # [OK]

block: # bug #22354
type Object = object
foo: int

proc takeFoo(self: var Object): int =
result = self.foo
self.foo = 999

proc doSomething(self: var Object; foo: int = self.takeFoo()) =
discard

proc main() =
var obj = Object(foo: 2)
obj.doSomething()
doAssert obj.foo == 999


main()

0 comments on commit 61145b1

Please sign in to comment.