summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgcalls.nim30
-rw-r--r--compiler/pragmas.nim9
-rw-r--r--compiler/sempass2.nim42
-rw-r--r--compiler/sigmatch.nim25
4 files changed, 64 insertions, 42 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index b9fc694cb..fb878a83e 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -430,15 +430,27 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   assert(typ.kind == tyProc)
   var length = sonsLen(ri)
   assert(sonsLen(typ) == sonsLen(typ.n))
-  
-  if length > 1:
-    app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
-    app(pl, ~" ")
-  app(pl, op.r)
-  if length > 2:
-    app(pl, ~": ")
-    app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
-  for i in countup(3, length-1):
+
+  # don't call 'ropeToStr' here for efficiency:
+  let pat = ri.sons[0].sym.loc.r.data
+  internalAssert pat != nil
+  var start = 3
+  if ' ' in pat:
+    start = 1
+    app(pl, op.r)
+    if length > 1:
+      app(pl, ~": ")
+      app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
+      start = 2
+  else:
+    if length > 1:
+      app(pl, genArg(p, ri.sons[1], typ.n.sons[1].sym, ri))
+      app(pl, ~" ")
+    app(pl, op.r)
+    if length > 2:
+      app(pl, ~": ")
+      app(pl, genArg(p, ri.sons[2], typ.n.sons[2].sym, ri))
+  for i in countup(start, length-1):
     assert(sonsLen(typ) == sonsLen(typ.n))
     if i >= sonsLen(typ):
       internalError(ri.info, "varargs for objective C method?")
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 90f87696b..78ee490e2 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -735,11 +735,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
           incl(sym.flags, sfProcvar)
           if sym.typ != nil: incl(sym.typ.flags, tfThread)
         of wGcSafe:
-          if optThreadAnalysis in gGlobalOptions:
-            noVal(it)
-            if sym.kind != skType: incl(sym.flags, sfThread)
-            if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
-            else: invalidPragma(it)
+          noVal(it)
+          if sym.kind != skType: incl(sym.flags, sfThread)
+          if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
+          else: invalidPragma(it)
         of wPacked:
           noVal(it)
           if sym.typ == nil: invalidPragma(it)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index ede556a70..3f78629c8 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -194,6 +194,9 @@ proc warnAboutGcUnsafe(n: PNode) =
   #assert false
   message(n.info, warnGcUnsafe, renderTree(n))
 
+template markGcUnsafe(a: PEffects) =
+  a.gcUnsafe = true
+
 proc useVar(a: PEffects, n: PNode) =
   let s = n.sym
   if isLocalVar(a, s):
@@ -209,7 +212,7 @@ proc useVar(a: PEffects, n: PNode) =
     if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and 
         tfGcSafe notin s.typ.flags:
       if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
-      a.gcUnsafe = true
+      markGcUnsafe(a)
 
 type
   TIntersection = seq[tuple[id, count: int]] # a simple count table
@@ -448,7 +451,7 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
 
   if notGcSafe(s.typ) and sfImportc notin s.flags:
     if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
-    tracked.gcUnsafe = true
+    markGcUnsafe(tracked)
   mergeLockLevels(tracked, n, s.getLockLevel)
 
 proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
@@ -502,13 +505,13 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
       # assume GcUnsafe unless in its type; 'forward' does not matter:
       if notGcSafe(op) and not isOwnedProcVar(a, tracked.owner):
         if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
-        tracked.gcUnsafe = true
+        markGcUnsafe(tracked)
     else:
       mergeEffects(tracked, effectList.sons[exceptionEffects], n)
       mergeTags(tracked, effectList.sons[tagEffects], n)
       if notGcSafe(op):
         if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
-        tracked.gcUnsafe = true
+        markGcUnsafe(tracked)
   notNilCheck(tracked, n, paramType)
 
 proc breaksBlock(n: PNode): bool =
@@ -656,7 +659,7 @@ proc track(tracked: PEffects, n: PNode) =
           # and it's not a recursive call:
           if not (a.kind == nkSym and a.sym == tracked.owner):
             warnAboutGcUnsafe(n)
-            tracked.gcUnsafe = true
+            markGcUnsafe(tracked)
     for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
     if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
       # may not look like an assignment, but it is:
