diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-07-19 02:53:07 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-18 20:53:07 +0200 |
commit | 3a103669d18408cd75ca5c5c97c34f4222c6e217 (patch) | |
tree | e539caadbb207be8f4bc6d14c38fb63d2bd990eb | |
parent | 6aa54d533b3ee10ed5156b0f67f5418bc4b6d99d (diff) | |
download | Nim-3a103669d18408cd75ca5c5c97c34f4222c6e217.tar.gz |
fixes #23858; 2.2.0 rc1 regression with cdecl functions (#23859)
fixes #23858 We should not assign fields to fields for returns of function calls because calls might have side effects.
-rw-r--r-- | compiler/ccgcalls.nim | 6 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 3 | ||||
-rw-r--r-- | compiler/cgen.nim | 1 | ||||
-rw-r--r-- | tests/arc/tarc_orc.nim | 11 |
4 files changed, 17 insertions, 4 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index 040eebc3a..89a6862af 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -141,7 +141,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, if d.k == locNone: d = getTemp(p, typ.returnType) var list = initLoc(locCall, d.lode, OnUnknown) list.snippet = pl - genAssignment(p, d, list, {}) # no need for deep copying + genAssignment(p, d, list, {needAssignCall}) # no need for deep copying if canRaise: raiseExit(p) elif isHarmlessStore(p, canRaise, d): @@ -152,7 +152,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, assert(d.t != nil) # generate an assignment to d: var list = initLoc(locCall, d.lode, OnUnknown) list.snippet = pl - genAssignment(p, d, list, flags) # no need for deep copying + genAssignment(p, d, list, flags+{needAssignCall}) # no need for deep copying if canRaise: if not (useTemp and cleanupTemp(p, typ.returnType, d)): raiseExit(p) @@ -160,7 +160,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, var tmp: TLoc = getTemp(p, typ.returnType, needsInit=true) var list = initLoc(locCall, d.lode, OnUnknown) list.snippet = pl - genAssignment(p, tmp, list, flags) # no need for deep copying + genAssignment(p, tmp, list, flags+{needAssignCall}) # no need for deep copying if canRaise: if not cleanupTemp(p, typ.returnType, tmp): raiseExit(p) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 45a2cc2a9..af3c8bf66 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -379,7 +379,8 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) = elif not isObjLackingTypeField(ty): genGenericAsgn(p, dest, src, flags) elif containsGarbageCollectedRef(ty): - if ty[0].isNil and asgnComplexity(ty.n) <= 4: + if ty[0].isNil and asgnComplexity(ty.n) <= 4 and + needAssignCall notin flags: # calls might contain side effects discard getTypeDesc(p.module, ty) internalAssert p.config, ty.n != nil genOptAsgnObject(p, dest, src, flags, ty.n, ty) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index c0af19080..08180a939 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -413,6 +413,7 @@ type needToCopy needToCopySinkParam needTempForOpenArray + needAssignCall TAssignmentFlags = set[TAssignmentFlag] proc genObjConstr(p: BProc, e: PNode, d: var TLoc) diff --git a/tests/arc/tarc_orc.nim b/tests/arc/tarc_orc.nim index 674ba0dbb..0e6208b4a 100644 --- a/tests/arc/tarc_orc.nim +++ b/tests/arc/tarc_orc.nim @@ -160,3 +160,14 @@ block: testCase() main() + +block: # bug #23858 + type Object = object + a: int + b: ref int + var x = 0 + proc fn(): auto {.cdecl.} = + inc x + return Object() + discard fn() + doAssert x == 1 |