mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-14 02:54:59 +00:00
fixes #26036
---------
Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
(cherry picked from commit 050b38c749)
This commit is contained in:
@@ -82,6 +82,7 @@ type
|
||||
guards: TModel # nested guards
|
||||
locked: seq[PNode] # locked locations
|
||||
gcUnsafe, isRecursive, isTopLevel, hasSideEffect, inEnforcedGcSafe: bool
|
||||
canRaiseDefect: bool # defects are deliberately omitted from `exc`
|
||||
isInnerProc: bool
|
||||
inEnforcedNoSideEffects: bool
|
||||
isArrayIndexing: bool
|
||||
@@ -140,6 +141,11 @@ proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo; explicit
|
||||
createTypeBoundOps(tracked.graph, tracked.c, realType.lastSon, info)
|
||||
|
||||
createTypeBoundOps(tracked.graph, tracked.c, typ, info, tracked.c.idgen)
|
||||
for kind in TTypeAttachedOp:
|
||||
let op = getAttachedOp(tracked.graph, typ, kind)
|
||||
if op != nil and sfNeverRaises notin op.flags:
|
||||
tracked.canRaiseDefect = true
|
||||
break
|
||||
if (tfHasAsgn in typ.flags) or
|
||||
optSeqDestructors in tracked.config.globalOptions:
|
||||
tracked.owner.flags.incl sfInjectDestructors
|
||||
@@ -191,6 +197,23 @@ proc shouldWarnRangeConversion(conf: ConfigRef; info: TLineInfo; formalType, arg
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc conversionCanRaiseDefect(conf: ConfigRef; destType, sourceType: PType): bool =
|
||||
## Keep this in sync with the range checks introduced by `transformConv`.
|
||||
let
|
||||
dest = destType.skipTypes(abstractVarRange)
|
||||
source = sourceType.skipTypes(abstractVarRange)
|
||||
case dest.kind
|
||||
of tyInt..tyInt64, tyEnum, tyChar, tyUInt8..tyUInt32:
|
||||
if not source.isOrdinalType:
|
||||
result = dest.kind in tyInt..tyInt64
|
||||
else:
|
||||
result = firstOrd(conf, destType) > firstOrd(conf, sourceType) or
|
||||
lastOrd(conf, sourceType) > lastOrd(conf, destType)
|
||||
of tyFloat..tyFloat128:
|
||||
result = destType.skipTypes(abstractVar).kind == tyRange
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc lockLocations(a: PEffects; pragma: PNode) =
|
||||
if pragma.kind != nkExprColonExpr:
|
||||
localError(a.config, pragma.info, "locks pragma without argument")
|
||||
@@ -493,7 +516,9 @@ proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) =
|
||||
if sameType(a.graph.excType(aa[i]), a.graph.excType(e)): return
|
||||
|
||||
if e.typ != nil:
|
||||
if not isDefectException(e.typ):
|
||||
if isDefectException(e.typ):
|
||||
a.canRaiseDefect = true
|
||||
else:
|
||||
throws(a.exc, e, comesFrom)
|
||||
|
||||
proc skipHiddenConv(n: PNode): PNode =
|
||||
@@ -1109,6 +1134,32 @@ proc trackCall(tracked: PEffects; n: PNode) =
|
||||
markSideEffect(tracked, a, n.info)
|
||||
# p's effects are ours too:
|
||||
var a = n[0]
|
||||
if a.kind == nkSym:
|
||||
let s = a.sym
|
||||
case s.magic
|
||||
of mNone:
|
||||
if {sfNeverRaises, sfImportc, sfCompilerProc} * s.flags == {} and
|
||||
(sfSystemModule notin getModule(s).flags or
|
||||
sfSystemRaisesDefect in s.flags):
|
||||
tracked.canRaiseDefect = true
|
||||
of mUnaryMinusI..mAbsI, mAddI..mPred:
|
||||
if optOverflowCheck in tracked.currOptions:
|
||||
tracked.canRaiseDefect = true
|
||||
of mInc, mDec:
|
||||
let typ = n[1].typ.skipTypes({tyGenericInst, tyAlias, tySink,
|
||||
tyVar, tyLent, tyRange, tyDistinct})
|
||||
if optOverflowCheck in tracked.currOptions and
|
||||
typ.kind notin {tyUInt..tyUInt64}:
|
||||
tracked.canRaiseDefect = true
|
||||
of mDivU, mModU:
|
||||
tracked.canRaiseDefect = true
|
||||
of mAddF64..mDivF64:
|
||||
if {optNaNCheck, optInfCheck} * tracked.currOptions != {}:
|
||||
tracked.canRaiseDefect = true
|
||||
else:
|
||||
discard
|
||||
else:
|
||||
tracked.canRaiseDefect = true
|
||||
#if canRaise(a):
|
||||
# echo "this can raise ", tracked.config $ n.info
|
||||
let op = a.typ
|
||||
@@ -1347,6 +1398,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
else:
|
||||
track(tracked, n[0])
|
||||
of nkRaiseStmt:
|
||||
tracked.canRaiseDefect = true
|
||||
if n[0].kind != nkEmpty:
|
||||
n[0].info = n.info
|
||||
#throws(tracked.exc, n[0])
|
||||
@@ -1375,6 +1427,8 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
for i in 0..<n.len: track(tracked, n[i])
|
||||
tracked.leftPartOfAsgn = oldLeftPartOfAsgn
|
||||
of nkCheckedFieldExpr:
|
||||
if optFieldCheck in tracked.currOptions:
|
||||
tracked.canRaiseDefect = true
|
||||
track(tracked, n[0])
|
||||
if tracked.config.hasWarn(warnProveField) or strictCaseObjects in tracked.c.features:
|
||||
checkFieldAccess(tracked.guards, n, tracked.config, strictCaseObjects in tracked.c.features)
|
||||
@@ -1572,6 +1626,9 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
if tracked.owner.kind != skMacro:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
if optRangeCheck in tracked.currOptions and
|
||||
conversionCanRaiseDefect(tracked.config, n.typ, n[1].typ):
|
||||
tracked.canRaiseDefect = true
|
||||
if n.kind in {nkHiddenStdConv, nkHiddenSubConv} and
|
||||
n.typ.skipTypes(abstractInst).kind == tyCstring and
|
||||
not allowCStringConv(n[1]):
|
||||
@@ -1609,6 +1666,11 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
if optStaticBoundsCheck in tracked.currOptions:
|
||||
checkRange(tracked, n[1], n.typ)
|
||||
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
||||
if n.kind in {nkObjUpConv, nkObjDownConv}:
|
||||
if optObjCheck in tracked.currOptions:
|
||||
tracked.canRaiseDefect = true
|
||||
elif optRangeCheck in tracked.currOptions:
|
||||
tracked.canRaiseDefect = true
|
||||
if n.len == 1:
|
||||
track(tracked, n[0])
|
||||
if tracked.owner.kind != skMacro:
|
||||
@@ -1623,6 +1685,8 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
if tracked.owner.kind != skMacro:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
of nkBracketExpr:
|
||||
if optBoundsCheck in tracked.currOptions:
|
||||
tracked.canRaiseDefect = true
|
||||
if optStaticBoundsCheck in tracked.currOptions and n.len == 2:
|
||||
if n[0].typ != nil and skipTypes(n[0].typ, abstractVar).kind != tyTuple:
|
||||
checkBounds(tracked, n[0], n[1])
|
||||
@@ -1804,6 +1868,9 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
|
||||
track(t, body)
|
||||
|
||||
if t.exc.len == 0 and not t.canRaiseDefect:
|
||||
s.incl sfNeverRaises
|
||||
|
||||
if s.kind != skMacro:
|
||||
let params = s.typ.n
|
||||
for i in 1..<params.len:
|
||||
|
||||
Reference in New Issue
Block a user