summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ccgexprs.nim9
-rw-r--r--compiler/ccgtypes.nim16
-rw-r--r--compiler/cgendata.nim1
-rw-r--r--compiler/commands.nim6
-rw-r--r--compiler/importer.nim22
-rw-r--r--compiler/lookups.nim17
-rw-r--r--compiler/modulegraphs.nim4
-rw-r--r--compiler/modules.nim1
-rw-r--r--compiler/msgs.nim8
-rw-r--r--compiler/nim.nim6
-rw-r--r--compiler/nimeval.nim11
-rw-r--r--compiler/options.nim7
-rw-r--r--compiler/passes.nim27
-rw-r--r--compiler/pragmas.nim3
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semgnrc.nim4
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/wordrecg.nim4
19 files changed, 111 insertions, 40 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index f8b0ac6cf..d68e26ec3 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -354,6 +354,14 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   else: internalError("genAssignment: " & $ty.kind)
 
+  if optMemTracker in p.options and dest.s in {OnHeap, OnUnknown}:
+    #writeStackTrace()
+    #echo p.currLineInfo, " requesting"
+    linefmt(p, cpsStmts, "#memTrackerWrite((void*)$1, $2, $3, $4);$n",
+            addrLoc(dest), rope getSize(dest.t),
+            makeCString(p.currLineInfo.toFullPath),
+            rope p.currLineInfo.safeLineNm)
+
 proc genDeepCopy(p: BProc; dest, src: TLoc) =
   var ty = skipTypes(dest.t, abstractVarRange)
   case ty.kind
@@ -1940,6 +1948,7 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
       d.s = OnStatic
 
 proc expr(p: BProc, n: PNode, d: var TLoc) =
+  p.currLineInfo = n.info
   case n.kind
   of nkSym:
     var sym = n.sym
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 9b12d38a2..5c13d8186 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -221,6 +221,10 @@ proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
   # linear search is not necessary anymore:
   result = tab.getOrDefault(sig)
 
+proc addAbiCheck(m: BModule, t: PType, name: Rope) =
+  if isDefined("checkabi"):
+    addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(getSize(t))])
+
 proc getTempName(m: BModule): Rope =
   result = m.tmpBase & rope(m.labels)
   inc m.labels
@@ -282,6 +286,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
     result = getSimpleTypeDesc(m, lastSon typ)
   else: result = nil
 
+  if result != nil and typ.isImportedType():
+    if cacheGetType(m.typeCache, typ) == nil:
+      idTablePut(m.typeCache, typ, result)
+      addAbiCheck(m, typ, result)
+
 proc pushType(m: BModule, typ: PType) =
   add(m.typeStack, typ)
 
@@ -678,6 +687,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
       let foo = getTypeDescAux(m, t.sons[1], check)
       addf(m.s[cfsTypes], "typedef $1 $2[$3];$n",
            [foo, result, rope(n)])
+    else: addAbiCheck(m, t, result)
   of tyObject, tyTuple:
     if isImportedCppType(t) and origTyp.kind == tyGenericInst:
       # for instantiated templates we do not go through the type cache as the
@@ -739,7 +749,9 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
       m.typeCache[sig] = result # always call for sideeffects:
       let recdesc = if t.kind != tyTuple: getRecordDesc(m, t, result, check)
                     else: getTupleDesc(m, t, result, check)
-      if not isImportedType(t): add(m.s[cfsTypes], recdesc)
+      if not isImportedType(t):
+        add(m.s[cfsTypes], recdesc)
+      elif tfIncompleteStruct notin t.flags: addAbiCheck(m, t, result)
   of tySet:
     result = getTypeName(m, t.lastSon, hashType t.lastSon) & "_Set"
     m.typeCache[sig] = result
@@ -841,6 +853,8 @@ proc genTypeInfoAuxBase(m: BModule; typ, origType: PType; name, base: Rope) =
   #else MessageOut("can contain a cycle: " & typeToString(typ))
   if flags != 0:
     addf(m.s[cfsTypeInit3], "$1.flags = $2;$n", [name, rope(flags)])
+  if isDefined("nimTypeNames"):
+    addf(m.s[cfsTypeInit3], "$1.name = $2;$n", [name, makeCstring typeToString origType])
   discard cgsym(m, "TNimType")
   addf(m.s[cfsVars], "TNimType $1; /* $2 */$n",
        [name, rope(typeToString(typ))])
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 5afdabf9a..c8146fc5f 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -69,6 +69,7 @@ type
     beforeRetNeeded*: bool    # true iff 'BeforeRet' label for proc is needed
     threadVarAccessed*: bool  # true if the proc already accessed some threadvar
     lastLineInfo*: TLineInfo  # to avoid generating excessive 'nimln' statements
+    currLineInfo*: TLineInfo  # AST codegen will make this superfluous
     nestedTryStmts*: seq[PNode]   # in how many nested try statements we are
                                   # (the vars must be volatile then)
     inExceptBlock*: int       # are we currently inside an except block?
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 85951a28f..590c4871d 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -242,6 +242,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "linetrace": result = contains(gOptions, optLineTrace)
   of "debugger": result = contains(gOptions, optEndb)
   of "profiler": result = contains(gOptions, optProfiler)
+  of "memtracker": result = contains(gOptions, optMemTracker)
   of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions
   of "floatchecks":
     result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck}
@@ -264,6 +265,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "implicitstatic": result = contains(gOptions, optImplicitStatic)
   of "patterns": result = contains(gOptions, optPatterns)
   of "experimental": result = gExperimentalMode
+  of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace)
   else: invalidCmdLineOption(passCmd1, switch, info)
 
 proc processPath(path: string, info: TLineInfo,
@@ -445,6 +447,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     processOnOffSwitch({optProfiler}, arg, pass, info)
     if optProfiler in gOptions: defineSymbol("profiler")
     else: undefSymbol("profiler")
+  of "memtracker":
+    processOnOffSwitch({optMemTracker}, arg, pass, info)
+    if optMemTracker in gOptions: defineSymbol("memtracker")
+    else: undefSymbol("memtracker")
   of "checks", "x": processOnOffSwitch(ChecksOptions, arg, pass, info)
   of "floatchecks":
     processOnOffSwitch({optNaNCheck, optInfCheck}, arg, pass, info)
diff --git a/compiler/importer.nim b/compiler/importer.nim
index ce365c4dc..feebf97c4 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -100,7 +100,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
   let ident = lookups.considerQuotedIdent(n)
   let s = strTableGet(fromMod.tab, ident)
   if s == nil:
-    localError(n.info, errUndeclaredIdentifier, ident.s)
+    errorUndeclaredIdentifier(c, n.info, ident.s)
   else:
     if s.kind == skStub: loadStub(s)
     if s.kind notin ExportableSymKinds:
@@ -162,12 +162,26 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
 proc myImportModule(c: PContext, n: PNode): PSym =
   var f = checkModuleName(n)
   if f != InvalidFileIDX:
+    let L = c.graph.importStack.len
+    let recursion = c.graph.importStack.find(f)
+    c.graph.importStack.add f
+    #echo "adding ", toFullPath(f), " at ", L+1
+    if recursion >= 0:
+      var err = ""
+      for i in countup(recursion, L-1):
+        if i > recursion: err.add "\n"
+        err.add toFullPath(c.graph.importStack[i]) & " imports " &
+                toFullPath(c.graph.importStack[i+1])
+      c.recursiveDep = err
     result = importModuleAs(n, gImportModule(c.graph, c.module, f, c.cache))
+    #echo "set back to ", L
+    c.graph.importStack.setLen(L)
     # we cannot perform this check reliably because of
     # test: modules/import_in_config)
-    if result.info.fileIndex == c.module.info.fileIndex and
-        result.info.fileIndex == n.info.fileIndex:
-      localError(n.info, errGenerated, "A module cannot import itself")
+    when true:
+      if result.info.fileIndex == c.module.info.fileIndex and
+          result.info.fileIndex == n.info.fileIndex:
+        localError(n.info, errGenerated, "A module cannot import itself")
     if sfDeprecated in result.flags:
       message(n.info, warnDeprecated, result.name.s)
     #suggestSym(n.info, result, false)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index df19a6afb..fe159011c 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -242,6 +242,15 @@ proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
     inc i
   localError(info, errGenerated, err)
 
+proc errorUndeclaredIdentifier*(c: PContext; info: TLineInfo; name: string) =
+  var err = "undeclared identifier: '" & name & "'"
+  if c.recursiveDep.len > 0:
+    err.add "\nThis might be caused by a recursive module dependency: "
+    err.add c.recursiveDep
+    # prevent excessive errors for 'nim check'
+    c.recursiveDep = nil
+  localError(info, errGenerated, err)
+
 proc lookUp*(c: PContext, n: PNode): PSym =
   # Looks up a symbol. Generates an error in case of nil.
   case n.kind
@@ -249,7 +258,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
     result = searchInScopes(c, n.ident).skipAlias(n)
     if result == nil:
       fixSpelling(n, n.ident, searchInScopes)
-      localError(n.info, errUndeclaredIdentifier, n.ident.s)
+      errorUndeclaredIdentifier(c, n.info, n.ident.s)
       result = errorSym(c, n)
   of nkSym:
     result = n.sym
@@ -258,7 +267,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
     result = searchInScopes(c, ident).skipAlias(n)
     if result == nil:
       fixSpelling(n, ident, searchInScopes)
-      localError(n.info, errUndeclaredIdentifier, ident.s)
+      errorUndeclaredIdentifier(c, n.info, ident.s)
       result = errorSym(c, n)
   else:
     internalError(n.info, "lookUp")
@@ -282,7 +291,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
       result = searchInScopes(c, ident, allExceptModule).skipAlias(n)
     if result == nil and checkUndeclared in flags:
       fixSpelling(n, ident, searchInScopes)
-      localError(n.info, errUndeclaredIdentifier, ident.s)
+      errorUndeclaredIdentifier(c, n.info, ident.s)
       result = errorSym(c, n)
     elif checkAmbiguity in flags and result != nil and
         contains(c.ambiguousSymbols, result.id):
@@ -307,7 +316,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
           result = strTableGet(m.tab, ident).skipAlias(n)
         if result == nil and checkUndeclared in flags:
           fixSpelling(n.sons[1], ident, searchInScopes)
-          localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
+          errorUndeclaredIdentifier(c, n.sons[1].info, ident.s)
           result = errorSym(c, n.sons[1])
       elif n.sons[1].kind == nkSym:
         result = n.sons[1].sym
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index 9a3caa663..38fd4f89f 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -36,6 +36,8 @@ type
     invalidTransitiveClosure: bool
     inclToMod*: Table[int32, int32] # mapping of include file to the
                                     # first module that included it
+    importStack*: seq[int32]  # The current import stack. Used for detecting recursive
+                              # module dependencies.
 
 {.this: g.}
 
@@ -44,12 +46,14 @@ proc newModuleGraph*(): ModuleGraph =
   initStrTable(result.packageSyms)
   result.deps = initIntSet()
   result.modules = @[]
+  result.importStack = @[]
   result.inclToMod = initTable[int32, int32]()
 
 proc resetAllModules*(g: ModuleGraph) =
   initStrTable(packageSyms)
   deps = initIntSet()
   modules = @[]
+  importStack = @[]
   inclToMod = initTable[int32, int32]()
 
 proc getModule*(g: ModuleGraph; fileIdx: int32): PSym =
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 26ca2177b..3451d85ec 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -231,6 +231,7 @@ proc compileProject*(graph: ModuleGraph; cache: IdentCache;
   wantMainModule()
   let systemFileIdx = fileInfoIdx(options.libpath / "system.nim")
   let projectFile = if projectFileIdx < 0: gProjectMainIdx else: projectFileIdx
+  graph.importStack.add projectFile
   if projectFile == systemFileIdx:
     discard graph.compileModule(projectFile, cache, {sfMainModule, sfSystemModule})
   else:
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index a44a1306c..94b0bee00 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -35,7 +35,7 @@ type
     errNoneSpeedOrSizeExpectedButXFound, errGuiConsoleOrLibExpectedButXFound,
     errUnknownOS, errUnknownCPU, errGenOutExpectedButXFound,
     errArgsNeedRunOption, errInvalidMultipleAsgn, errColonOrEqualsExpected,
-    errExprExpected, errUndeclaredIdentifier, errUndeclaredField,
+    errExprExpected, errUndeclaredField,
     errUndeclaredRoutine, errUseQualifier,
     errTypeExpected,
     errSystemNeeds, errExecutionOfProgramFailed, errNotOverloadable,
@@ -197,7 +197,6 @@ const
     errInvalidMultipleAsgn: "multiple assignment is not allowed",
     errColonOrEqualsExpected: "\':\' or \'=\' expected, but found \'$1\'",
     errExprExpected: "expression expected, but found \'$1\'",
-    errUndeclaredIdentifier: "undeclared identifier: \'$1\'",
     errUndeclaredField: "undeclared field: \'$1\'",
     errUndeclaredRoutine: "attempting to call undeclared routine: \'$1\'",
     errUseQualifier: "ambiguous identifier: \'$1\' -- use a qualifier",
@@ -676,9 +675,8 @@ proc getInfoContext*(index: int): TLineInfo =
   if i >=% L: result = unknownLineInfo()
   else: result = msgContext[i]
 
-proc toFilename*(fileIdx: int32): string =
-  if fileIdx < 0: result = "???"
-  else: result = fileInfos[fileIdx].projPath
+template toFilename*(fileIdx: int32): string =
+  (if fileIdx < 0: "???" else: fileInfos[fileIdx].projPath)
 
 proc toFullPath*(fileIdx: int32): string =
   if fileIdx < 0: result = "???"
diff --git a/compiler/nim.nim b/compiler/nim.nim
index f8d6b607a..35afecf20 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -46,7 +46,7 @@ proc handleCmdLine(cache: IdentCache) =
     if gProjectName == "-":
       gProjectName = "stdinfile"
       gProjectFull = "stdinfile"
-      gProjectPath = getCurrentDir()
+      gProjectPath = canonicalizePath getCurrentDir()
       gProjectIsStdin = true
     elif gProjectName != "":
       try:
@@ -54,10 +54,10 @@ proc handleCmdLine(cache: IdentCache) =
       except OSError:
         gProjectFull = gProjectName
       let p = splitFile(gProjectFull)
-      gProjectPath = p.dir
+      gProjectPath = canonicalizePath p.dir
       gProjectName = p.name
     else:
-      gProjectPath = getCurrentDir()
+      gProjectPath = canonicalizePath getCurrentDir()
     loadConfigs(DefaultConfig) # load all config files
     let scriptFile = gProjectFull.changeFileExt("nims")
     if fileExists(scriptFile):
diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim
index 2bddb76e7..2872bdade 100644
--- a/compiler/nimeval.nim
+++ b/compiler/nimeval.nim
@@ -8,10 +8,9 @@
 #
 
 ## exposes the Nim VM to clients.
-
 import
   ast, modules, passes, passaux, condsyms,
-  options, nimconf, lists, sem, semdata, llstream, vm
+  options, nimconf, lists, sem, semdata, llstream, vm, modulegraphs, idents
 
 proc execute*(program: string) =
   passes.gIncludeFile = includeModule
@@ -27,7 +26,9 @@ proc execute*(program: string) =
   registerPass(evalPass)
 
   appendStr(searchPaths, options.libpath)
-  compileSystemModule()
-  var m = makeStdinModule()
+  var graph = newModuleGraph()
+  var cache = newIdentCache()
+  var m = makeStdinModule(graph)
   incl(m.flags, sfMainModule)
-  processModule(m, llStreamOpen(program), nil)
+  compileSystemModule(graph,cache)
+  processModule(graph,m, llStreamOpen(program), nil, cache)
diff --git a/compiler/options.nim b/compiler/options.nim
index 7cf707945..9edafb17a 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -34,7 +34,8 @@ type                          # please make sure we have under 32 options
     optProfiler,              # profiler turned on
     optImplicitStatic,        # optimization: implicit at compile time
                               # evaluation
-    optPatterns               # en/disable pattern matching
+    optPatterns,              # en/disable pattern matching
+    optMemTracker
 
   TOptions* = set[TOption]
   TGlobalOption* = enum       # **keep binary compatible**
@@ -231,10 +232,10 @@ proc canonicalizePath*(path: string): string =
 
 proc shortenDir*(dir: string): string =
   ## returns the interesting part of a dir
-  var prefix = getPrefixDir() & DirSep
+  var prefix = gProjectPath & DirSep
   if startsWith(dir, prefix):
     return substr(dir, len(prefix))
-  prefix = gProjectPath & DirSep
+  prefix = getPrefixDir() & DirSep
   if startsWith(dir, prefix):
     return substr(dir, len(prefix))
   result = dir
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 4f1d4e3aa..3cc15147e 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -149,14 +149,25 @@ proc closePassesCached(a: var TPassContextArray) =
       m = gPasses[i].close(a[i], m)
     a[i] = nil                # free the memory here
 
+proc resolveMod(module, relativeTo: string): int32 =
+  let fullPath = findModule(module, relativeTo)
+  if fullPath.len == 0:
+    result = InvalidFileIDX
+  else:
+    result = fullPath.fileInfoIdx
+
 proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
-                      a: var TPassContextArray) =
+                      a: var TPassContextArray; m: PSym) =
+  # XXX fixme this should actually be relative to the config file!
+  let relativeTo = m.info.toFullPath
   for module in items(implicits):
