fixes a long-standing bug about procvar checking
This commit is contained in:
parent
0eae08af7e
commit
3051c52f51
8 changed files with 45 additions and 22 deletions
|
|
@ -764,7 +764,7 @@ const
|
||||||
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5!
|
||||||
|
|
||||||
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix,
|
||||||
nkCommand, nkCallStrLit}
|
nkCommand, nkCallStrLit, nkHiddenCallConv}
|
||||||
|
|
||||||
nkLambdaKinds* = {nkLambda, nkDo}
|
nkLambdaKinds* = {nkLambda, nkDo}
|
||||||
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
|
nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
if c.p != nil: InternalError(module.info, "sem.myOpen")
|
if c.p != nil: InternalError(module.info, "sem.myOpen")
|
||||||
c.semConstExpr = semConstExpr
|
c.semConstExpr = semConstExpr
|
||||||
c.semExpr = semExpr
|
c.semExpr = semExpr
|
||||||
c.semExprWithType = semExprWithType
|
c.semOperand = semOperand
|
||||||
c.semConstBoolExpr = semConstBoolExpr
|
c.semConstBoolExpr = semConstBoolExpr
|
||||||
c.semOverloadedCall = semOverloadedCall
|
c.semOverloadedCall = semOverloadedCall
|
||||||
c.semTypeNode = semTypeNode
|
c.semTypeNode = semTypeNode
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ type
|
||||||
libs*: TLinkedList # all libs used by this module
|
libs*: TLinkedList # all libs used by this module
|
||||||
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
|
||||||
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||||
semExprWithType*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
semOperand*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
|
||||||
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
semConstBoolExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # XXX bite the bullet
|
||||||
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
semOverloadedCall*: proc (c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds): PNode {.nimcall.}
|
filter: TSymKinds): PNode {.nimcall.}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,33 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode =
|
||||||
|
|
||||||
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
|
||||||
|
|
||||||
|
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||||
|
var smoduleId = getModule(s).id
|
||||||
|
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
||||||
|
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
||||||
|
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
||||||
|
|
||||||
|
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||||
|
let n = n.skipConv
|
||||||
|
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
|
||||||
|
skConverter}:
|
||||||
|
performProcvarCheck(c, n, n.sym)
|
||||||
|
|
||||||
|
proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
|
# same as 'semExprWithType' but doesn't check for proc vars
|
||||||
|
result = semExpr(c, n, flags)
|
||||||
|
if result.kind == nkEmpty:
|
||||||
|
# do not produce another redundant error message:
|
||||||
|
#raiseRecoverableError("")
|
||||||
|
result = errorNode(c, n)
|
||||||
|
if result.typ != nil:
|
||||||
|
# XXX tyGenericInst here?
|
||||||
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
|
else:
|
||||||
|
LocalError(n.info, errExprXHasNoType,
|
||||||
|
renderTree(result, {renderNoComments}))
|
||||||
|
result.typ = errorType(c)
|
||||||
|
|
||||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, n, flags)
|
result = semExpr(c, n, flags)
|
||||||
if result.kind == nkEmpty:
|
if result.kind == nkEmpty:
|
||||||
|
|
@ -27,6 +54,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = errorNode(c, n)
|
result = errorNode(c, n)
|
||||||
if result.typ != nil:
|
if result.typ != nil:
|
||||||
# XXX tyGenericInst here?
|
# XXX tyGenericInst here?
|
||||||
|
semProcvarCheck(c, result)
|
||||||
if result.typ.kind == tyVar: result = newDeref(result)
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
else:
|
else:
|
||||||
LocalError(n.info, errExprXHasNoType,
|
LocalError(n.info, errExprXHasNoType,
|
||||||
|
|
@ -42,6 +70,8 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
LocalError(n.info, errExprXHasNoType,
|
LocalError(n.info, errExprXHasNoType,
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
else:
|
||||||
|
semProcvarCheck(c, result)
|
||||||
|
|
||||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
|
|
@ -51,15 +81,6 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
|
||||||
result.typ = s.typ
|
result.typ = s.typ
|
||||||
result.info = n.info
|
result.info = n.info
|
||||||
|
|
||||||
proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
|
||||||
# XXX this not correct; it's valid to pass to templates and macros.
|
|
||||||
# We really need another post nkCallConv check for this. Or maybe do it
|
|
||||||
# in transform().
|
|
||||||
var smoduleId = getModule(s).id
|
|
||||||
if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
|
|
||||||
smoduleId != c.module.id and smoduleId != c.friendModule.id:
|
|
||||||
LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
|
|
||||||
|
|
||||||
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skConst:
|
of skConst:
|
||||||
|
|
@ -512,6 +533,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
LocalError(n.sons[i].info, errVarForOutParamNeeded)
|
||||||
return
|
return
|
||||||
for i in countup(1, sonsLen(n) - 1):
|
for i in countup(1, sonsLen(n) - 1):
|
||||||
|
semProcvarCheck(c, n.sons[i])
|
||||||
if i < sonsLen(t) and
|
if i < sonsLen(t) and
|
||||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||||
if n.sons[i].kind != nkHiddenAddr:
|
if n.sons[i].kind != nkHiddenAddr:
|
||||||
|
|
@ -1728,7 +1750,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
semCaptureSym(s, c.p.owner)
|
semCaptureSym(s, c.p.owner)
|
||||||
result = semSym(c, n, s, flags)
|
result = semSym(c, n, s, flags)
|
||||||
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
||||||
performProcvarCheck(c, n, s)
|
#performProcvarCheck(c, n, s)
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
if result.kind == nkSym:
|
if result.kind == nkSym:
|
||||||
markIndirect(c, result.sym)
|
markIndirect(c, result.sym)
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ import
|
||||||
# Second semantic checking pass over the AST. Necessary because the old
|
# Second semantic checking pass over the AST. Necessary because the old
|
||||||
# way had some inherent problems. Performs:
|
# way had some inherent problems. Performs:
|
||||||
#
|
#
|
||||||
# * procvar checks
|
|
||||||
# * effect+exception tracking
|
# * effect+exception tracking
|
||||||
# * closure analysis
|
|
||||||
# * checks for invalid usages of compiletime magics (not implemented)
|
# * checks for invalid usages of compiletime magics (not implemented)
|
||||||
# * checks for invalid usages of PNimNode (not implemented)
|
# * checks for invalid usages of PNimNode (not implemented)
|
||||||
# * later: will do an escape analysis for closures at least
|
# * later: will do an escape analysis for closures at least
|
||||||
|
|
|
||||||
|
|
@ -177,12 +177,12 @@ proc NotFoundError*(c: PContext, n: PNode) =
|
||||||
add(result, renderTree(n.sons[i].sons[0]))
|
add(result, renderTree(n.sons[i].sons[0]))
|
||||||
add(result, ": ")
|
add(result, ": ")
|
||||||
if nt.isNil:
|
if nt.isNil:
|
||||||
n.sons[i].sons[1] = c.semExprWithType(c, n.sons[i].sons[1])
|
n.sons[i].sons[1] = c.semOperand(c, n.sons[i].sons[1])
|
||||||
nt = n.sons[i].sons[1].typ
|
nt = n.sons[i].sons[1].typ
|
||||||
n.sons[i].typ = nt
|
n.sons[i].typ = nt
|
||||||
else:
|
else:
|
||||||
if nt.isNil:
|
if nt.isNil:
|
||||||
n.sons[i] = c.semExprWithType(c, n.sons[i])
|
n.sons[i] = c.semOperand(c, n.sons[i])
|
||||||
nt = n.sons[i].typ
|
nt = n.sons[i].typ
|
||||||
if nt.kind == tyError: return
|
if nt.kind == tyError: return
|
||||||
add(result, typeToString(nt))
|
add(result, typeToString(nt))
|
||||||
|
|
@ -812,13 +812,13 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
|
||||||
# a.typ == nil is valid
|
# a.typ == nil is valid
|
||||||
result = a
|
result = a
|
||||||
elif a.typ.isNil:
|
elif a.typ.isNil:
|
||||||
result = c.semExprWithType(c, a, {efDetermineType})
|
result = c.semOperand(c, a, {efDetermineType})
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
proc prepareOperand(c: PContext; a: PNode): PNode =
|
proc prepareOperand(c: PContext; a: PNode): PNode =
|
||||||
if a.typ.isNil:
|
if a.typ.isNil:
|
||||||
result = c.semExprWithType(c, a, {efDetermineType})
|
result = c.semOperand(c, a, {efDetermineType})
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,5 @@ type
|
||||||
line*: int
|
line*: int
|
||||||
filename*: string
|
filename*: string
|
||||||
buffer: cstring
|
buffer: cstring
|
||||||
|
|
||||||
|
proc noProcVar*(): int = 18
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -13,6 +13,7 @@ version 0.9.2
|
||||||
- acyclic vs prunable; introduce GC hints
|
- acyclic vs prunable; introduce GC hints
|
||||||
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
||||||
- document NimMain and check whether it works for threading
|
- document NimMain and check whether it works for threading
|
||||||
|
- a project wide override option for 'dynlib'
|
||||||
|
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue