mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-25 04:15:09 +00:00
Properly wrap discarded statements (#10322)
Failing to do so lead the codegen to emit invalid code sometimes, especially when C++ references were involved. Fixes #10241
This commit is contained in:
@@ -917,7 +917,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode =
|
||||
let isPush = hintExtendedContext in c.config.notes
|
||||
if isPush: pushInfoContext(c.config, n.info)
|
||||
result = semExpr(c, n, {efWantStmt})
|
||||
discardCheck(c, result, {})
|
||||
result = discardCheck(c, result, {})
|
||||
if isPush: popInfoContext(c.config)
|
||||
|
||||
proc isTypeExpr(n: PNode): bool =
|
||||
@@ -1639,7 +1639,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
|
||||
a.sons[1] = result
|
||||
result = semAsgn(c, a)
|
||||
else:
|
||||
discardCheck(c, result, {})
|
||||
result = discardCheck(c, result, {})
|
||||
|
||||
if c.p.owner.kind notin {skMacro, skTemplate} and
|
||||
c.p.resultSym != nil and c.p.resultSym.typ.isMetaType:
|
||||
|
||||
@@ -130,13 +130,13 @@ proc fixNilType(c: PContext; n: PNode) =
|
||||
for it in n: fixNilType(c, it)
|
||||
n.typ = nil
|
||||
|
||||
proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
|
||||
proc discardCheck(c: PContext, expr: PNode, flags: TExprFlags): PNode =
|
||||
result = expr
|
||||
if c.matchedConcept != nil or efInTypeof in flags: return
|
||||
|
||||
if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}:
|
||||
if implicitlyDiscardable(result):
|
||||
var n = newNodeI(nkDiscardStmt, result.info, 1)
|
||||
n[0] = result
|
||||
result = newNode(nkDiscardStmt, result.info, @[result])
|
||||
elif result.typ.kind != tyError and c.config.cmd != cmdInteractive:
|
||||
var n = result
|
||||
while n.kind in skipForDiscardable: n = n.lastSon
|
||||
@@ -168,7 +168,8 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
else: illFormedAst(it, c.config)
|
||||
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
|
||||
(not hasElse and efInTypeof notin flags):
|
||||
for it in n: discardCheck(c, it.lastSon, flags)
|
||||
for it in n:
|
||||
it.sons[^1] = discardCheck(c, it.sons[^1], flags)
|
||||
result.kind = nkIfStmt
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
|
||||
@@ -266,12 +267,14 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
|
||||
dec c.p.inTryStmt
|
||||
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}:
|
||||
discardCheck(c, n.sons[0], flags)
|
||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
|
||||
n.sons[0] = discardCheck(c, n.sons[0], flags)
|
||||
for i in 1..n.len-1:
|
||||
n.sons[i].sons[^1] = discardCheck(c, n.sons[i].sons[^1], flags)
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
else:
|
||||
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
|
||||
if n.lastSon.kind == nkFinally:
|
||||
n.sons[^1].sons[^1] = discardCheck(c, n.sons[^1].sons[^1], flags)
|
||||
n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info)
|
||||
for i in 1..last:
|
||||
var it = n.sons[i]
|
||||
@@ -679,7 +682,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
openScope(c)
|
||||
n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
|
||||
if efInTypeof notin flags:
|
||||
discardCheck(c, n.sons[length-1], flags)
|
||||
n.sons[^1] = discardCheck(c, n.sons[^1], flags)
|
||||
closeScope(c)
|
||||
dec(c.p.nestedLoopCounter)
|
||||
|
||||
@@ -866,7 +869,8 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
closeScope(c)
|
||||
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or
|
||||
(not hasElse and efInTypeof notin flags):
|
||||
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags)
|
||||
for i in 1..n.len-1:
|
||||
n.sons[i].sons[^1] = discardCheck(c, n.sons[i].sons[^1], flags)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
@@ -2029,7 +2033,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
n.typ = n.sons[i].typ
|
||||
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
|
||||
elif i != last or voidContext:
|
||||
discardCheck(c, n.sons[i], flags)
|
||||
n.sons[i] = discardCheck(c, n.sons[i], flags)
|
||||
else:
|
||||
n.typ = n.sons[i].typ
|
||||
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
|
||||
|
||||
19
tests/cpp/t10241.nim
Normal file
19
tests/cpp/t10241.nim
Normal file
@@ -0,0 +1,19 @@
|
||||
discard """
|
||||
targets: "cpp"
|
||||
action: "compile"
|
||||
"""
|
||||
|
||||
type
|
||||
String* {.importcpp: "std::string", header: "string".} = object
|
||||
|
||||
proc initString*(): String
|
||||
{.importcpp: "std::string()", header: "string".}
|
||||
|
||||
proc append*(this: var String, str: String): var String
|
||||
{.importcpp: "append", header: "string", discardable.}
|
||||
|
||||
var
|
||||
s1 = initString()
|
||||
s2 = initString()
|
||||
|
||||
s1.append s2
|
||||
Reference in New Issue
Block a user