* restrict casting for closure. This commit forbid casting a closure to anything other than another closure. use rawEnv/rawProc to access underlaying pointers. * better error message for closure cast * fixes #5742
This commit is contained in:
parent
210955c3b6
commit
bbf9ef606d
2 changed files with 29 additions and 1 deletions
|
|
@ -152,6 +152,8 @@ proc isCastable(dst, src: PType): bool =
|
||||||
result = false
|
result = false
|
||||||
elif typeAllowed(dst, skParam) != nil:
|
elif typeAllowed(dst, skParam) != nil:
|
||||||
result = false
|
result = false
|
||||||
|
elif dst.kind == tyProc and dst.callConv == ccClosure:
|
||||||
|
result = src.kind == tyProc and src.callConv == ccClosure
|
||||||
else:
|
else:
|
||||||
result = (dstSize >= srcSize) or
|
result = (dstSize >= srcSize) or
|
||||||
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
(skipTypes(dst, abstractInst).kind in IntegralTypes) or
|
||||||
|
|
@ -227,7 +229,10 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||||
if tfHasMeta in targetType.flags:
|
if tfHasMeta in targetType.flags:
|
||||||
localError(n.sons[0].info, errCastToANonConcreteType, $targetType)
|
localError(n.sons[0].info, errCastToANonConcreteType, $targetType)
|
||||||
if not isCastable(targetType, castedExpr.typ):
|
if not isCastable(targetType, castedExpr.typ):
|
||||||
localError(n.info, errExprCannotBeCastToX, $targetType)
|
let tar = $targetType
|
||||||
|
let alt = typeToString(targetType, preferDesc)
|
||||||
|
let msg = if tar != alt: tar & "=" & alt else: tar
|
||||||
|
localError(n.info, errExprCannotBeCastToX, msg)
|
||||||
result = newNodeI(nkCast, n.info)
|
result = newNodeI(nkCast, n.info)
|
||||||
result.typ = targetType
|
result.typ = targetType
|
||||||
addSon(result, copyTree(n.sons[0]))
|
addSon(result, copyTree(n.sons[0]))
|
||||||
|
|
|
||||||
23
tests/misc/tcast.nim
Normal file
23
tests/misc/tcast.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
discard """
|
||||||
|
output: '''
|
||||||
|
Hello World
|
||||||
|
Hello World'''
|
||||||
|
"""
|
||||||
|
type MyProc = proc() {.cdecl.}
|
||||||
|
type MyProc2 = proc() {.nimcall.}
|
||||||
|
type MyProc3 = proc() #{.closure.} is implicit
|
||||||
|
|
||||||
|
proc testProc() = echo "Hello World"
|
||||||
|
|
||||||
|
proc callPointer(p: pointer) =
|
||||||
|
# can cast to proc(){.cdecl.}
|
||||||
|
let ffunc0 = cast[MyProc](p)
|
||||||
|
# can cast to proc(){.nimcall.}
|
||||||
|
let ffunc1 = cast[MyProc2](p)
|
||||||
|
# cannot cast to proc(){.closure.}
|
||||||
|
doAssert(not compiles(cast[MyProc3](p)))
|
||||||
|
|
||||||
|
ffunc0()
|
||||||
|
ffunc1()
|
||||||
|
|
||||||
|
callPointer(cast[pointer](testProc))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue