mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-30 16:45:38 +00:00
Merge branch 'devel' into pr_disable_sink
This commit is contained in:
@@ -1237,6 +1237,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
else:
|
||||
scope = initScope(p.s(cpsStmts))
|
||||
# we handled the error:
|
||||
linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp])
|
||||
expr(p, t[i][0], d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
endBlockWith(p):
|
||||
|
||||
@@ -46,7 +46,7 @@ proc isLocation(n: PNode): bool = not n.isValue
|
||||
|
||||
proc isLet(n: PNode): bool =
|
||||
if n.kind == nkSym:
|
||||
if n.sym.kind in {skLet, skTemp, skForVar}:
|
||||
if n.sym.kind in {skLet, skConst, skTemp, skForVar}: # guard immutable variables
|
||||
result = true
|
||||
elif n.sym.kind == skParam and skipTypes(n.sym.typ,
|
||||
abstractInst).kind notin {tyVar}:
|
||||
|
||||
@@ -1208,6 +1208,7 @@ type
|
||||
enforcedGcSafety, enforceNoSideEffects: bool
|
||||
oldExc, oldTags, oldForbids: int
|
||||
exc, tags, forbids: PNode
|
||||
excSource, tagsSource, forbidsSource: PNode
|
||||
|
||||
proc createBlockContext(tracked: PEffects): PragmaBlockContext =
|
||||
var oldForbidsLen = 0
|
||||
@@ -1230,17 +1231,18 @@ proc unapplyBlockContext(tracked: PEffects; bc: PragmaBlockContext) =
|
||||
# anything about 'raises' in the 'cast' at all. Same applies for 'tags'.
|
||||
setLen(tracked.exc.sons, bc.oldExc)
|
||||
for e in bc.exc:
|
||||
addRaiseEffect(tracked, e, e)
|
||||
addRaiseEffect(tracked, e, if bc.excSource != nil: bc.excSource else: e)
|
||||
if bc.tags != nil:
|
||||
setLen(tracked.tags.sons, bc.oldTags)
|
||||
for t in bc.tags:
|
||||
addTag(tracked, t, t)
|
||||
addTag(tracked, t, if bc.tagsSource != nil: bc.tagsSource else: t)
|
||||
if bc.forbids != nil:
|
||||
setLen(tracked.forbids.sons, bc.oldForbids)
|
||||
for t in bc.forbids:
|
||||
addNotTag(tracked, t, t)
|
||||
addNotTag(tracked, t, if bc.forbidsSource != nil: bc.forbidsSource else: t)
|
||||
|
||||
proc castBlock(tracked: PEffects, pragma: PNode, bc: var PragmaBlockContext) =
|
||||
proc castBlock(tracked: PEffects, castPragma: PNode, bc: var PragmaBlockContext) =
|
||||
let pragma = castPragma[1]
|
||||
case whichPragma(pragma)
|
||||
of wGcSafe:
|
||||
bc.enforcedGcSafety = true
|
||||
@@ -1253,6 +1255,7 @@ proc castBlock(tracked: PEffects, pragma: PNode, bc: var PragmaBlockContext) =
|
||||
else:
|
||||
bc.tags = newNodeI(nkArgList, pragma.info)
|
||||
bc.tags.add n
|
||||
bc.tagsSource = castPragma
|
||||
of wForbids:
|
||||
let n = pragma[1]
|
||||
if n.kind in {nkCurly, nkBracket}:
|
||||
@@ -1260,6 +1263,7 @@ proc castBlock(tracked: PEffects, pragma: PNode, bc: var PragmaBlockContext) =
|
||||
else:
|
||||
bc.forbids = newNodeI(nkArgList, pragma.info)
|
||||
bc.forbids.add n
|
||||
bc.forbidsSource = castPragma
|
||||
of wRaises:
|
||||
let n = pragma[1]
|
||||
if n.kind in {nkCurly, nkBracket}:
|
||||
@@ -1267,6 +1271,7 @@ proc castBlock(tracked: PEffects, pragma: PNode, bc: var PragmaBlockContext) =
|
||||
else:
|
||||
bc.exc = newNodeI(nkArgList, pragma.info)
|
||||
bc.exc.add n
|
||||
bc.excSource = castPragma
|
||||
of wUncheckedAssign:
|
||||
discard "handled in sempass1"
|
||||
else:
|
||||
@@ -1520,7 +1525,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
of wNoSideEffect:
|
||||
bc.enforceNoSideEffects = true
|
||||
of wCast:
|
||||
castBlock(tracked, pragmaList[i][1], bc)
|
||||
castBlock(tracked, pragmaList[i], bc)
|
||||
else:
|
||||
discard
|
||||
applyBlockContext(tracked, bc)
|
||||
|
||||
@@ -791,8 +791,10 @@ proc procParamTypeRel(c: var TCandidate; f, a: PType): TTypeRelation =
|
||||
# different C types (size_t vs unsigned long long).
|
||||
let fCheck = concreteType(c, f)
|
||||
let aCheck = concreteType(c, a)
|
||||
# Note that `result` is equal; now check whether they have the same
|
||||
# backend type.
|
||||
if fCheck != nil and aCheck != nil and
|
||||
not sameBackendTypePickyAliases(fCheck, aCheck):
|
||||
not sameBackendTypePickyAliases(fCheck, aCheck, {IgnoreFlags}):
|
||||
result = isNone
|
||||
|
||||
if result <= isSubrange or inconsistentVarTypes(f, a):
|
||||
@@ -2471,6 +2473,10 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
return arg
|
||||
elif f.kind == tyStatic and arg.typ.n != nil:
|
||||
return arg.typ.n
|
||||
elif f.kind == tyUntyped:
|
||||
# bug #25693: a different overload candidate may have sem-checked the
|
||||
# operand and left symbols behind; templates expect the pristine AST.
|
||||
return argOrig
|
||||
else:
|
||||
return argSemantized # argOrig
|
||||
|
||||
|
||||
@@ -1069,9 +1069,10 @@ proc sameBackendTypeIgnoreRange*(x, y: PType): bool =
|
||||
c.cmp = dcEqIgnoreDistinct
|
||||
result = sameTypeAux(x, y, c)
|
||||
|
||||
proc sameBackendTypePickyAliases*(x, y: PType): bool =
|
||||
proc sameBackendTypePickyAliases*(x, y: PType, flags: TTypeCmpFlags = {}): bool =
|
||||
var c = initSameTypeClosure()
|
||||
c.flags.incl {IgnoreTupleFields, IgnoreRangeShallow, PickyCAliases, PickyBackendAliases}
|
||||
c.flags.incl flags
|
||||
c.cmp = dcEqIgnoreDistinct
|
||||
result = sameTypeAux(x, y, c)
|
||||
|
||||
|
||||
@@ -175,23 +175,48 @@ proc parseEscapedUTF16*(buf: cstring, pos: var int): int =
|
||||
else:
|
||||
return -1
|
||||
|
||||
proc addSpan(dst: var string; src: string; startPos, endPos: int) {.inline.} =
|
||||
let n = endPos - startPos
|
||||
if n <= 0:
|
||||
return
|
||||
|
||||
let old = dst.len
|
||||
dst.setLen old + n
|
||||
|
||||
template impl =
|
||||
for i in 0..<n:
|
||||
dst[old + i] = src[startPos + i]
|
||||
|
||||
when nimvm:
|
||||
impl
|
||||
else:
|
||||
when defined(js) or defined(nimscript):
|
||||
impl
|
||||
else:
|
||||
{.noSideEffect.}:
|
||||
copyMem dst[old].addr, src[startPos].unsafeAddr, n
|
||||
|
||||
proc parseString(my: var JsonParser): TokKind =
|
||||
result = tkString
|
||||
var pos = my.bufpos + 1
|
||||
var spanStart = pos
|
||||
if my.rawStringLiterals:
|
||||
add(my.a, '"')
|
||||
while true:
|
||||
case my.buf[pos]
|
||||
of '\0':
|
||||
my.err = errQuoteExpected
|
||||
my.err = errInvalidToken
|
||||
addSpan(my.a, my.buf, spanStart, pos)
|
||||
result = tkError
|
||||
break
|
||||
of '"':
|
||||
addSpan(my.a, my.buf, spanStart, pos)
|
||||
if my.rawStringLiterals:
|
||||
add(my.a, '"')
|
||||
inc(pos)
|
||||
break
|
||||
of '\\':
|
||||
addSpan(my.a, my.buf, spanStart, pos)
|
||||
if my.rawStringLiterals:
|
||||
add(my.a, '\\')
|
||||
case my.buf[pos+1]
|
||||
@@ -251,14 +276,18 @@ proc parseString(my: var JsonParser): TokKind =
|
||||
# don't bother with the error
|
||||
add(my.a, my.buf[pos])
|
||||
inc(pos)
|
||||
spanStart = pos
|
||||
of '\c':
|
||||
addSpan(my.a, my.buf, spanStart, pos)
|
||||
pos = lexbase.handleCR(my, pos)
|
||||
add(my.a, '\c')
|
||||
spanStart = pos
|
||||
of '\L':
|
||||
addSpan(my.a, my.buf, spanStart, pos)
|
||||
pos = lexbase.handleLF(my, pos)
|
||||
add(my.a, '\L')
|
||||
spanStart = pos
|
||||
else:
|
||||
add(my.a, my.buf[pos])
|
||||
inc(pos)
|
||||
my.bufpos = pos # store back
|
||||
|
||||
|
||||
8
tests/effects/tcast_effect_violation.nim
Normal file
8
tests/effects/tcast_effect_violation.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
discard """
|
||||
errormsg: "cast(raises: ValueError) can raise an unlisted exception: ValueError"
|
||||
line: 7
|
||||
"""
|
||||
|
||||
proc fff() {.raises: [].} =
|
||||
{.cast(raises: ValueError).}:
|
||||
discard
|
||||
30
tests/exception/treraise_typeless_except_finally.nim
Normal file
30
tests/exception/treraise_typeless_except_finally.nim
Normal file
@@ -0,0 +1,30 @@
|
||||
discard """
|
||||
targets: "cpp"
|
||||
matrix: "--mm:arc; --mm:orc; --mm:refc"
|
||||
output: '''
|
||||
finally
|
||||
after
|
||||
'''
|
||||
"""
|
||||
|
||||
# Regression test: typeless `except:` followed by `finally:` must not
|
||||
# trigger ReraiseDefect at the end of the proc.
|
||||
#
|
||||
# Previously, `genTryCpp` only emitted `T_ = nullptr;` in the *typed*
|
||||
# except branches, leaving the typeless `except:` path with a still-set
|
||||
# `T_`. After the handler body and `popCurrentException`, the trailing
|
||||
# `if (T_) std::rethrow_exception(T_);` in the finally block would still
|
||||
# fire — but with the Nim exception stack already popped, the rethrow
|
||||
# bubbled up as a `ReraiseDefect: no exception to reraise`.
|
||||
|
||||
proc test() =
|
||||
try:
|
||||
raise newException(CatchableError, "x")
|
||||
except:
|
||||
let e = getCurrentException()
|
||||
discard e
|
||||
finally:
|
||||
echo "finally"
|
||||
|
||||
test()
|
||||
echo "after"
|
||||
@@ -20,3 +20,25 @@ block: # issue #24021
|
||||
discard
|
||||
else:
|
||||
discard foo.z
|
||||
|
||||
|
||||
# bug #22791
|
||||
type Foo = object
|
||||
case a: bool
|
||||
of false:
|
||||
discard
|
||||
of true:
|
||||
case b: bool
|
||||
of false:
|
||||
discard
|
||||
of true:
|
||||
c: bool
|
||||
|
||||
const f = Foo(a: true, b: true, c: true)
|
||||
case f.a
|
||||
of true:
|
||||
case f.b
|
||||
of true:
|
||||
echo f.c
|
||||
else: discard
|
||||
else: discard
|
||||
@@ -29,3 +29,30 @@ block tnestprc:
|
||||
result = x + y
|
||||
result = add(x, 3)
|
||||
doAssert Add3(7) == 10
|
||||
|
||||
block:
|
||||
type A = object
|
||||
c: int
|
||||
type H = proc(): lent A {.nimcall.}
|
||||
const u = A(c: 0)
|
||||
proc e(T: typedesc): lent A = u
|
||||
proc y(T: typedesc): H =
|
||||
proc(): lent A {.nimcall.} = T.e
|
||||
discard y(int)
|
||||
|
||||
block:
|
||||
type A = object
|
||||
c: int
|
||||
type H = proc(): lent A {.nimcall.}
|
||||
let u = A(c: 0)
|
||||
proc y(_: int | int): H =
|
||||
proc(): lent A {.nimcall.} = u
|
||||
discard y(0)
|
||||
|
||||
block:
|
||||
type A = object
|
||||
c: int
|
||||
type H = proc(): lent A {.nimcall.}
|
||||
let u = A()
|
||||
let _: H = proc(): lent A {.nimcall.} = u
|
||||
|
||||
|
||||
32
tests/template/toverload_over_untyped.nim
Normal file
32
tests/template/toverload_over_untyped.nim
Normal file
@@ -0,0 +1,32 @@
|
||||
discard """
|
||||
output: "ok"
|
||||
"""
|
||||
|
||||
# bug #25693
|
||||
|
||||
template g(b: untyped) {.dirty.} =
|
||||
template t: untyped = b
|
||||
|
||||
proc d() = discard @[0]
|
||||
proc g(_: int) = discard
|
||||
|
||||
proc f(a: var seq[int], _: string) =
|
||||
let p = @[0]
|
||||
d()
|
||||
a = p
|
||||
|
||||
let q = "a"
|
||||
g:
|
||||
var a: seq[int]
|
||||
try:
|
||||
f(a, q & "1")
|
||||
except CatchableError:
|
||||
discard
|
||||
try:
|
||||
f(a, q & "1")
|
||||
except CatchableError:
|
||||
discard
|
||||
block: t()
|
||||
block: t()
|
||||
echo "ok"
|
||||
|
||||
Reference in New Issue
Block a user