Skip to content

Commit 32083c7

Browse files
authored
more precise analysis about 'observable stores' [backport:1.2] (#14582)
1 parent 4fdf9cb commit 32083c7

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

compiler/ast.nim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ type
293293
sfInjectDestructors # whether the proc needs the 'injectdestructors' transformation
294294
sfNeverRaises # proc can never raise an exception, not even OverflowDefect
295295
# or out-of-memory
296+
sfUsedInFinallyOrExcept # symbol is used inside an 'except' or 'finally'
296297

297298
TSymFlags* = set[TSymFlag]
298299

compiler/ccgcalls.nim

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ proc canRaiseDisp(p: BProc; n: PNode): bool =
2222
result = canRaiseConservative(n)
2323

2424
proc preventNrvo(p: BProc; le, ri: PNode): bool =
25-
proc locationEscapes(p: BProc; le: PNode): bool =
25+
proc locationEscapes(p: BProc; le: PNode; inTryStmt: bool): bool =
2626
var n = le
2727
while true:
2828
# do NOT follow nkHiddenDeref here!
2929
case n.kind
3030
of nkSym:
3131
# we don't own the location so it escapes:
32-
return n.sym.owner != p.prc
32+
if n.sym.owner != p.prc:
33+
return true
34+
elif inTryStmt and sfUsedInFinallyOrExcept in n.sym.flags:
35+
# it is also an observable store if the location is used
36+
# in 'except' or 'finally'
37+
return true
38+
return false
3339
of nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
3440
nkCheckedFieldExpr:
3541
n = n[0]
@@ -46,7 +52,7 @@ proc preventNrvo(p: BProc; le, ri: PNode): bool =
4652
# we use the weaker 'canRaise' here in order to prevent too many
4753
# annoying warnings, see #14514
4854
if canRaise(ri[0]) and
49-
(p.nestedTryStmts.len > 0 or locationEscapes(p, le)):
55+
locationEscapes(p, le, p.nestedTryStmts.len > 0):
5056
message(p.config, le.info, warnObservableStores, $le)
5157

5258
proc hasNoInit(call: PNode): bool {.inline.} =

compiler/sempass2.nim

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ type
6666
TEffects = object
6767
exc: PNode # stack of exceptions
6868
tags: PNode # list of tags
69-
bottom, inTryStmt: int
69+
bottom, inTryStmt, inExceptOrFinallyStmt: int
7070
owner: PSym
7171
ownerModule: PSym
7272
init: seq[int] # list of initialized variables
@@ -248,6 +248,8 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool; conf: ConfigRef) =
248248

249249
proc useVar(a: PEffects, n: PNode) =
250250
let s = n.sym
251+
if a.inExceptOrFinallyStmt > 0:
252+
incl s.flags, sfUsedInFinallyOrExcept
251253
if isLocalVar(a, s):
252254
if sfNoInit in s.flags:
253255
# If the variable is explicitly marked as .noinit. do not emit any error
@@ -382,6 +384,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
382384

383385
var branches = 1
384386
var hasFinally = false
387+
inc tracked.inExceptOrFinallyStmt
385388

386389
# Collect the exceptions caught by the except branches
387390
for i in 1..<n.len:
@@ -414,6 +417,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
414417
hasFinally = true
415418

416419
tracked.bottom = oldBottom
420+
dec tracked.inExceptOrFinallyStmt
417421
if not hasFinally:
418422
setLen(tracked.init, oldState)
419423
for id, count in items(inter):

0 commit comments

Comments
 (0)