-    var importStmt = newNodeI(nodeKind, gCmdLineInfo)
-    var str = newStrNode(nkStrLit, module)
-    str.info = gCmdLineInfo
-    importStmt.addSon str
-    if not processTopLevelStmt(importStmt, a): break
+    # implicit imports should not lead to a module importing itself
+    if m.position != resolveMod(module, relativeTo):
+      var importStmt = newNodeI(nodeKind, gCmdLineInfo)
+      var str = newStrNode(nkStrLit, module)
+      str.info = gCmdLineInfo
+      importStmt.addSon str
+      if not processTopLevelStmt(importStmt, a): break
 
 proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
                     rd: PRodReader; cache: IdentCache): bool {.discardable.} =
@@ -183,8 +194,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
         # modules to include between compilation runs? we'd need to track that
         # in ROD files. I think we should enable this feature only
         # for the interactive mode.
-        processImplicits implicitImports, nkImportStmt, a
-        processImplicits implicitIncludes, nkIncludeStmt, a
+        processImplicits implicitImports, nkImportStmt, a, module
+        processImplicits implicitIncludes, nkIncludeStmt, a, module
 
       while true:
         var n = parseTopLevelStmt(p)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index f4109b26d..e11a8d08b 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -323,7 +323,8 @@ proc processOption(c: PContext, n: PNode): bool =
     of wStacktrace: onOff(c, n, {optStackTrace})
     of wLinetrace: onOff(c, n, {optLineTrace})
     of wDebugger: onOff(c, n, {optEndb})
