summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-03-25 01:44:52 +0100
committerAraq <rumpf_a@web.de>2013-03-25 01:44:52 +0100
commit3051c52f517be70b4efb8d5823a3f4cb5cb7cd5e (patch)
tree9de025b3233866922587e49293ef10cf1d49c524
parent0eae08af7e65c8863e22236ddbf269516808767e (diff)
downloadNim-3051c52f517be70b4efb8d5823a3f4cb5cb7cd5e.tar.gz
fixes a long-standing bug about procvar checking
-rw-r--r--compiler/ast.nim2
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semdata.nim2
-rw-r--r--compiler/semexprs.nim48
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/sigmatch.nim8
-rw-r--r--tests/reject/mopaque.nim2
-rw-r--r--todo.txt1
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