@@ -825,7 +828,7 @@ proc trackProc*(s: PSym, body: PNode) =
   # effects already computed?
   if sfForward in s.flags: return
   if effects.len == effectListLen: return
-  
+
   var t: TEffects
   initEffects(effects, s, t)
   track(t, body)
@@ -849,19 +852,20 @@ proc trackProc*(s: PSym, body: PNode) =
     # after the check, use the formal spec:
     effects.sons[tagEffects] = tagsSpec
 
-  if optThreadAnalysis in gGlobalOptions:
-    if sfThread in s.flags and t.gcUnsafe:
-      if optThreads in gGlobalOptions:
-        localError(s.info, "'$1' is not GC-safe" % s.name.s)
-      else:
-        localError(s.info, warnGcUnsafe2, s.name.s)
-    if not t.gcUnsafe: s.typ.flags.incl tfGcSafe
-    if s.typ.lockLevel == UnspecifiedLockLevel:
-      s.typ.lockLevel = t.maxLockLevel
-    elif t.maxLockLevel > s.typ.lockLevel:
-      localError(s.info,
-        "declared lock level is $1, but real lock level is $2" %
-          [$s.typ.lockLevel, $t.maxLockLevel])
+  if sfThread in s.flags and t.gcUnsafe:
+    if optThreads in gGlobalOptions and optThreadAnalysis in gGlobalOptions:
+      localError(s.info, "'$1' is not GC-safe" % s.name.s)
+    else:
+      localError(s.info, warnGcUnsafe2, s.name.s)
+  if not t.gcUnsafe:
+    s.typ.flags.incl tfGcSafe
+  if s.typ.lockLevel == UnspecifiedLockLevel:
+    s.typ.lockLevel = t.maxLockLevel
+  elif t.maxLockLevel > s.typ.lockLevel:
+    #localError(s.info,
+    message(s.info, warnLockLevel,
+      "declared lock level is $1, but real lock level is $2" %
+        [$s.typ.lockLevel, $t.maxLockLevel])
 
 proc trackTopLevelStmt*(module: PSym; n: PNode) =
   if n.kind in {nkPragma, nkMacroDef, nkTemplateDef, nkProcDef,
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9a99d5200..00802e69b 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -418,7 +418,8 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
 
     if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
       return isNone
-    elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
+    elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {} and
+        optThreadAnalysis in gGlobalOptions:
       # noSideEffect implies ``tfThread``!
       return isNone
     elif f.flags * {tfIterator} != a.flags * {tfIterator}:
@@ -1441,13 +1442,14 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         return
       checkConstraint(n.sons[a].sons[1])
       if m.baseTypeMatch: 
-        assert(container == nil)
+        #assert(container == nil)
         container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
         addSon(container, arg)
         setSon(m.call, formal.position + 1, container)
         if f != formalLen - 1: container = nil
-      else: 
+      else:
         setSon(m.call, formal.position + 1, arg)
+      inc f
     else:
       # unnamed param
       if f >= formalLen:
@@ -1466,7 +1468,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
           var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
                                     n.sons[a], nOrig.sons[a])
-          if (arg != nil) and m.baseTypeMatch and (container != nil):
+          if arg != nil and m.baseTypeMatch and container != nil:
             addSon(container, arg)
             incrIndexType(container.typ)
           else:
@@ -1480,7 +1482,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           internalError(n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
-        if containsOrIncl(marker, formal.position): 
+        if containsOrIncl(marker, formal.position) and container.isNil:
           # already in namedParams:
           localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
@@ -1493,17 +1495,22 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.state = csNoMatch
           return
         if m.baseTypeMatch:
-          assert(container == nil)
-          container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
+          #assert(container == nil)
+          if container.isNil:
+            container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
           addSon(container, arg)
           setSon(m.call, formal.position + 1, 
                  implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
-          if f != formalLen - 1: container = nil
+          #if f != formalLen - 1: container = nil
+
+          # pick the formal from the end, so that 'x, y, varargs, z' works:
+          f = max(f, formalLen - n.len + a + 1)
         else:
           setSon(m.call, formal.position + 1, arg)
+          inc(f)
+          container = nil
       checkConstraint(n.sons[a])
     inc(a)
-    inc(f)
 
 proc semFinishOperands*(c: PContext, n: PNode) =
   # this needs to be called to ensure that after overloading resolution every