-    of wProfiler: onOff(c, n, {optProfiler})
+    of wProfiler: onOff(c, n, {optProfiler, optMemTracker})
+    of wMemTracker: onOff(c, n, {optMemTracker})
     of wByRef: onOff(c, n, {optByRef})
     of wDynlib: processDynLib(c, n, nil)
     of wOptimization:
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 5b84b7cdf..2fec8c757 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -110,6 +110,7 @@ type
     cache*: IdentCache
     graph*: ModuleGraph
     signatures*: TStrTable
+    recursiveDep*: string
 
 proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair =
   result.genericSym = s
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 0a4e39878..60435202b 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1553,7 +1553,7 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
   if isCallExpr(n):
     var expandedSym = qualifiedLookUp(c, n[0], {checkUndeclared})
     if expandedSym == nil:
-      localError(n.info, errUndeclaredIdentifier, n[0].renderTree)
+      errorUndeclaredIdentifier(c, n.info, n[0].renderTree)
       return errorSym(c, n[0])
 
     if expandedSym.kind notin {skMacro, skTemplate}:
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index b8451865e..ab0ce7c4c 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -107,7 +107,7 @@ proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
   var s = searchInScopes(c, ident).skipAlias(n)
   if s == nil:
     if ident.id notin ctx.toMixin and withinMixin notin flags:
