diff options
author | Araq <rumpf_a@web.de> | 2013-03-25 01:44:52 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-03-25 01:44:52 +0100 |
commit | 3051c52f517be70b4efb8d5823a3f4cb5cb7cd5e (patch) | |
tree | 9de025b3233866922587e49293ef10cf1d49c524 | |
parent | 0eae08af7e65c8863e22236ddbf269516808767e (diff) | |
download | Nim-3051c52f517be70b4efb8d5823a3f4cb5cb7cd5e.tar.gz |
fixes a long-standing bug about procvar checking
-rw-r--r-- | compiler/ast.nim | 2 | ||||
-rw-r--r-- | compiler/sem.nim | 2 | ||||
-rw-r--r-- | compiler/semdata.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 48 | ||||
-rw-r--r-- | compiler/sempass2.nim | 2 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 8 | ||||
-rw-r--r-- | tests/reject/mopaque.nim | 2 | ||||
-rw-r--r-- | todo.txt | 1 |
8 files changed, 45 insertions, 22 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index b59c93950..8816d461a 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -764,7 +764,7 @@ const dispatcherPos* = 8 # caution: if method has no 'result' it can be position 5! nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, - nkCommand, nkCallStrLit} + nkCommand, nkCallStrLit, nkHiddenCallConv} nkLambdaKinds* = {nkLambda, nkDo} nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice} diff --git a/compiler/sem.nim b/compiler/sem.nim index f20ab9a05..60ece4b30 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -201,7 +201,7 @@ proc myOpen(module: PSym): PPassContext = if c.p != nil: InternalError(module.info, "sem.myOpen") c.semConstExpr = semConstExpr c.semExpr = semExpr - c.semExprWithType = semExprWithType + c.semOperand = semOperand c.semConstBoolExpr = semConstBoolExpr c.semOverloadedCall = semOverloadedCall c.semTypeNode = semTypeNode diff --git a/compiler/semdata.nim b/compiler/semdata.nim index dd5f76172..ce91fb8af 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -69,7 +69,7 @@ type libs*: TLinkedList # all libs used by this module semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas 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 semOverloadedCall*: proc (c: PContext, n, nOrig: PNode, filter: TSymKinds): PNode {.nimcall.} diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 7d5fdc4f2..7bd732161 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -19,7 +19,20 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode -proc semExprWithType(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: @@ -33,15 +46,32 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = renderTree(result, {renderNoComments})) result.typ = errorType(c) -proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = +proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 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? + semProcvarCheck(c, result) + if result.typ.kind == tyVar: result = newDeref(result) + else: + LocalError(n.info, errExprXHasNoType, + renderTree(result, {renderNoComments})) + result.typ = errorType(c) + +proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = + result = semExpr(c, n, flags) + if result.kind == nkEmpty: + # do not produce another redundant error message: result = errorNode(c, n) if result.typ == nil: LocalError(n.info, errExprXHasNoType, renderTree(result, {renderNoComments})) result.typ = errorType(c) + else: + semProcvarCheck(c, result) proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = result = symChoice(c, n, s, scClosed) @@ -50,15 +80,6 @@ proc inlineConst(n: PNode, s: PSym): PNode {.inline.} = result = copyTree(s.ast) result.typ = s.typ 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 = case s.kind @@ -468,7 +489,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = proc analyseIfAddressTaken(c: PContext, n: PNode): PNode = result = n case n.kind - of nkSym: + of nkSym: # n.sym.typ can be nil in 'check' mode ... if n.sym.typ != nil and skipTypes(n.sym.typ, abstractInst-{tyTypeDesc}).kind != tyVar: @@ -512,6 +533,7 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = LocalError(n.sons[i].info, errVarForOutParamNeeded) return for i in countup(1, sonsLen(n) - 1): + semProcvarCheck(c, n.sons[i]) if i < sonsLen(t) and skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar: if n.sons[i].kind != nkHiddenAddr: @@ -1728,7 +1750,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = semCaptureSym(s, c.p.owner) result = semSym(c, n, s, flags) if s.kind in {skProc, skMethod, skIterator, skConverter}: - performProcvarCheck(c, n, s) + #performProcvarCheck(c, n, s) result = symChoice(c, n, s, scClosed) if result.kind == nkSym: markIndirect(c, result.sym) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index b2fd0fb04..f43820fa7 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -14,9 +14,7 @@ import # Second semantic checking pass over the AST. Necessary because the old # way had some inherent problems. Performs: # -# * procvar checks # * effect+exception tracking -# * closure analysis # * checks for invalid usages of compiletime magics (not implemented) # * checks for invalid usages of PNimNode (not implemented) # * later: will do an escape analysis for closures at least diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 882f582cb..f479267a0 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -177,12 +177,12 @@ proc NotFoundError*(c: PContext, n: PNode) = add(result, renderTree(n.sons[i].sons[0])) add(result, ": ") 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 n.sons[i].typ = nt else: 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 if nt.kind == tyError: return add(result, typeToString(nt)) @@ -812,13 +812,13 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode = # a.typ == nil is valid result = a elif a.typ.isNil: - result = c.semExprWithType(c, a, {efDetermineType}) + result = c.semOperand(c, a, {efDetermineType}) else: result = a proc prepareOperand(c: PContext; a: PNode): PNode = if a.typ.isNil: - result = c.semExprWithType(c, a, {efDetermineType}) + result = c.semOperand(c, a, {efDetermineType}) else: result = a diff --git a/tests/reject/mopaque.nim b/tests/reject/mopaque.nim index b7c5180fd..7eee4bd96 100644 --- a/tests/reject/mopaque.nim +++ b/tests/reject/mopaque.nim @@ -3,3 +3,5 @@ type line*: int filename*: string buffer: cstring + +proc noProcVar*(): int = 18 diff --git a/todo.txt b/todo.txt index de9210314..af126381b 100644 --- a/todo.txt +++ b/todo.txt @@ -13,6 +13,7 @@ version 0.9.2 - acyclic vs prunable; introduce GC hints - CGEN: ``restrict`` pragma + backend support; computed goto support - document NimMain and check whether it works for threading +- a project wide override option for 'dynlib' Bugs |