Merge branch 'devel' into pr_disable_sink

This commit is contained in:
ringabout
2026-05-29 20:26:03 +08:00
committed by GitHub
11 changed files with 171 additions and 10 deletions

View File

@@ -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):

View File

@@ -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}:

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View 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

View 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"

View File

@@ -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

View File

@@ -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

View 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"