-      localError(n.info, errUndeclaredIdentifier, ident.s)
+      errorUndeclaredIdentifier(c, n.info, ident.s)
   else:
     if withinBind in flags:
       result = symChoice(c, n, s, scClosed)
@@ -195,7 +195,7 @@ proc semGenericStmt(c: PContext, n: PNode,
     if s == nil and withinMixin notin flags and
         fn.kind in {nkIdent, nkAccQuoted} and
         considerQuotedIdent(fn).id notin ctx.toMixin:
-      localError(n.info, errUndeclaredIdentifier, fn.renderTree)
+      errorUndeclaredIdentifier(c, n.info, fn.renderTree)
 
     var first = 0
     var mixinContext = false
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index cd90782d1..e72172c81 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -143,7 +143,7 @@ proc semBindSym(c: PContext, n: PNode): PNode =
     var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
     result.add(sc)
   else:
-    localError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
+    errorUndeclaredIdentifier(c, n.sons[1].info, sl.strVal)
 
 proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
 
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 04376892f..cf66b6358 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -34,7 +34,7 @@ type
 
     wColon, wColonColon, wEquals, wDot, wDotDot,
     wStar, wMinus,
-    wMagic, wThread, wFinal, wProfiler, wObjChecks,
+    wMagic, wThread, wFinal, wProfiler, wMemTracker, wObjChecks,
     wIntDefine, wStrDefine,
 
     wDestroy,
@@ -121,7 +121,7 @@ const
 
     ":", "::", "=", ".", "..",
     "*", "-",
-    "magic", "thread", "final", "profiler", "objchecks", "intdefine", "strdefine",
+    "magic", "thread", "final", "profiler", "memtracker", "objchecks", "intdefine", "strdefine",
 
     "destroy",