mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-07 15:59:10 +00:00
fixes #26045;
fixes #26046
The fix isolates compiler option state while semantically checking each
when nimvm branch.
compiler/semexprs.nim:2745 snapshots the option stack, compiler options,
diagnostics settings, and enabled features. It analyzes one branch and
restores that state in finally. Both the nimvm and else branches use
this function.
This prevents:
```nim
when nimvm:
{.push overflowChecks: off.}
```
from disabling overflow checks in following runtime code. It also means
a {.pop.} in the opposite branch correctly reports that it has no
corresponding {.push.}.
(cherry picked from commit f6651e6c70)
This commit is contained in:
@@ -2664,6 +2664,22 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
else:
|
||||
result = semDirectOp(c, n, flags, expectedType)
|
||||
|
||||
proc semNimvmBranch(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
let
|
||||
oldOptionStack = c.optionStack[0..^1]
|
||||
oldOptions = c.config.options
|
||||
oldNotes = c.config.notes
|
||||
oldWarningAsErrors = c.config.warningAsErrors
|
||||
oldFeatures = c.features
|
||||
try:
|
||||
result = semExpr(c, n, flags)
|
||||
finally:
|
||||
c.optionStack = oldOptionStack
|
||||
c.config.options = oldOptions
|
||||
c.config.notes = oldNotes
|
||||
c.config.warningAsErrors = oldWarningAsErrors
|
||||
c.features = oldFeatures
|
||||
|
||||
proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
# If semCheck is set to false, ``when`` will return the verbatim AST of
|
||||
# the correct branch. Otherwise the AST will be passed through semStmt.
|
||||
@@ -2700,7 +2716,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
checkSonsLen(it, 2, c.config)
|
||||
if whenNimvm:
|
||||
if semCheck:
|
||||
it[1] = semExpr(c, it[1], flags)
|
||||
it[1] = semNimvmBranch(c, it[1], flags)
|
||||
typ = commonType(c, typ, it[1].typ)
|
||||
result = n # when nimvm is not elimited until codegen
|
||||
elif c.inGenericContext > 0:
|
||||
@@ -2731,7 +2747,8 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
discard
|
||||
elif result == nil or whenNimvm:
|
||||
if semCheck:
|
||||
it[0] = semExpr(c, it[0], flags)
|
||||
it[0] = if whenNimvm: semNimvmBranch(c, it[0], flags)
|
||||
else: semExpr(c, it[0], flags)
|
||||
typ = commonType(c, typ, it[0].typ)
|
||||
if typ != nil and typ.kind != tyUntyped:
|
||||
it[0] = fitNode(c, typ, it[0], it[0].info)
|
||||
|
||||
21
tests/whenstmt/twhen_nimvm_push.nim
Normal file
21
tests/whenstmt/twhen_nimvm_push.nim
Normal file
@@ -0,0 +1,21 @@
|
||||
discard """
|
||||
output: "ok"
|
||||
"""
|
||||
|
||||
var overflowDetected = false
|
||||
when nimvm:
|
||||
{.push overflowChecks: off.}
|
||||
else:
|
||||
var branchX = high(int)
|
||||
try:
|
||||
inc branchX
|
||||
except OverflowDefect:
|
||||
overflowDetected = true
|
||||
|
||||
doAssert overflowDetected
|
||||
|
||||
var x = high(int)
|
||||
try:
|
||||
inc x
|
||||
except OverflowDefect:
|
||||
echo "ok"
|
||||
8
tests/whenstmt/twhen_nimvm_push_pop.nim
Normal file
8
tests/whenstmt/twhen_nimvm_push_pop.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard """
|
||||
errormsg: "{.pop.} without a corresponding {.push.}"
|
||||
line: 8
|
||||
"""
|
||||
|
||||
when nimvm:
|
||||
{.push checks: off.}
|
||||
else: {.pop.}
|
||||
Reference in New Issue
Block a user