summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md6
-rw-r--r--compiler/ast.nim8
-rw-r--r--compiler/ccgexprs.nim5
-rw-r--r--compiler/ccgstmts.nim18
-rw-r--r--compiler/ccgutils.nim4
-rw-r--r--compiler/cgen.nim4
-rw-r--r--compiler/commands.nim52
-rw-r--r--compiler/extccomp.nim3
-rw-r--r--compiler/nim.nim10
-rw-r--r--compiler/nimconf.nim4
-rw-r--r--compiler/options.nim19
-rw-r--r--compiler/passes.nim2
-rw-r--r--compiler/pragmas.nim36
-rw-r--r--compiler/renderer.nim33
-rw-r--r--compiler/reorder.nim2
-rw-r--r--compiler/rodread.nim2
-rw-r--r--compiler/scriptconfig.nim6
-rw-r--r--compiler/semasgn.nim4
-rw-r--r--compiler/semcall.nim2
-rw-r--r--compiler/semdata.nim6
-rw-r--r--compiler/semexprs.nim6
-rw-r--r--compiler/semstmts.nim71
-rw-r--r--compiler/semtypinst.nim4
-rw-r--r--compiler/service.nim14
-rw-r--r--compiler/transf.nim6
-rw-r--r--compiler/wordrecg.nim6
-rw-r--r--doc/advopt.txt6
-rw-r--r--doc/basicopt.txt1
-rw-r--r--doc/manual.rst37
-rw-r--r--doc/nimc.rst4
-rw-r--r--lib/deprecated/pure/sockets.nim2
-rw-r--r--lib/impure/db_sqlite.nim2
-rw-r--r--lib/impure/rdstdin.nim2
-rw-r--r--lib/posix/epoll.nim2
-rw-r--r--lib/posix/inotify.nim2
-rw-r--r--lib/posix/kqueue.nim8
-rw-r--r--lib/posix/linux.nim2
-rw-r--r--lib/posix/posix.nim8
-rw-r--r--lib/posix/posix_other.nim2
-rw-r--r--lib/posix/termios.nim2
-rw-r--r--lib/pure/fenv.nim57
-rw-r--r--lib/pure/matchers.nim2
-rw-r--r--lib/pure/net.nim2
-rw-r--r--lib/pure/os.nim2
-rw-r--r--lib/pure/parseutils.nim2
-rw-r--r--lib/pure/random.nim2
-rw-r--r--lib/pure/ropes.nim2
-rw-r--r--lib/pure/strmisc.nim2
-rw-r--r--lib/pure/strutils.nim19
-rw-r--r--lib/pure/times.nim60
-rw-r--r--lib/pure/unicode.nim2
-rw-r--r--lib/pure/xmltree.nim9
-rw-r--r--lib/system.nim44
-rw-r--r--lib/windows/winlean.nim2
-rw-r--r--lib/wrappers/iup.nim2
-rw-r--r--lib/wrappers/mysql.nim2
-rw-r--r--lib/wrappers/odbcsql.nim2
-rw-r--r--lib/wrappers/openssl.nim2
-rw-r--r--lib/wrappers/pcre.nim2
-rw-r--r--lib/wrappers/postgres.nim2
-rw-r--r--lib/wrappers/sqlite3.nim2
-rw-r--r--nimsuggest/nimsuggest.nim8
-rw-r--r--tests/assign/toverload_asgn1.nim1
-rw-r--r--tests/assign/toverload_asgn2.nim1
-rw-r--r--tests/collections/tcollections_to_string.nim10
-rw-r--r--tests/enum/toptions.nim2
-rw-r--r--tests/flags/tgenscript.nim5
-rw-r--r--tests/iter/tobj_iter.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim1
-rw-r--r--tests/manyloc/keineschweine/dependencies/enet/enet.nim1
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim1
-rw-r--r--tests/manyloc/keineschweine/keineschweine.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/sg_gui.nim2
-rw-r--r--tests/manyloc/keineschweine/server/nim.cfg1
-rw-r--r--tests/manyloc/nake/nakefile.nim2
-rw-r--r--tests/manyloc/standalone/barebone.nim.cfg1
-rw-r--r--tests/parallel/tparfind.nim2
-rw-r--r--tests/pragmas/tnoreturn.nim7
-rw-r--r--tests/rodfiles/deadg.nim3
-rw-r--r--tests/stdlib/ttimes.nim8
-rw-r--r--tests/testament/backend.nim2
-rw-r--r--tests/testament/categories.nim28
-rw-r--r--tests/testament/htmlgen.nim2
-rw-r--r--tests/testament/tester.nim25
-rw-r--r--tools/nim.bash-completion4
-rw-r--r--tools/nim.zsh-completion2
-rw-r--r--tools/nimgrep.nim21
90 files changed, 405 insertions, 379 deletions
diff --git a/changelog.md b/changelog.md
index a3332789a..8ac02a388 100644
--- a/changelog.md
+++ b/changelog.md
@@ -102,4 +102,10 @@
 - Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual
   machine.
 
+- The ``deadCodeElim`` option is now always turned on and the switch has no
+  effect anymore, but is recognized for backwards compatibility.
+
+- ``experimental`` is now a pragma / command line switch that can enable specific
+  language extensions, it is not an all-or-nothing switch anymore.
+
 ### Bugfixes
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4a0a9a20b..b8202abe6 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -262,7 +262,8 @@ type
                       # variable is a thread variable
     sfCompileTime,    # proc can be evaluated at compile time
     sfConstructor,    # proc is a C++ constructor
-    sfDeadCodeElim,   # dead code elimination for the module is turned on
+    sfDispatcher,     # copied method symbol is the dispatcher
+                      # deprecated and unused, except for the con
     sfBorrow,         # proc is borrowed
     sfInfixCall,      # symbol needs infix call syntax in target language;
                       # for interfacing with C++, JS
@@ -275,10 +276,9 @@ type
   TSymFlags* = set[TSymFlag]
 
 const
-  sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher
   sfNoInit* = sfMainModule       # don't generate code to init the variable
 
-  sfImmediate* = sfDeadCodeElim
+  sfImmediate* = sfDispatcher
     # macro or template is immediately expanded
     # without considering any possible overloads
   sfAllUntyped* = sfVolatile # macro or template is immediately expanded \
@@ -1622,7 +1622,7 @@ iterator items*(n: PNode): PNode =
   for i in 0..<n.safeLen: yield n.sons[i]
 
 iterator pairs*(n: PNode): tuple[i: int, n: PNode] =
-  for i in 0..<n.len: yield (i, n.sons[i])
+  for i in 0..<n.safeLen: yield (i, n.sons[i])
 
 proc isAtom*(n: PNode): bool {.inline.} =
   result = n.kind >= nkNone and n.kind <= nkNilLit
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 461a86298..ea373f5a6 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2264,7 +2264,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
   of nkEmpty: discard
   of nkWhileStmt: genWhileStmt(p, n)
   of nkVarSection, nkLetSection: genVarStmt(p, n)
-  of nkConstSection: genConstStmt(p, n)
+  of nkConstSection: discard  # consts generated lazily on use
   of nkForStmt: internalError(n.info, "for statement not eliminated")
   of nkCaseStmt: genCase(p, n, d)
   of nkReturnStmt: genReturnStmt(p, n)
@@ -2315,8 +2315,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       # are not transformed correctly. We work around this issue (#411) here
       # by ensuring it's no inner proc (owner is a module):
       if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
-        if (not emitLazily(prc)) or
-            ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
+        if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
             (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
             (prc.kind == skMethod):
           # we have not only the header:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 2030d6add..cb3d6dbe6 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -280,20 +280,6 @@ proc genVarStmt(p: BProc, n: PNode) =
     else:
       genVarTuple(p, it)
 
-proc genConstStmt(p: BProc, n: PNode) =
-  for it in n.sons:
-    if it.kind == nkCommentStmt: continue
-    if it.kind != nkConstDef: internalError(n.info, "genConstStmt")
-
-    let sym = it.sons[0].sym
-    if sym.typ.containsCompileTimeOnly or
-        sym.typ.kind notin ConstantDataTypes or
-        sym.ast.len == 0 or
-        emitLazily(sym):
-      continue
-
-    requestConstImpl(p, sym)
-
 proc genIf(p: BProc, n: PNode, d: var TLoc) =
   #
   #  { if (!expr1) goto L1;
@@ -587,7 +573,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
     genLineDir(p, t)
     if isImportedException(typ):
       lineF(p, cpsStmts, "throw $1;$n", [e])
-    else:      
+    else:
       lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n",
           [e, makeCString(typ.sym.name.s)])
   else:
@@ -836,7 +822,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
     else:
       for j in 0..t[i].len-2:
         if t[i][j].isInfixAs():
-          let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:` 
+          let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
           fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown)
           startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc))
         else:
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index fe28d2209..48648bdde 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -211,8 +211,4 @@ proc mangle*(name: string): string =
   if requiresUnderscore:
     result.add "_"
 
-proc emitLazily*(s: PSym): bool {.inline.} =
-  result = optDeadCodeElim in gGlobalOptions or
-           sfDeadCodeElim in getModule(s).flags
-
 initTypeTables()
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 9e1f9349f..ff3e6714d 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1309,10 +1309,6 @@ proc newModule(g: BModuleList; module: PSym): BModule =
   growCache g.modules, module.position
   g.modules[module.position] = result
 
-  if (optDeadCodeElim in gGlobalOptions):
-    if (sfDeadCodeElim in module.flags):
-      internalError("added pending module twice: " & toFilename(FileIndex module.position))
-
 template injectG(config) {.dirty.} =
   if graph.backend == nil:
     graph.backend = newModuleList(config)
diff --git a/compiler/commands.nim b/compiler/commands.nim
index e1dc1aacf..06b487cf0 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -46,9 +46,9 @@ type
     passCmd2,                 # second pass over the command line
     passPP                    # preprocessor called processCommand()
 
-proc processCommand*(switch: string, pass: TCmdLinePass)
+proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef)
 proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
-                    config: ConfigRef = nil)
+                    config: ConfigRef)
 
 # implementation
 
@@ -58,7 +58,13 @@ const
 
 const
   Usage = slurp"../doc/basicopt.txt".replace("//", "")
-  AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "")
+  FeatureDesc = block:
+    var x = ""
+    for f in low(Feature)..high(Feature):
+      if x.len > 0: x.add "|"
+      x.add $f
+    x
+  AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc
 
 proc getCommandLineDesc(): string =
   result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name,
@@ -268,7 +274,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "movechecks": result = contains(gOptions, optMoveCheck)
   of "linedir": result = contains(gOptions, optLineDir)
   of "assertions", "a": result = contains(gOptions, optAssert)
-  of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim)
   of "run", "r": result = contains(gGlobalOptions, optRun)
   of "symbolfiles": result = gSymbolFiles != disabledSf
   of "genscript": result = contains(gGlobalOptions, optGenScript)
@@ -277,7 +282,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation)
   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)
 
@@ -340,7 +344,7 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
     options.inclDynlibOverride(arg)
 
 proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
-                   config: ConfigRef = nil) =
+                   config: ConfigRef) =
   var
     theOS: TSystemOS
     cpu: TSystemCPU
@@ -509,7 +513,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info)
   of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
   of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
-  of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
+  of "deadcodeelim": discard # deprecated, dead code elim always on
   of "threads":
     processOnOffSwitchG({optThreads}, arg, pass, info)
     #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe)
@@ -648,6 +652,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "genscript", "gendeps":
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optGenScript)
+    incl(gGlobalOptions, optCompileOnly)
   of "colors": processOnOffSwitchG({optUseColors}, arg, pass, info)
   of "lib":
     expectArg(switch, arg, pass, info)
@@ -695,8 +700,13 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     # only supported for compatibility. Does nothing.
     expectArg(switch, arg, pass, info)
   of "experimental":
-    expectNoArg(switch, arg, pass, info)
-    gExperimentalMode = true
+    if arg.len == 0:
+      config.features.incl oldExperimentalFeatures
+    else:
+      try:
+        config.features.incl parseEnum[Feature](arg)
+      except ValueError:
+        localError(info, "unknown experimental feature")
   of "nocppexceptions":
     expectNoArg(switch, arg, pass, info)
     incl(gGlobalOptions, optNoCppExceptions)
@@ -707,7 +717,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
       config.cppDefine(arg)
   of "newruntime":
     expectNoArg(switch, arg, pass, info)
-    newDestructors = true
+    doAssert(config != nil)
+    incl(config.features, destructor)
     defineSymbol("nimNewRuntime")
   of "cppcompiletonamespace":
     expectNoArg(switch, arg, pass, info)
@@ -717,36 +728,31 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg)
     else: invalidCmdLineOption(pass, switch, info)
 
-proc processCommand(switch: string, pass: TCmdLinePass) =
+proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) =
   var cmd, arg: string
   splitSwitch(switch, cmd, arg, pass, gCmdLineInfo)
-  processSwitch(cmd, arg, pass, gCmdLineInfo)
+  processSwitch(cmd, arg, pass, gCmdLineInfo, config)
 
 
-var
-  arguments* = ""
-    # the arguments to be passed to the program that
-    # should be run
-
-proc processSwitch*(pass: TCmdLinePass; p: OptParser) =
+proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) =
   # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off")
   # we fix this here
   var bracketLe = strutils.find(p.key, '[')
   if bracketLe >= 0:
     var key = substr(p.key, 0, bracketLe - 1)
     var val = substr(p.key, bracketLe + 1) & ':' & p.val
-    processSwitch(key, val, pass, gCmdLineInfo)
+    processSwitch(key, val, pass, gCmdLineInfo, config)
   else:
-    processSwitch(p.key, p.val, pass, gCmdLineInfo)
+    processSwitch(p.key, p.val, pass, gCmdLineInfo, config)
 
 proc processArgument*(pass: TCmdLinePass; p: OptParser;
-                      argsCount: var int): bool =
+                      argsCount: var int; config: ConfigRef): bool =
   if argsCount == 0:
     # nim filename.nims  is the same as "nim e filename.nims":
     if p.key.endswith(".nims"):
       options.command = "e"
       options.gProjectName = unixToNativePath(p.key)
-      arguments = cmdLineRest(p)
+      config.arguments = cmdLineRest(p)
       result = true
     elif pass != passCmd2:
       options.command = p.key
@@ -755,6 +761,6 @@ proc processArgument*(pass: TCmdLinePass; p: OptParser;
     if argsCount == 1:
       # support UNIX style filenames everywhere for portable build scripts:
       options.gProjectName = unixToNativePath(p.key)
-      arguments = cmdLineRest(p)
+      config.arguments = cmdLineRest(p)
       result = true
   inc argsCount
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index f9b18a335..f8938e3af 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -470,8 +470,9 @@ proc execExternalProgram*(cmd: string, msg = hintExecuting) =
 
 proc generateScript(projectFile: string, script: Rope) =
   let (dir, name, ext) = splitFile(projectFile)
-  writeRope(script, dir / addFileExt("compile_" & name,
+  writeRope(script, getNimcacheDir() / addFileExt("compile_" & name,
                                      platform.OS[targetOS].scriptExt))
+  copyFile(libpath / "nimbase.h", getNimcacheDir() / "nimbase.h")
 
 proc getOptSpeed(c: TSystemCC): string =
   result = getConfigVar(c, ".options.speed")
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 8f3463be9..280782330 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -42,7 +42,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
     writeCommandLineUsage()
   else:
     # Process command line arguments:
-    processCmdLine(passCmd1, "")
+    processCmdLine(passCmd1, "", config)
     if gProjectName == "-":
       gProjectName = "stdinfile"
       gProjectFull = "stdinfile"
@@ -71,7 +71,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
     # now process command line arguments again, because some options in the
     # command line can overwite the config file's settings
     extccomp.initVars()
-    processCmdLine(passCmd2, "")
+    processCmdLine(passCmd2, "", config)
     if options.command == "":
       rawMessage(errNoCommand, command)
     mainCommand(newModuleGraph(config), cache)
@@ -80,7 +80,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
     if msgs.gErrorCounter == 0:
       when hasTinyCBackend:
         if gCmd == cmdRun:
-          tccgen.run(commands.arguments)
+          tccgen.run(config.arguments)
       if optRun in gGlobalOptions:
         if gCmd == cmdCompileToJS:
           var ex: string
@@ -89,7 +89,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
           else:
             ex = quoteShell(
               completeCFilePath(changeFileExt(gProjectFull, "js").prependCurDir))
-          execExternalProgram(findNodeJs() & " " & ex & ' ' & commands.arguments)
+          execExternalProgram(findNodeJs() & " " & ex & ' ' & config.arguments)
         else:
           var binPath: string
           if options.outFile.len > 0:
@@ -99,7 +99,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
             # Figure out ourselves a valid binary name.
             binPath = changeFileExt(gProjectFull, ExeExt).prependCurDir
           var ex = quoteShell(binPath)
-          execExternalProgram(ex & ' ' & commands.arguments)
+          execExternalProgram(ex & ' ' & config.arguments)
 
 when declared(GC_setMaxPause):
   GC_setMaxPause 2_000
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index c19b41af1..bdf558134 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -247,10 +247,6 @@ proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) =
       var projectConfig = changeFileExt(gProjectFull, "nimcfg")
       if not fileExists(projectConfig):
         projectConfig = changeFileExt(gProjectFull, "nim.cfg")
-      if not fileExists(projectConfig):
-        projectConfig = changeFileExt(gProjectFull, "nimrod.cfg")
-        if fileExists(projectConfig):
-          rawMessage(warnDeprecated, projectConfig)
       readConfigFile(projectConfig, cache, config)
 
 proc loadConfigs*(cfg: string; config: ConfigRef = nil) =
diff --git a/compiler/options.nim b/compiler/options.nim
index 93a3f1796..a5dfaa81c 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -41,7 +41,8 @@ type                          # please make sure we have under 32 options
 
   TOptions* = set[TOption]
   TGlobalOption* = enum       # **keep binary compatible**
-    gloptNone, optForceFullMake, optDeadCodeElim,
+    gloptNone, optForceFullMake,
+    optDeadCodeElimUnused,    # deprecated, always on
     optListCmd, optCompileOnly, optNoLinking,
     optCDebug,                # turn on debugging information
     optGenDynLib,             # generate a dynamic library
@@ -102,13 +103,25 @@ type
     ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod,
     ideHighlight, ideOutline, ideKnown, ideMsg
 
+  Feature* = enum  ## experimental features
+    implicitDeref,
+    dotOperators,
+    callOperator,
+    parallel,
+    destructor
+
   ConfigRef* = ref object ## eventually all global configuration should be moved here
     cppDefines*: HashSet[string]
     headerFile*: string
+    features*: set[Feature]
+    arguments*: string ## the arguments to be passed to the program that
+                       ## should be run
+
+const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel}
 
 proc newConfigRef*(): ConfigRef =
   result = ConfigRef(cppDefines: initSet[string](),
-    headerFile: "")
+    headerFile: "", features: {})
 
 proc cppDefine*(c: ConfigRef; define: string) =
   c.cppDefines.incl define
@@ -145,8 +158,6 @@ var
   gListFullPaths*: bool
   gPreciseStack*: bool = false
   gNoNimblePath* = false
-  gExperimentalMode*: bool
-  newDestructors*: bool
   gDynlibOverrideAll*: bool
   useNimNamespace*: bool
 
diff --git a/compiler/passes.nim b/compiler/passes.nim
index d7c181676..6ff3f2bb5 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -166,7 +166,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
     p: TParsers
     a: TPassContextArray
     s: PLLStream
-    fileIdx = FileIndex module.fileIdx
+    fileIdx = module.fileIdx
   if module.id < 0:
     # new module caching mechanism:
     for i in 0..<gPassesLen:
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index cb11564a4..5aa903771 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -44,7 +44,9 @@ const
     wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
     wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
-    wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
+    wBreakpoint, wWatchPoint, wPassl, wPassc,
+    wDeadCodeElimUnused,  # deprecated, always on
+    wDeprecated,
     wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
     wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto,
     wInjectStmt, wDeprecated, wExperimental, wThis}
@@ -215,10 +217,6 @@ proc onOff(c: PContext, n: PNode, op: TOptions) =
   if isTurnedOn(c, n): gOptions = gOptions + op
   else: gOptions = gOptions - op
 
-proc pragmaDeadCodeElim(c: PContext, n: PNode) =
-  if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
-  else: excl(c.module.flags, sfDeadCodeElim)
-
 proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) =
   if isTurnedOn(c, n): incl(c.module.flags, flag)
   else: excl(c.module.flags, flag)
@@ -682,6 +680,22 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
     elif n.kind == nkExprColonExpr:
       result.kind = n.kind # pragma(arg) -> pragma: arg
 
+proc processExperimental(c: PContext; n: PNode; s: PSym) =
+  if not isTopLevel(c):
+    localError(n.info, "'experimental' pragma only valid as toplevel statement")
+  if n.kind notin nkPragmaCallKinds or n.len != 2:
+    c.features.incl oldExperimentalFeatures
+  else:
+    n[1] = c.semConstExpr(c, n[1])
+    case n[1].kind
+    of nkStrLit, nkRStrLit, nkTripleStrLit:
+      try:
+        c.features.incl parseEnum[Feature](n[1].strVal)
+      except ValueError:
+        localError(n[1].info, "unknown experimental feature")
+    else:
+      localError(n.info, errStringLiteralExpected)
+
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
                   validPragmas: TSpecialWords): bool =
   var it = n.sons[i]
@@ -764,7 +778,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
       of wThreadVar:
         noVal(it)
         incl(sym.flags, sfThread)
-      of wDeadCodeElim: pragmaDeadCodeElim(c, it)
+      of wDeadCodeElimUnused: discard  # deprecated, dead code elim always on
       of wNoForward: pragmaNoForward(c, it)
       of wReorder: pragmaNoForward(c, it, sfReorder)
       of wMagic: processMagic(c, it, sym)
@@ -960,10 +974,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         if sym.kind != skType or sym.typ == nil: invalidPragma(it)
         else:
           incl(sym.typ.flags, tfPartial)
-          # .partial types can only work with dead code elimination
-          # to prevent the codegen from doing anything before we compiled
-          # the whole program:
-          incl gGlobalOptions, optDeadCodeElim
       of wInject, wGensym:
         # We check for errors, but do nothing with these pragmas otherwise
         # as they are handled directly in 'evalTemplate'.
@@ -999,11 +1009,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         else:
           it.sons[1] = c.semExpr(c, it.sons[1])
       of wExperimental:
-        noVal(it)
-        if isTopLevel(c):
-          c.module.flags.incl sfExperimental
-        else:
-          localError(it.info, "'experimental' pragma only valid as toplevel statement")
+        processExperimental(c, it, sym)
       of wThis:
         if it.kind in nkPragmaCallKinds and it.len == 2:
           c.selfName = considerQuotedIdent(it[1])
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 0e631a898..2a65a10a8 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -172,32 +172,6 @@ proc put(g: var TSrcGen, kind: TTokType, s: string) =
   else:
     g.pendingWhitespace = s.len
 
-proc addNimChar(dst: var string; c: char): void =
-  case c
-  of '\0': dst.add "\\x00" # not "\\0" to avoid ambiguous cases like "\\012".
-  of '\a': dst.add "\\a" # \x07
-  of '\b': dst.add "\\b" # \x08
-  of '\t': dst.add "\\t" # \x09
-  of '\L': dst.add "\\L" # \x0A
-  of '\v': dst.add "\\v" # \x0B
-  of '\f': dst.add "\\f" # \x0C
-  of '\c': dst.add "\\c" # \x0D
-  of '\e': dst.add "\\e" # \x1B
-  of '\x01'..'\x06', '\x0E'..'\x1A', '\x1C'..'\x1F', '\x80'..'\xFF':
-    dst.add "\\x"
-    dst.add strutils.toHex(ord(c), 2)
-  of '\'', '\"', '\\':
-    dst.add '\\'
-    dst.add c
-  else:
-    dst.add c
-
-proc makeNimString(s: string): string =
-  result = "\""
-  for c in s:
-    result.addNimChar c
-  add(result, '\"')
-
 proc putComment(g: var TSrcGen, s: string) =
   if s.isNil: return
   var i = 0
@@ -365,10 +339,13 @@ proc atom(g: TSrcGen; n: PNode): string =
   of nkEmpty: result = ""
   of nkIdent: result = n.ident.s
   of nkSym: result = n.sym.name.s
-  of nkStrLit: result = makeNimString(n.strVal)
+  of nkStrLit: result = ""; result.addQuoted(n.strVal)
   of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"")  & '\"'
   of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\""
-  of nkCharLit: result = "\'"; result.addNimChar chr(int(n.intVal)); result.add '\''
+  of nkCharLit:
+    result = "\'"
+    result.addEscapedChar(chr(int(n.intVal)));
+    result.add '\''
   of nkIntLit: result = litAux(g, n, n.intVal, 4)
   of nkInt8Lit: result = litAux(g, n, n.intVal, 1) & "\'i8"
   of nkInt16Lit: result = litAux(g, n, n.intVal, 2) & "\'i16"
diff --git a/compiler/reorder.nim b/compiler/reorder.nim
index 878e3b11e..56d8d5886 100644
--- a/compiler/reorder.nim
+++ b/compiler/reorder.nim
@@ -429,7 +429,7 @@ proc reorder*(graph: ModuleGraph, n: PNode, module: PSym, cache: IdentCache): PN
   if n.hasForbiddenPragma:
     return n
   var includedFiles = initIntSet()
-  let mpath = module.fileIdx.FileIndex.toFullPath
+  let mpath = module.fileIdx.toFullPath
   let n = expandIncludes(graph, module, n, mpath,
                           includedFiles, cache).splitSections
   result = newNodeI(nkStmtList, n.info)
diff --git a/compiler/rodread.nim b/compiler/rodread.nim
index aa699e337..f55c3279c 100644
--- a/compiler/rodread.nim
+++ b/compiler/rodread.nim
@@ -915,7 +915,7 @@ proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader =
     module.id = getID()
     return nil
   idgen.loadMaxIds(options.gProjectPath / options.gProjectName)
-  let fileIdx = FileIndex module.fileIdx
+  let fileIdx = module.fileIdx
   discard checkDep(fileIdx, cache)
   if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile")
   result = gMods[fileIdx.int32].rd
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index 692a8d896..c533f4cb4 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -26,7 +26,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
   setResult(a, result)
 
 proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
-              config: ConfigRef = nil): PEvalContext =
+              config: ConfigRef): PEvalContext =
   # For Nimble we need to export 'setupVM'.
   result = newCtx(module, cache)
   result.mode = emRepl
@@ -128,7 +128,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
   cbconf getCommand:
     setResult(a, options.command)
   cbconf switch:
-    processSwitch(a.getString 0, a.getString 1, passPP, module.info)
+    processSwitch(a.getString 0, a.getString 1, passPP, module.info, config)
   cbconf hintImpl:
     processSpecificNote(a.getString 0, wHint, passPP, module.info,
       a.getString 1)
@@ -150,7 +150,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
       options.cppDefine(config, a.getString(0))
 
 proc runNimScript*(cache: IdentCache; scriptName: string;
-                   freshDefines=true; config: ConfigRef=nil) =
+                   freshDefines=true; config: ConfigRef) =
   rawMessage(hintConf, scriptName)
   passes.gIncludeFile = includeModule
   passes.gImportModule = importModule
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index bbd2baf6e..5c7b91f6d 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -101,7 +101,7 @@ proc newOpCall(op: PSym; x: PNode): PNode =
 proc destructorCall(c: PContext; op: PSym; x: PNode): PNode =
   result = newNodeIT(nkCall, x.info, op.typ.sons[0])
   result.add(newSymNode(op))
-  if newDestructors:
+  if destructor in c.features:
     result.add genAddr(c, x)
   else:
     result.add x
@@ -319,7 +319,7 @@ proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
   ## In the semantic pass this is called in strategic places
   ## to ensure we lift assignment, destructors and moves properly.
   ## The later 'destroyer' pass depends on it.
-  if not newDestructors or not hasDestructor(typ): return
+  if destructor notin c.features or not hasDestructor(typ): return
   when false:
     # do not produce wrong liftings while we're still instantiating generics:
     # now disabled; breaks topttree.nim!
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 0fc12f164..f443339f5 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -434,7 +434,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
               "Non-matching candidates for " & renderTree(n) & "\n" &
               candidates)
     result = semResolvedCall(c, n, r)
-  elif experimentalMode(c) and canDeref(n):
+  elif implicitDeref in c.features and canDeref(n):
     # try to deref the first argument and then try overloading resolution again:
     #
     # XXX: why is this here?
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index bcc1bba15..8159abf8f 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -130,6 +130,7 @@ type
     signatures*: TStrTable
     recursiveDep*: string
     suggestionsMade*: bool
+    features*: set[Feature]
     inTypeContext*: int
     typesWithOps*: seq[(PType, PType)] #\
       # We need to instantiate the type bound ops lazily after
@@ -225,7 +226,7 @@ proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext
   result.graph = graph
   initStrTable(result.signatures)
   result.typesWithOps = @[]
-
+  result.features = graph.config.features
 
 proc inclSym(sq: var TSymSeq, s: PSym) =
   var L = len(sq)
@@ -398,6 +399,3 @@ proc checkMinSonsLen*(n: PNode, length: int) =
 
 proc isTopLevel*(c: PContext): bool {.inline.} =
   result = c.currentScope.depthLevel <= 2
-
-proc experimentalMode*(c: PContext): bool {.inline.} =
-  result = gExperimentalMode or sfExperimental in c.module.flags
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 279b6cc57..6ad5d931d 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -663,7 +663,7 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
   matches(c, n, nOrig, result)
   if result.state != csMatch:
     # try to deref the first argument:
-    if experimentalMode(c) and canDeref(n):
+    if implicitDeref in c.features and canDeref(n):
       n.sons[1] = n.sons[1].tryDeref
       initCandidate(c, result, t)
       matches(c, n, nOrig, result)
@@ -1452,7 +1452,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
           typeMismatch(n.info, lhs.typ, rhsTyp)
 
     n.sons[1] = fitNode(c, le, rhs, n.info)
-    if not newDestructors:
+    if destructor notin c.features:
       if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
           mode != noOverloadedAsgn:
         return overloadedAsgn(c, lhs, n.sons[1])
@@ -1884,7 +1884,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
     result.typ = getSysType(tyString)
   of mParallel:
-    if not experimentalMode(c):
+    if parallel notin c.features:
       localError(n.info, "use the {.experimental.} pragma to enable 'parallel'")
     result = setMs(n, s)
     var x = n.lastSon
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 8d7747fb4..94090852f 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -385,30 +385,9 @@ proc checkNilable(v: PSym) =
 include semasgn
 
 proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
-  # consider this:
-  #   var
-  #     x = 0
-  #     withOverloadedAssignment = foo()
-  #     y = use(withOverloadedAssignment)
-  # We need to split this into a statement list with multiple 'var' sections
-  # in order for this transformation to be correct.
   let L = identDefs.len
   let value = identDefs[L-1]
-  if value.typ != nil and tfHasAsgn in value.typ.flags and not newDestructors:
-    # the spec says we need to rewrite 'var x = T()' to 'var x: T; x = T()':
-    identDefs.sons[L-1] = emptyNode
-    if result.kind != nkStmtList:
-      let oldResult = result
-      oldResult.add identDefs
-      result = newNodeI(nkStmtList, result.info)
-      result.add oldResult
-    else:
-      let o = copyNode(orig)
-      o.add identDefs
-      result.add o
-    for i in 0 .. L-3:
-      result.add overloadedAsgn(c, identDefs[i], value)
-  elif result.kind == nkStmtList:
+  if result.kind == nkStmtList:
     let o = copyNode(orig)
     o.add identDefs
     result.add o
@@ -1267,9 +1246,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
     gp = newNodeI(nkGenericParams, n.info)
 
   if n.sons[paramsPos].kind != nkEmpty:
-    #if n.kind == nkDo and not experimentalMode(c):
-    #  localError(n.sons[paramsPos].info,
-    #      "use the {.experimental.} pragma to enable 'do' with parameters")
     semParamList(c, n.sons[paramsPos], gp, s)
     # paramsTypeCheck(c, s.typ)
     if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty:
@@ -1363,27 +1339,26 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
 
 proc semOverride(c: PContext, s: PSym, n: PNode) =
   case s.name.s.normalize
-  of "destroy", "=destroy":
-    if newDestructors:
-      let t = s.typ
-      var noError = false
-      if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
-        var obj = t.sons[1].sons[0]
-        while true:
-          incl(obj.flags, tfHasAsgn)
-          if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon
-          elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
-          else: break
-        if obj.kind in {tyObject, tyDistinct}:
-          if obj.destructor.isNil:
-            obj.destructor = s
-          else:
-            localError(n.info, errGenerated,
-              "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
-          noError = true
-      if not noError and sfSystemModule notin s.owner.flags:
-        localError(n.info, errGenerated,
-          "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
+  of "=destroy":
+    let t = s.typ
+    var noError = false
+    if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar:
+      var obj = t.sons[1].sons[0]
+      while true:
+        incl(obj.flags, tfHasAsgn)
+        if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon
+        elif obj.kind == tyGenericInvocation: obj = obj.sons[0]
+        else: break
+      if obj.kind in {tyObject, tyDistinct}:
+        if obj.destructor.isNil:
+          obj.destructor = s
+        else:
+          localError(n.info, errGenerated,
+            "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
+        noError = true
+    if not noError and sfSystemModule notin s.owner.flags:
+      localError(n.info, errGenerated,
+        "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
     incl(s.flags, sfUsed)
   of "deepcopy", "=deepcopy":
     if s.typ.len == 2 and
@@ -1612,9 +1587,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   s.options = gOptions
   if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
   if s.name.s[0] in {'.', '('}:
-    if s.name.s in [".", ".()", ".="] and not experimentalMode(c) and not newDestructors:
+    if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
       message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s)
-    elif s.name.s == "()" and not experimentalMode(c):
+    elif s.name.s == "()" and callOperator notin c.features:
       message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s)
 
   if n.sons[bodyPos].kind != nkEmpty:
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 09434c925..c97c1186e 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -368,7 +368,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
         assert newbody.kind in {tyRef, tyPtr}
         assert newbody.lastSon.typeInst == nil
         newbody.lastSon.typeInst = result
-    if newDestructors:
+    if destructor in cl.c.features:
       cl.c.typesWithOps.add((newbody, result))
     else:
       typeBound(cl.c, newbody, result, assignment, cl.info)
@@ -545,7 +545,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
       else: discard
 
 proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
-  if not newDestructors: return
+  if destructor notin c.features: return
   var i = 0
   while i < c.typesWithOps.len:
     let (newty, oldty) = c.typesWithOps[i]
diff --git a/compiler/service.nim b/compiler/service.nim
index ac04b7860..6ec9b9046 100644
--- a/compiler/service.nim
+++ b/compiler/service.nim
@@ -26,7 +26,7 @@ var
     # in caas mode, the list of defines and options will be given at start-up?
     # it's enough to check that the previous compilation command is the same?
 
-proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
+proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
   var p = parseopt.initOptParser(cmd)
   var argsCount = 0
   while true:
@@ -36,19 +36,19 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
     of cmdLongoption, cmdShortOption:
       if p.key == " ":
         p.key = "-"
-        if processArgument(pass, p, argsCount): break
+        if processArgument(pass, p, argsCount, config): break
       else:
-        processSwitch(pass, p)
+        processSwitch(pass, p, config)
     of cmdArgument:
-      if processArgument(pass, p, argsCount): break
+      if processArgument(pass, p, argsCount, config): break
   if pass == passCmd2:
-    if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run":
+    if optRun notin gGlobalOptions and config.arguments.len > 0 and options.command.normalize != "run":
       rawMessage(errArgsNeedRunOption, [])
 
-proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}) =
+proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) =
   template execute(cmd) =
     curCaasCmd = cmd
-    processCmdLine(passCmd2, cmd)
+    processCmdLine(passCmd2, cmd, config)
     action(cache)
     gErrorCounter = 0
 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index f30f8583a..f7ec6c97f 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -979,7 +979,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
     #result = liftLambdas(prc, result)
     when useEffectSystem: trackProc(prc, result)
     result = liftLocalsIfRequested(prc, result)
-    if c.needsDestroyPass and newDestructors:
+    if c.needsDestroyPass: #and newDestructors:
       result = injectDestructorCalls(prc, result)
     incl(result.flags, nfTransf)
       #if prc.name.s == "testbody":
@@ -996,7 +996,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
     when useEffectSystem: trackTopLevelStmt(module, result)
     #if n.info ?? "temp.nim":
     #  echo renderTree(result, {renderIds})
-    if c.needsDestroyPass and newDestructors:
+    if c.needsDestroyPass:
       result = injectDestructorCalls(module, result)
     incl(result.flags, nfTransf)
 
@@ -1007,6 +1007,6 @@ proc transformExpr*(module: PSym, n: PNode): PNode =
     var c = openTransf(module, "")
     result = processTransf(c, n, module)
     liftDefer(c, result)
-    if c.needsDestroyPass and newDestructors:
+    if c.needsDestroyPass:
       result = injectDestructorCalls(module, result)
     incl(result.flags, nfTransf)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 76d91d4e7..91b527e02 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -55,7 +55,8 @@ type
     wFloatchecks, wNanChecks, wInfChecks, wMoveChecks,
     wAssertions, wPatterns, wWarnings,
     wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
-    wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite,
+    wDeadCodeElimUnused,  # deprecated, dead code elim always happens
+    wSafecode, wPackage, wNoForward, wReorder, wNoRewrite,
     wPragma,
     wCompileTime, wNoInit,
     wPassc, wPassl, wBorrow, wDiscardable,
@@ -143,7 +144,8 @@ const
 
     "assertions", "patterns", "warnings", "hints",
     "optimization", "raises", "writes", "reads", "size", "effects", "tags",
-    "deadcodeelim", "safecode", "package", "noforward", "reorder", "norewrite",
+    "deadcodeelim",  # deprecated, dead code elim always happens
+    "safecode", "package", "noforward", "reorder", "norewrite",
     "pragma",
     "compiletime", "noinit",
     "passc", "passl", "borrow", "discardable", "fieldchecks",
diff --git a/doc/advopt.txt b/doc/advopt.txt
index bf7dd7fb4..d4a4b4961 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -35,7 +35,8 @@ Advanced options:
   --noLinking               compile Nim and generated files but do not link
   --noMain                  do not generate a main procedure
   --genScript               generate a compile script (in the 'nimcache'
-                            subdirectory named 'compile_$project$scriptext')
+                            subdirectory named 'compile_$$project$$scriptext'),
+                            implies --compileOnly
   --genDeps                 generate a '.deps' file containing the dependencies
   --os:SYMBOL               set the target operating system (cross-compilation)
   --cpu:SYMBOL              set the target processor (cross-compilation)
@@ -88,5 +89,6 @@ Advanced options:
   --parallelBuild:0|1|...   perform a parallel build
                             value = number of processors (0 for auto-detect)
   --verbosity:0|1|2|3       set Nim's verbosity level (1 is default)
-  --experimental            enable experimental language features
+  --experimental:$1
+                            enable experimental language feature
   -v, --version             show detailed version information
diff --git a/doc/basicopt.txt b/doc/basicopt.txt
index 4c11cc767..90c7ba09c 100644
--- a/doc/basicopt.txt
+++ b/doc/basicopt.txt
@@ -29,7 +29,6 @@ Options:
   --nanChecks:on|off        turn NaN checks on|off
   --infChecks:on|off        turn Inf checks on|off
   --nilChecks:on|off        turn nil checks on|off
-  --deadCodeElim:on|off     whole program dead code elimination on|off
   --opt:none|speed|size     optimize not at all or for speed|size
                             Note: use -d:release for a release build!
   --debugger:native|endb    use native debugger (gdb) | ENDB (experimental)
diff --git a/doc/manual.rst b/doc/manual.rst
index fbd043020..636bf796b 100644
--- a/doc/manual.rst
+++ b/doc/manual.rst
@@ -1397,10 +1397,10 @@ dereferencing operations for reference types:
 
 Automatic dereferencing is also performed for the first argument of a routine
 call. But currently this feature has to be only enabled
-via ``{.experimental.}``:
+via ``{.experimental: "implicitDeref".}``:
 
 .. code-block:: nim
-  {.experimental.}
+  {.experimental: "implicitDeref".}
 
   proc depth(x: NodeObj): int = ...
 
@@ -5588,7 +5588,7 @@ dot operators
 -------------
 
 **Note**: Dot operators are still experimental and so need to be enabled
-via ``{.experimental.}``.
+via ``{.experimental: "dotOperators".}``.
 
 Nim offers a special family of dot operators that can be used to
 intercept and rewrite proc call and field access attempts, referring
@@ -6768,22 +6768,6 @@ the created global variables within a module is not defined, but all of them
 will be initialized after any top-level variables in their originating module
 and before any variable in a module that imports it.
 
-deadCodeElim pragma
--------------------
-The ``deadCodeElim`` pragma only applies to whole modules: It tells the
-compiler to activate (or deactivate) dead code elimination for the module the
-pragma appears in.
-
-The ``--deadCodeElim:on`` command line switch has the same effect as marking
-every module with ``{.deadCodeElim:on}``. However, for some modules such as
-the GTK wrapper it makes sense to *always* turn on dead code elimination -
-no matter if it is globally active or not.
-
-Example:
-
-.. code-block:: nim
-  {.deadCodeElim: on.}
-
 
 ..
   NoForward pragma
@@ -6901,17 +6885,12 @@ is uncertain (it may be removed any time).
 Example:
 
 .. code-block:: nim
-  {.experimental.}
-  type
-    FooId = distinct int
-    BarId = distinct int
-  using
-    foo: FooId
-    bar: BarId
+  {.experimental: "parallel".}
 
   proc useUsing(bar, foo) =
-    echo "bar is of type BarId"
-    echo "foo is of type FooId"
+    parallel:
+      for i in 0..4:
+        echo "echo in parallel"
 
 
 Implementation Specific Pragmas
@@ -7933,7 +7912,7 @@ Example:
 
   # Compute PI in an inefficient way
   import strutils, math, threadpool
-  {.experimental.}
+  {.experimental: "parallel".}
 
   proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1)
 
diff --git a/doc/nimc.rst b/doc/nimc.rst
index b275438ea..29dbdea42 100644
--- a/doc/nimc.rst
+++ b/doc/nimc.rst
@@ -181,7 +181,7 @@ generated; use the ``--symbolFiles:on`` command line switch to activate them.
 
 Unfortunately due to technical reasons the ``--symbolFiles:on`` needs
 to *aggregate* some generated C code. This means that the resulting executable
-might contain some cruft even when dead code elimination is turned on. So
+might contain some cruft even with dead code elimination. So
 the final release build should be done with ``--symbolFiles:off``.
 
 Due to the aggregation of C code it is also recommended that each project
@@ -439,7 +439,7 @@ target.
 
 For example, to generate code for an `AVR`:idx: processor use this command::
 
-  nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim
+  nim c --cpu:avr --os:standalone --genScript x.nim
 
 For the ``standalone`` target one needs to provide
 a file ``panicoverride.nim``.
diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim
index f0568366a..05aebef76 100644
--- a/lib/deprecated/pure/sockets.nim
+++ b/lib/deprecated/pure/sockets.nim
@@ -32,7 +32,7 @@
 
 include "system/inclrtl"
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when hostOS == "solaris":
   {.passl: "-lsocket -lnsl".}
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index 21049571f..f88037e2f 100644
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -81,7 +81,7 @@
 ##
 ##  theDb.close()
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 import strutils, sqlite3
 
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index 5aa4cfcc3..54bab82f0 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -13,7 +13,7 @@
 ## is used. This suffices because Windows' console already provides the
 ## wanted functionality.
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when defined(Windows):
   proc readLineFromStdin*(prompt: string): TaintedString {.
diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim
index c5ed1a873..2d38137bb 100644
--- a/lib/posix/epoll.nim
+++ b/lib/posix/epoll.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 from posix import SocketHandle
 
diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim
index a206f8067..359e88617 100644
--- a/lib/posix/inotify.nim
+++ b/lib/posix/inotify.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 # Get the platform-dependent flags.
 # Structure describing an inotify event.
diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim
index 730491a53..18b47f5d5 100644
--- a/lib/posix/kqueue.nim
+++ b/lib/posix/kqueue.nim
@@ -7,8 +7,6 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim:on.}
-
 from posix import Timespec
 
 when defined(macosx) or defined(freebsd) or defined(openbsd) or
@@ -61,7 +59,7 @@ const
   EV_CLEAR*    = 0x0020 ## Clear event state after reporting.
   EV_RECEIPT*  = 0x0040 ## Force EV_ERROR on success, data == 0
   EV_DISPATCH* = 0x0080 ## Disable event after reporting.
-  
+
   EV_SYSFLAGS* = 0xF000 ## Reserved by system
   EV_DROP*     = 0x1000 ## Not should be dropped
   EV_FLAG1*    = 0x2000 ## Filter-specific flag
@@ -87,10 +85,10 @@ when defined(macosx) or defined(freebsd) or defined(dragonfly):
     NOTE_FFAND*      = 0x40000000'u32 ## AND fflags
     NOTE_FFOR*       = 0x80000000'u32 ## OR fflags
     NOTE_FFCOPY*     = 0xc0000000'u32 ## copy fflags
-    NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations 
+    NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations
     NOTE_FFLAGSMASK* = 0x00ffffff'u32
 
-    NOTE_TRIGGER*    = 0x01000000'u32 ## Cause the event to be triggered 
+    NOTE_TRIGGER*    = 0x01000000'u32 ## Cause the event to be triggered
                                       ## for output.
 
 # data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim
index 6f9f75e34..25c7c7979 100644
--- a/lib/posix/linux.nim
+++ b/lib/posix/linux.nim
@@ -1,4 +1,4 @@
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 import posix
 
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index a23d76050..3ff156bdf 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -27,10 +27,10 @@
 ## resulting C code will just ``#include <XYZ.h>`` and *not* define the
 ## symbols declared here.
 
-# This ensures that we don't accidentally generate #includes for files that
-# might not exist on a specific platform! The user will get an error only
-# if they actualy try to use the missing declaration
-{.deadCodeElim: on.}
+# Dead code elimination ensures that we don't accidentally generate #includes
+# for files that might not exist on a specific platform! The user will get an
+# error only if they actualy try to use the missing declaration
+{.deadCodeElim: on.}  # dce option deprecated
 
 # TODO these constants don't seem to be fetched from a header file for unknown
 #      platforms - where do they come from and why are they here?
diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim
index ae41263e8..004a4205b 100644
--- a/lib/posix/posix_other.nim
+++ b/lib/posix/posix_other.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 const
   hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays
diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim
index f86e408fb..60d540107 100644
--- a/lib/posix/termios.nim
+++ b/lib/posix/termios.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 import posix
 
 type
diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim
index f8f115ecc..c946c4261 100644
--- a/lib/pure/fenv.nim
+++ b/lib/pure/fenv.nim
@@ -10,7 +10,7 @@
 ## Floating-point environment. Handling of floating-point rounding and
 ## exceptions (overflow, division by zero, etc.).
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when defined(Posix) and not defined(haiku):
   {.passl: "-lm".}
@@ -102,32 +102,33 @@ proc feupdateenv*(envp: ptr Tfenv): cint {.importc, header: "<fenv.h>".}
   ## represented by object pointed to by `envp` and raise exceptions
   ## according to saved exceptions.
 
-var FP_RADIX_INTERNAL {. importc: "FLT_RADIX" header: "<float.h>" .} : int
-
-template fpRadix* : int = FP_RADIX_INTERNAL
+const 
+  FLT_RADIX = 2 ## the radix of the exponent representation
+
+  FLT_MANT_DIG = 24 ## the number of base FLT_RADIX digits in the mantissa part of a float
+  FLT_DIG = 6 ## the number of digits of precision of a float
+  FLT_MIN_EXP = -125 # the minimum value of base FLT_RADIX in the exponent part of a float
+  FLT_MAX_EXP = 128 # the maximum value of base FLT_RADIX in the exponent part of a float
+  FLT_MIN_10_EXP = -37 ## the minimum value in base 10 of the exponent part of a float
+  FLT_MAX_10_EXP = 38 ## the maximum value in base 10 of the exponent part of a float
+  FLT_MIN = 1.17549435e-38'f32  ## the minimum value of a float
+  FLT_MAX = 3.40282347e+38'f32 ## the maximum value of a float
+  FLT_EPSILON = 1.19209290e-07'f32  ## the difference between 1 and the least value greater than 1 of a float
+ 
+  DBL_MANT_DIG = 53 ## the number of base FLT_RADIX digits in the mantissa part of a double
+  DBL_DIG = 15 ## the number of digits of precision of a double
+  DBL_MIN_EXP = -1021 ## the minimum value of base FLT_RADIX in the exponent part of a double
+  DBL_MAX_EXP = 1024 ## the maximum value of base FLT_RADIX in the exponent part of a double
+  DBL_MIN_10_EXP = -307 ## the minimum value in base 10 of the exponent part of a double
+  DBL_MAX_10_EXP = 308 ## the maximum value in base 10 of the exponent part of a double
+  DBL_MIN = 2.2250738585072014E-308 ## the minimal value of a double
+  DBL_MAX = 1.7976931348623157E+308 ## the minimal value of a double
+  DBL_EPSILON = 2.2204460492503131E-16 ## the difference between 1 and the least value greater than 1 of a double
+
+template fpRadix* : int = FLT_RADIX
   ## The (integer) value of the radix used to represent any floating
   ## point type on the architecture used to build the program.
 
-var FLT_MANT_DIG {. importc: "FLT_MANT_DIG" header: "<float.h>" .} : int
-var FLT_DIG {. importc: "FLT_DIG" header: "<float.h>" .} : int
-var FLT_MIN_EXP {. importc: "FLT_MIN_EXP" header: "<float.h>" .} : int
-var FLT_MAX_EXP {. importc: "FLT_MAX_EXP" header: "<float.h>" .} : int
-var FLT_MIN_10_EXP {. importc: "FLT_MIN_10_EXP" header: "<float.h>" .} : int
-var FLT_MAX_10_EXP {. importc: "FLT_MAX_10_EXP" header: "<float.h>" .} : int
-var FLT_MIN {. importc: "FLT_MIN" header: "<float.h>" .} : cfloat
-var FLT_MAX {. importc: "FLT_MAX" header: "<float.h>" .} : cfloat
-var FLT_EPSILON {. importc: "FLT_EPSILON" header: "<float.h>" .} : cfloat
-
-var DBL_MANT_DIG {. importc: "DBL_MANT_DIG" header: "<float.h>" .} : int
-var DBL_DIG {. importc: "DBL_DIG" header: "<float.h>" .} : int
-var DBL_MIN_EXP {. importc: "DBL_MIN_EXP" header: "<float.h>" .} : int
-var DBL_MAX_EXP {. importc: "DBL_MAX_EXP" header: "<float.h>" .} : int
-var DBL_MIN_10_EXP {. importc: "DBL_MIN_10_EXP" header: "<float.h>" .} : int
-var DBL_MAX_10_EXP {. importc: "DBL_MAX_10_EXP" header: "<float.h>" .} : int
-var DBL_MIN {. importc: "DBL_MIN" header: "<float.h>" .} : cdouble
-var DBL_MAX {. importc: "DBL_MAX" header: "<float.h>" .} : cdouble
-var DBL_EPSILON {. importc: "DBL_EPSILON" header: "<float.h>" .} : cdouble
-
 template mantissaDigits*(T : typedesc[float32]) : int = FLT_MANT_DIG
   ## Number of digits (in base ``floatingPointRadix``) in the mantissa
   ## of 32-bit floating-point numbers.
@@ -179,3 +180,11 @@ template maximumPositiveValue*(T : typedesc[float64]) : float64 = DBL_MAX
 template epsilon*(T : typedesc[float64]): float64 = DBL_EPSILON
   ## The difference between 1.0 and the smallest number greater than
   ## 1.0 that can be represented in a 64-bit floating-point type.
+
+
+when isMainModule:
+  func is_significant(x: float): bool = 
+    if x > minimumPositiveValue(float) and x < maximumPositiveValue(float): true
+    else: false
+
+  doAssert is_significant(10.0)
diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim
index 6366fee1a..685c3b07a 100644
--- a/lib/pure/matchers.nim
+++ b/lib/pure/matchers.nim
@@ -12,7 +12,7 @@
 ## **Warning:** This module is deprecated since version 0.14.0.
 {.deprecated.}
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index ccf02a1fc..ebb59ca6d 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -68,7 +68,7 @@
 ## ``newSocket()``. The difference is that the latter creates a new file
 ## descriptor.
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 import nativesockets, os, strutils, parseutils, times, sets, options
 export Port, `$`, `==`
 export Domain, SockType, Protocol
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index ddeee2c6b..11be8f0c1 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -10,7 +10,7 @@
 ## This module contains basic operating system facilities like
 ## retrieving environment variables, reading command line arguments,
 ## working with directories, running shell commands, etc.
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 {.push debugger: off.}
 
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 57387e62e..cecc94e92 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -11,7 +11,7 @@
 ##
 ## To unpack raw bytes look at the `streams <streams.html>`_ module.
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
diff --git a/lib/pure/random.nim b/lib/pure/random.nim
index 968a326d2..01ea9c845 100644
--- a/lib/pure/random.nim
+++ b/lib/pure/random.nim
@@ -192,7 +192,7 @@ when not defined(nimscript):
     ## Initializes the random number generator with a "random"
     ## number, i.e. a tickcount. Note: Does not work for NimScript.
     let now = times.getTime()
-    randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanoseconds)
+    randomize(convert(Seconds, Nanoseconds, now.toUnix) + now.nanosecond)
 
 {.pop.}
 
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index 6ddd61afa..24ba012e5 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -19,7 +19,7 @@
 include "system/inclrtl"
 import streams
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim
index 89ef2fcd2..d1ff920c9 100644
--- a/lib/pure/strmisc.nim
+++ b/lib/pure/strmisc.nim
@@ -12,7 +12,7 @@
 
 import strutils
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect,
   procvar.} =
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 54fdcb4d0..cdc5ec4f9 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -17,7 +17,7 @@ import parseutils
 from math import pow, round, floor, log10
 from algorithm import reverse
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 {.push debugger:off .} # the user does not want to trace a part
                        # of the standard library!
@@ -1818,20 +1818,29 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
     dec(L)
 
 proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
-  rtl, extern: "nsuEscape".} =
+  rtl, extern: "nsuEscape", deprecated.} =
   ## Escapes a string `s`. See `system.addEscapedChar <system.html#addEscapedChar>`_
   ## for the escaping scheme.
   ##
   ## The resulting string is prefixed with `prefix` and suffixed with `suffix`.
   ## Both may be empty strings.
+  ##
+  ## **Warning:** This procedure is deprecated because it's to easy to missuse.
   result = newStringOfCap(s.len + s.len shr 2)
   result.add(prefix)
   for c in items(s):
-    result.addEscapedChar(c)
+    case c
+    of '\0'..'\31', '\127'..'\255':
+      add(result, "\\x")
+      add(result, toHex(ord(c), 2))
+    of '\\': add(result, "\\\\")
+    of '\'': add(result, "\\'")
+    of '\"': add(result, "\\\"")
+    else: add(result, c)
   add(result, suffix)
 
 proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
-  rtl, extern: "nsuUnescape".} =
+  rtl, extern: "nsuUnescape", deprecated.} =
   ## Unescapes a string `s`.
   ##
   ## This complements `escape <#escape>`_ as it performs the opposite
@@ -1839,6 +1848,8 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
   ##
   ## If `s` does not begin with ``prefix`` and end with ``suffix`` a
   ## ValueError exception will be raised.
+  ##
+  ## **Warning:** This procedure is deprecated because it's to easy to missuse.  
   result = newStringOfCap(s.len)
   var i = prefix.len
   if not s.startsWith(prefix):
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index bf63ed344..7d101beab 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -103,7 +103,7 @@ type
 
   Time* = object ## Represents a point in time.
     seconds: int64
-    nanoseconds: NanosecondRange
+    nanosecond: NanosecondRange
 
   DateTime* = object of RootObj ## Represents a time in different parts.
                                 ## Although this type can represent leap
@@ -159,7 +159,7 @@ type
                      ## This type should be prefered over ``TimeInterval`` unless
                      ## non-static time units is needed.
     seconds: int64
-    nanoseconds: NanosecondRange
+    nanosecond: NanosecondRange
 
   TimeUnit* = enum ## Different units of time.
     Nanoseconds, Microseconds, Milliseconds, Seconds, Minutes, Hours, Days, Weeks, Months, Years
@@ -223,21 +223,21 @@ proc normalize[T: Duration|Time](seconds, nanoseconds: int64): T =
   ## a ``Duration`` or ``Time``. A normalized ``Duration|Time`` has a
   ## positive nanosecond part in the range ``NanosecondRange``.
   result.seconds = seconds + convert(Nanoseconds, Seconds, nanoseconds)
-  var nanoseconds = nanoseconds mod convert(Seconds, Nanoseconds, 1)
-  if nanoseconds < 0:
-    nanoseconds += convert(Seconds, Nanoseconds, 1)
+  var nanosecond = nanoseconds mod convert(Seconds, Nanoseconds, 1)
+  if nanosecond < 0:
+    nanosecond += convert(Seconds, Nanoseconds, 1)
     result.seconds -= 1
-  result.nanoseconds = nanoseconds.int
+  result.nanosecond = nanosecond.int
 
-proc initTime*(unix: int64, nanoseconds: NanosecondRange): Time =
+proc initTime*(unix: int64, nanosecond: NanosecondRange): Time =
   ## Create a ``Time`` from a unix timestamp and a nanosecond part.
   result.seconds = unix
-  result.nanoseconds = nanoseconds
+  result.nanosecond = nanosecond
 
-proc nanoseconds*(time: Time): NanosecondRange =
+proc nanosecond*(time: Time): NanosecondRange =
   ## Get the fractional part of a ``Time`` as the number
   ## of nanoseconds of the second.
-  time.nanoseconds
+  time.nanosecond
 
 proc initDuration*(nanoseconds, microseconds, milliseconds,
                    seconds, minutes, hours, days, weeks: int64 = 0): Duration =
@@ -281,7 +281,7 @@ proc milliseconds*(dur: Duration): int {.inline.} =
   runnableExamples:
     let dur = initDuration(seconds = 1, milliseconds = 1)
     doAssert dur.milliseconds == 1
-  convert(Nanoseconds, Milliseconds, dur.nanoseconds)
+  convert(Nanoseconds, Milliseconds, dur.nanosecond)
 
 proc microseconds*(dur: Duration): int {.inline.} =
   ## Number of whole microseconds represented by the **fractional**
@@ -289,7 +289,7 @@ proc microseconds*(dur: Duration): int {.inline.} =
   runnableExamples:
     let dur = initDuration(seconds = 1, microseconds = 1)
     doAssert dur.microseconds == 1
-  convert(Nanoseconds, Microseconds, dur.nanoseconds)
+  convert(Nanoseconds, Microseconds, dur.nanosecond)
 
 proc nanoseconds*(dur: Duration): int {.inline.} =
   ## Number of whole nanoseconds represented by the **fractional**
@@ -297,14 +297,14 @@ proc nanoseconds*(dur: Duration): int {.inline.} =
   runnableExamples:
     let dur = initDuration(seconds = 1, nanoseconds = 1)
     doAssert dur.nanoseconds == 1
-  dur.nanoseconds
+  dur.nanosecond
 
 proc fractional*(dur: Duration): Duration {.inline.} =
   ## The fractional part of duration, as a duration.
   runnableExamples:
     let dur = initDuration(seconds = 1, nanoseconds = 5)
     doAssert dur.fractional == initDuration(nanoseconds = 5)
-  initDuration(nanoseconds = dur.nanoseconds)
+  initDuration(nanoseconds = dur.nanosecond)
 
 const DurationZero* = initDuration() ## Zero value for durations. Useful for comparisons.
                                      ##
@@ -322,7 +322,7 @@ proc `$`*(dur: Duration): string =
     doAssert $initDuration(milliseconds = -1500) == "-1 second and -500 milliseconds"
   var parts = newSeq[string]()
   var remS = dur.seconds
-  var remNs = dur.nanoseconds.int
+  var remNs = dur.nanosecond.int
 
   # Normally ``nanoseconds`` should always be positive, but
   # that makes no sense when printing.
@@ -387,7 +387,7 @@ proc fromWinTime*(win: int64): Time =
 
 proc toWinTime*(t: Time): int64 =
   ## Convert ``t`` to a Windows file time (100-nanosecond intervals since ``1601-01-01T00:00:00Z``).
-  result = t.seconds * rateDiff + epochDiff + t.nanoseconds div 100
+  result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100
 
 proc isLeapYear*(year: int): bool =
   ## Returns true if ``year`` is a leap year.
@@ -473,21 +473,21 @@ proc localZoneInfoFromTz(adjTime: Time): ZonedTime {.tags: [], raises: [], benig
 {. pragma: operator, rtl, noSideEffect, benign .}
 
 template subImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T =
-  normalize[T](a.seconds - b.seconds, a.nanoseconds - b.nanoseconds)
+  normalize[T](a.seconds - b.seconds, a.nanosecond - b.nanosecond)
 
 template addImpl[T: Duration|Time](a: Duration|Time, b: Duration|Time): T =
-  normalize[T](a.seconds + b.seconds, a.nanoseconds + b.nanoseconds)
+  normalize[T](a.seconds + b.seconds, a.nanosecond + b.nanosecond)
 
 template ltImpl(a: Duration|Time, b: Duration|Time): bool =
   a.seconds < b.seconds or (
-    a.seconds == b.seconds and a.nanoseconds < b.nanoseconds)
+    a.seconds == b.seconds and a.nanosecond < b.nanosecond)
 
 template lqImpl(a: Duration|Time, b: Duration|Time): bool =
-  a.seconds <= b.seconds or (
-    a.seconds == b.seconds and a.nanoseconds <= b.seconds)
+  a.seconds < b.seconds or (
+    a.seconds == b.seconds and a.nanosecond <= b.nanosecond)
 
 template eqImpl(a: Duration|Time, b: Duration|Time): bool =
-  a.seconds == b.seconds and a.nanoseconds == b.nanoseconds
+  a.seconds == b.seconds and a.nanosecond == b.nanosecond
 
 proc `+`*(a, b: Duration): Duration {.operator.} =
   ## Add two durations together.
@@ -507,7 +507,7 @@ proc `-`*(a: Duration): Duration {.operator.} =
   ## Reverse a duration.
   runnableExamples:
     doAssert -initDuration(seconds = 1) == initDuration(seconds = -1)
-  normalize[Duration](-a.seconds, -a.nanoseconds)
+  normalize[Duration](-a.seconds, -a.nanosecond)
 
 proc `<`*(a, b: Duration): bool {.operator.} =
   ## Note that a duration can be negative,
@@ -530,7 +530,7 @@ proc `*`*(a: int64, b: Duration): Duration {.operator} =
   ## Multiply a duration by some scalar.
   runnableExamples:
     doAssert 5 * initDuration(seconds = 1) == initDuration(seconds = 5)
-  normalize[Duration](a * b.seconds, a * b.nanoseconds)
+  normalize[Duration](a * b.seconds, a * b.nanosecond)
 
 proc `*`*(a: Duration, b: int64): Duration {.operator} =
   ## Multiply a duration by some scalar.
@@ -544,7 +544,7 @@ proc `div`*(a: Duration, b: int64): Duration {.operator} =
     doAssert initDuration(seconds = 3) div 2 == initDuration(milliseconds = 1500)
     doAssert initDuration(nanoseconds = 3) div 2 == initDuration(nanoseconds = 1)
   let carryOver = convert(Seconds, Nanoseconds, a.seconds mod b)
-  normalize[Duration](a.seconds div b, (a.nanoseconds + carryOver) div b)
+  normalize[Duration](a.seconds div b, (a.nanosecond + carryOver) div b)
 
 proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
   ## Computes the duration between two points in time.
@@ -600,7 +600,7 @@ proc abs*(a: Duration): Duration =
   runnableExamples:
     doAssert initDuration(milliseconds = -1500).abs ==
       initDuration(milliseconds = 1500)
-  initDuration(seconds = abs(a.seconds), nanoseconds = -a.nanoseconds)
+  initDuration(seconds = abs(a.seconds), nanoseconds = -a.nanosecond)
 
 proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} =
   ## Converts a broken-down time structure to
@@ -650,7 +650,7 @@ proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime =
     hour: hour,
     minute: minute,
     second: second,
-    nanosecond: zt.adjTime.nanoseconds,
+    nanosecond: zt.adjTime.nanosecond,
     weekday: getDayOfWeek(d, m, y),
     yearday: getDayOfYear(d, m, y),
     isDst: zt.isDst,
@@ -809,7 +809,7 @@ else:
     # as a result of offset changes (normally due to dst)
     let utcUnix = adjTime.seconds + utcOffset
     let (finalOffset, dst) = getLocalOffsetAndDst(utcUnix)
-    result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanoseconds)
+    result.adjTime = initTime(utcUnix - finalOffset, adjTime.nanosecond)
     result.utcOffset = finalOffset
     result.isDst = dst
 
@@ -1806,7 +1806,7 @@ proc toSeconds*(time: Time): float {.tags: [], raises: [], benign, deprecated.}
   ## Returns the time in seconds since the unix epoch.
   ##
   ## **Deprecated since v0.18.0:** use ``fromUnix`` instead
-  time.seconds.float + time.nanoseconds / convert(Seconds, Nanoseconds, 1)
+  time.seconds.float + time.nanosecond / convert(Seconds, Nanoseconds, 1)
 
 proc getLocalTime*(time: Time): DateTime {.tags: [], raises: [], benign, deprecated.} =
   ## Converts the calendar time `time` to broken-time representation,
@@ -1853,7 +1853,7 @@ when defined(JS):
     ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead.
     let dur = getTime() - start
     result = (convert(Seconds, Milliseconds, dur.seconds) +
-      convert(Nanoseconds, Milliseconds, dur.nanoseconds)).int
+      convert(Nanoseconds, Milliseconds, dur.nanosecond)).int
 else:
   proc getStartMilsecs*(): int {.deprecated, tags: [TimeEffect], benign.} =
     when defined(macosx):
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 257c620f7..cc4d28f5b 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -9,7 +9,7 @@
 
 ## This module provides support to handle the Unicode UTF-8 encoding.
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 include "system/inclrtl"
 
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 45696c80c..a6f62abce 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -12,9 +12,9 @@
 import macros, strtabs
 
 type
-  XmlNode* = ref XmlNodeObj ## an XML tree consists of ``PXmlNode``'s.
+  XmlNode* = ref XmlNodeObj ## an XML tree consists of ``XmlNode``'s.
 
-  XmlNodeKind* = enum  ## different kinds of ``PXmlNode``'s
+  XmlNodeKind* = enum  ## different kinds of ``XmlNode``'s
     xnText,             ## a text element
     xnElement,          ## an element with 0 or more children
     xnCData,            ## a CDATA node
@@ -315,9 +315,7 @@ proc newXmlTree*(tag: string, children: openArray[XmlNode],
   for i in 0..children.len-1: result.s[i] = children[i]
   result.fAttr = attributes
 
-proc xmlConstructor(e: NimNode): NimNode {.compileTime.} =
-  expectLen(e, 2)
-  var a = e[1]
+proc xmlConstructor(a: NimNode): NimNode {.compileTime.} =
   if a.kind == nnkCall:
     result = newCall("newXmlTree", toStrLit(a[0]))
     var attrs = newNimNode(nnkBracket, a)
@@ -348,7 +346,6 @@ macro `<>`*(x: untyped): untyped =
   ##
   ##  <a href="http://nim-lang.org">Nim rules.</a>
   ##
-  let x = callsite()
   result = xmlConstructor(x)
 
 proc child*(n: XmlNode, name: string): XmlNode =
diff --git a/lib/system.nim b/lib/system.nim
index 5e08dadc0..98c133428 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -146,7 +146,7 @@ proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
   ##     # missing it.
 
 when defined(useNimRtl):
-  {.deadCodeElim: on.}
+  {.deadCodeElim: on.}  # dce option deprecated
 
 proc definedInScope*(x: untyped): bool {.
   magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
@@ -3933,29 +3933,48 @@ proc addEscapedChar*(s: var string, c: char) {.noSideEffect, inline.} =
   ## * replaces any ``\`` by ``\\``
   ## * replaces any ``'`` by ``\'``
   ## * replaces any ``"`` by ``\"``
-  ## * replaces any other character in the set ``{'\0'..'\31', '\127'..'\255'}``
+  ## * replaces any ``\a`` by ``\\a``
+  ## * replaces any ``\b`` by ``\\b``
+  ## * replaces any ``\t`` by ``\\t``
+  ## * replaces any ``\n`` by ``\\n``
+  ## * replaces any ``\v`` by ``\\v``
+  ## * replaces any ``\f`` by ``\\f``
+  ## * replaces any ``\c`` by ``\\c``
+  ## * replaces any ``\e`` by ``\\e``
+  ## * replaces any other character not in the set ``{'\21..'\126'}
   ##   by ``\xHH`` where ``HH`` is its hexadecimal value.
   ##
   ## The procedure has been designed so that its output is usable for many
   ## different common syntaxes.
   ## **Note**: This is not correct for producing Ansi C code!
   case c
-  of '\0'..'\31', '\127'..'\255':
-    add(s, "\\x")
+  of '\a': s.add "\\a" # \x07
+  of '\b': s.add "\\b" # \x08
+  of '\t': s.add "\\t" # \x09
+  of '\n': s.add "\\n" # \x0A
+  of '\v': s.add "\\v" # \x0B
+  of '\f': s.add "\\f" # \x0C
+  of '\c': s.add "\\c" # \x0D
+  of '\e': s.add "\\e" # \x1B
+  of '\\': s.add("\\\\")
+  of '\'': s.add("\\'")
+  of '\"': s.add("\\\"")
+  of {'\32'..'\126'} - {'\\', '\'', '\"'}: s.add(c)
+  else:
+    s.add("\\x")
     const HexChars = "0123456789ABCDEF"
     let n = ord(c)
     s.add(HexChars[int((n and 0xF0) shr 4)])
     s.add(HexChars[int(n and 0xF)])
-  of '\\': add(s, "\\\\")
-  of '\'': add(s, "\\'")
-  of '\"': add(s, "\\\"")
-  else: add(s, c)
 
 proc addQuoted*[T](s: var string, x: T) =
   ## Appends `x` to string `s` in place, applying quoting and escaping
   ## if `x` is a string or char. See
   ## `addEscapedChar <system.html#addEscapedChar>`_
-  ## for the escaping scheme.
+  ## for the escaping scheme. When `x` is a string, characters in the
+  ## range ``{\128..\255}`` are never escaped so that multibyte UTF-8
+  ## characters are untouched (note that this behavior is different from
+  ## ``addEscapedChar``).
   ##
   ## The Nim standard library uses this function on the elements of
   ## collections when producing a string representation of a collection.
@@ -3974,7 +3993,12 @@ proc addQuoted*[T](s: var string, x: T) =
   when T is string:
     s.add("\"")
     for c in x:
-      s.addEscapedChar(c)
+      # Only ASCII chars are escaped to avoid butchering
+      # multibyte UTF-8 characters.
+      if c <= 127.char:
+        s.addEscapedChar(c)
+      else:
+        s.add c
     s.add("\"")
   elif T is char:
     s.add("'")
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 62bc38da9..7e22f98c7 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -10,7 +10,7 @@
 ## This module implements a small wrapper for some needed Win API procedures,
 ## so that the Nim compiler does not depend on the huge Windows module.
 
-{.deadCodeElim:on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 import dynlib
 
diff --git a/lib/wrappers/iup.nim b/lib/wrappers/iup.nim
index d910173ca..dee2e14c7 100644
--- a/lib/wrappers/iup.nim
+++ b/lib/wrappers/iup.nim
@@ -34,7 +34,7 @@
 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 # ****************************************************************************
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when defined(windows):
   const dllname = "iup(|30|27|26|25|24).dll"
diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim
index 4464eae50..06c663822 100644
--- a/lib/wrappers/mysql.nim
+++ b/lib/wrappers/mysql.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 {.push, callconv: cdecl.}
 
 when defined(Unix):
diff --git a/lib/wrappers/odbcsql.nim b/lib/wrappers/odbcsql.nim
index 1b2544ec0..43d1c504d 100644
--- a/lib/wrappers/odbcsql.nim
+++ b/lib/wrappers/odbcsql.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when not defined(ODBCVER):
   const
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index 357343bff..86ae85369 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -22,7 +22,7 @@
 ##   ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
 ##   ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 const useWinVersion = defined(Windows) or defined(nimdoc)
 
diff --git a/lib/wrappers/pcre.nim b/lib/wrappers/pcre.nim
index 6c7088bbf..e9e11960c 100644
--- a/lib/wrappers/pcre.nim
+++ b/lib/wrappers/pcre.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 # The current PCRE version information.
 
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
index f9a10dccb..7cb816f68 100644
--- a/lib/wrappers/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -15,7 +15,7 @@
 # connection-protocol.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 
 when defined(windows):
   const
diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim
index a12945832..0276a0a65 100644
--- a/lib/wrappers/sqlite3.nim
+++ b/lib/wrappers/sqlite3.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-{.deadCodeElim: on.}
+{.deadCodeElim: on.}  # dce option deprecated
 when defined(windows):
   when defined(nimOldDlls):
     const Lib = "sqlite3.dll"
diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim
index 49e61b9a9..b2764e9ee 100644
--- a/nimsuggest/nimsuggest.nim
+++ b/nimsuggest/nimsuggest.nim
@@ -518,7 +518,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
   close(requests)
   close(results)
 
-proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
+proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) =
   var p = parseopt.initOptParser(cmd)
   while true:
     parseopt.next(p)
@@ -562,7 +562,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
           gRefresh = true
       of "maxresults":
         suggestMaxResults = parseInt(p.val)
-      else: processSwitch(pass, p)
+      else: processSwitch(pass, p, config)
     of cmdArgument:
       let a = unixToNativePath(p.key)
       if dirExists(a) and not fileExists(a.addFileExt("nim")):
@@ -577,7 +577,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
   if paramCount() == 0:
     stdout.writeline(Usage)
   else:
-    processCmdLine(passCmd1, "")
+    processCmdLine(passCmd1, "", config)
     if gMode != mstdin:
       msgs.writelnHook = proc (msg: string) = discard
     if gProjectName != "":
@@ -616,7 +616,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
       runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
 
     extccomp.initVars()
-    processCmdLine(passCmd2, "")
+    processCmdLine(passCmd2, "", config)
 
     let graph = newModuleGraph(config)
     graph.suggestMode = true
diff --git a/tests/assign/toverload_asgn1.nim b/tests/assign/toverload_asgn1.nim
index dbc3a71c4..01e7e7aa7 100644
--- a/tests/assign/toverload_asgn1.nim
+++ b/tests/assign/toverload_asgn1.nim
@@ -14,6 +14,7 @@ GenericT[T] '=' bool
 GenericT[T] '=' bool
 GenericT[T] '=' bool
 GenericT[T] '=' bool'''
+  disabled: "true"
 """
 
 import typetraits
diff --git a/tests/assign/toverload_asgn2.nim b/tests/assign/toverload_asgn2.nim
index 243c90494..1104be92b 100644
--- a/tests/assign/toverload_asgn2.nim
+++ b/tests/assign/toverload_asgn2.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''i value 88
 2aa'''
+  disabled: "true"
 """
 
 import moverload_asgn2
diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim
index 6cc8a84ff..48b06a6aa 100644
--- a/tests/collections/tcollections_to_string.nim
+++ b/tests/collections/tcollections_to_string.nim
@@ -85,14 +85,20 @@ block:
   s.addQuoted('\0')
   s.addQuoted('\31')
   s.addQuoted('\127')
-  s.addQuoted('\255')
-  doAssert s == "'\\x00''\\x1F''\\x7F''\\xFF'"
+  doAssert s == "'\\x00''\\x1F''\\x7F'"
 block:
   var s = ""
   s.addQuoted('\\')
   s.addQuoted('\'')
   s.addQuoted('\"')
   doAssert s == """'\\''\'''\"'"""
+block:
+  var s = ""
+  s.addQuoted("å")
+  s.addQuoted("ä")
+  s.addQuoted("ö")
+  s.addEscapedChar('\xFF')
+  doAssert s == """"å""ä""ö"\xFF"""
 
 # Test customized element representation
 type CustomString = object
diff --git a/tests/enum/toptions.nim b/tests/enum/toptions.nim
index e53acb2b3..da66f0067 100644
--- a/tests/enum/toptions.nim
+++ b/tests/enum/toptions.nim
@@ -4,7 +4,7 @@ type
   TOption = enum
     optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck,
     optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir,
-    optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly,
+    optWarns, optHints, optListCmd, optCompileOnly,
     optSafeCode,             # only allow safe code
     optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib,
     optGenGuiApp, optStackTrace
diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim
new file mode 100644
index 000000000..6a037b5d8
--- /dev/null
+++ b/tests/flags/tgenscript.nim
@@ -0,0 +1,5 @@
+discard """
+  file: "tgenscript.nim"
+"""
+
+echo "--genscript"
diff --git a/tests/iter/tobj_iter.nim b/tests/iter/tobj_iter.nim
index eb0e37b23..a894755d7 100644
--- a/tests/iter/tobj_iter.nim
+++ b/tests/iter/tobj_iter.nim
@@ -4,8 +4,6 @@ discard """
 
 # bug #2023
 
-{.deadCodeElim:on.}
-
 type
     Obj = object
         iter: iterator (): int8 {.closure.}
diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
index 56d3edec4..f06c4e0be 100644
--- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
+++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
@@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1"
 
 when defined(MoreNim):
   {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".}
-{.deadCodeElim: on.}
 from math import sqrt, sin, cos, arctan2
 when defined(CpUseFloat):
   {.hint: "CpUseFloat defined; using float32 as float".}
diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim
index 3c4ce2017..3ea8172d5 100644
--- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim
+++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim
@@ -20,7 +20,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 const Lib = "libenet.so.1(|.0.3)"
 
-{.deadCodeElim: on.}
 const
   ENET_VERSION_MAJOR* = 1
   ENET_VERSION_MINOR* = 3
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
index d3a0c701d..86c12fbb0 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
@@ -1,5 +1,5 @@
 import macros
-{.deadCodeElim: on.}
+
 #Inline macro.add() to allow for easier nesting
 proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} =
   a.add(b)
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
index 1524f0eb4..0060bf12b 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
@@ -12,7 +12,7 @@ else:
     LibS = "libcsfml-system.so.2.0"
     LibW = "libcsfml-window.so.2.0"
   #{.error: "Platform unsupported".}
-{.deadCodeElim: on.}
+
 {.pragma: pf, pure, final.}
 type
   PClock* = ptr TClock
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
index 95a760e1f..b4eb1b8f0 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
@@ -1,5 +1,5 @@
 import sfml
-{.deadCodeElim: on.}
+
 let
   Black*: TColor = color(0, 0, 0)
   White*: TColor = color(255, 255, 255)
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
index 474d249aa..94c5308a9 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
@@ -1,2 +1 @@
 import sfml, math, strutils
-{.deadCodeElim: on.}
diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim
index c0f1bc031..59347ee46 100644
--- a/tests/manyloc/keineschweine/keineschweine.nim
+++ b/tests/manyloc/keineschweine/keineschweine.nim
@@ -5,7 +5,7 @@ import
   sg_gui, sg_assets, sound_buffer, enet_client
 when defined(profiler):
   import nimprof
-{.deadCodeElim: on.}
+
 type
   PPlayer* = ref TPlayer
   TPlayer* = object
diff --git a/tests/manyloc/keineschweine/lib/sg_gui.nim b/tests/manyloc/keineschweine/lib/sg_gui.nim
index ffc4e8215..b7448d9df 100644
--- a/tests/manyloc/keineschweine/lib/sg_gui.nim
+++ b/tests/manyloc/keineschweine/lib/sg_gui.nim
@@ -2,7 +2,7 @@ import
   sfml, sfml_colors,
   input_helpers, sg_packets
 from strutils import countlines
-{.deadCodeElim: on.}
+
 type
   PGuiContainer* = ref TGuiContainer
   TGuiContainer* = object of TObject
diff --git a/tests/manyloc/keineschweine/server/nim.cfg b/tests/manyloc/keineschweine/server/nim.cfg
index fdc45a8e1..211ad3003 100644
--- a/tests/manyloc/keineschweine/server/nim.cfg
+++ b/tests/manyloc/keineschweine/server/nim.cfg
@@ -1,5 +1,4 @@
 debugger = off
-deadCodeElim = on
 path = ".."
 path = "../genpacket"
 path = "../helpers"
diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim
index 2055d7834..97af79a84 100644
--- a/tests/manyloc/nake/nakefile.nim
+++ b/tests/manyloc/nake/nakefile.nim
@@ -10,7 +10,7 @@ const
   ExeName = "keineschweine"
   ServerDefines = "-d:NoSFML -d:NoChipmunk"
   TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild"
-  ReleaseDefines = "-d:release --deadCodeElim:on"
+  ReleaseDefines = "-d:release"
   ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild"
 
 task "testprofile", "..":
diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg
index bb350ff55..b956bef8e 100644
--- a/tests/manyloc/standalone/barebone.nim.cfg
+++ b/tests/manyloc/standalone/barebone.nim.cfg
@@ -1,3 +1,2 @@
 --os:standalone
---deadCodeElim:on
 --gc:none
diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim
index 9de5012f5..4b3610c67 100644
--- a/tests/parallel/tparfind.nim
+++ b/tests/parallel/tparfind.nim
@@ -4,7 +4,7 @@ discard """
 
 import threadpool, sequtils
 
-{.experimental.}
+{.experimental: "parallel".}
 
 proc linearFind(a: openArray[int]; x, offset: int): int =
   for i, y in a:
diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim
index 4d00c6034..bb59b1c71 100644
--- a/tests/pragmas/tnoreturn.nim
+++ b/tests/pragmas/tnoreturn.nim
@@ -2,13 +2,16 @@ discard """
 ccodeCheck: "\\i @'__attribute__((noreturn))' .*"
 """
 
-proc noret1*(i: int) {.noreturn.} = 
+proc noret1*(i: int) {.noreturn.} =
   echo i
 
 
-proc noret2*(i: int): void {.noreturn.} = 
+proc noret2*(i: int): void {.noreturn.} =
   echo i
 
+noret1(1)
+noret2(2)
+
 var p {.used.}: proc(i: int): int
 doAssert(not compiles(
   p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int
diff --git a/tests/rodfiles/deadg.nim b/tests/rodfiles/deadg.nim
index 587608e14..0aee59bb8 100644
--- a/tests/rodfiles/deadg.nim
+++ b/tests/rodfiles/deadg.nim
@@ -1,6 +1,3 @@
-
-{.deadCodeElim: on.}
-
 proc p1*(x, y: int): int =
   result = x + y
 
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index 945d7ba3d..37e14c1e2 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -367,6 +367,10 @@ suite "ttimes":
     check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500)
     check d(milliseconds = -1500) == d(seconds = -1, milliseconds = -500)
     check d(seconds = -1, milliseconds = 500) == d(milliseconds = -500)
+    check initDuration(seconds = 1, nanoseconds = 2) <=
+      initDuration(seconds = 1, nanoseconds = 3)
+    check (initDuration(seconds = 1, nanoseconds = 3) <=
+      initDuration(seconds = 1, nanoseconds = 1)).not
 
   test "large/small dates":
     discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc())
@@ -413,7 +417,7 @@ suite "ttimes":
   
   test "fromWinTime/toWinTime":
     check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0
-    check (-1).fromWinTime.nanoseconds == convert(Seconds, Nanoseconds, 1) - 100
+    check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100
     check -1.fromWinTime.toWinTime == -1
     # One nanosecond is discarded due to differences in time resolution
-    check initTime(0, 101).toWinTime.fromWinTime.nanoseconds == 100 
\ No newline at end of file
+    check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 
\ No newline at end of file
diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim
index 4acef9ca4..385f1171c 100644
--- a/tests/testament/backend.nim
+++ b/tests/testament/backend.nim
@@ -13,7 +13,7 @@ type
   CommitId = distinct string
 
 proc `$`*(id: MachineId): string {.borrow.}
-proc `$`(id: CommitId): string {.borrow.}
+#proc `$`(id: CommitId): string {.borrow.} # not used
 
 var
   thisMachine: MachineId
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 2f9198759..84e536636 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -63,6 +63,26 @@ proc compileRodFiles(r: var TResults, cat: Category, options: string) =
   test "gtkex1", true
   test "gtkex2"
 
+# --------------------- flags tests -------------------------------------------
+
+proc flagTests(r: var TResults, cat: Category, options: string) =
+  # --genscript
+  const filename = "tests"/"flags"/"tgenscript"
+  const genopts = " --genscript"
+  let nimcache = nimcacheDir(filename, genopts, targetC)
+  testSpec r, makeTest(filename, genopts, cat)
+
+  when defined(windows):
+    testExec r, makeTest(filename, " cmd /c cd " & nimcache &
+                         " && compile_tgenscript.bat", cat)
+
+  when defined(linux):
+    testExec r, makeTest(filename, " sh -c \"cd " & nimcache &
+                         " && sh compile_tgenscript.sh\"", cat)
+
+  # Run
+  testExec r, makeTest(filename, " " & nimcache / "tgenscript", cat)
+
 # --------------------- DLL generation tests ----------------------------------
 
 proc safeCopyFile(src, dest: string) =
@@ -323,7 +343,7 @@ var nimbleDir = getEnv("NIMBLE_DIR").string
 if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
 let
   nimbleExe = findExe("nimble")
-  packageDir = nimbleDir / "pkgs"
+  #packageDir = nimbleDir / "pkgs" # not used
   packageIndex = nimbleDir / "packages.json"
 
 proc waitForExitEx(p: Process): int =
@@ -407,9 +427,9 @@ proc `&.?`(a, b: string): string =
   # candidate for the stdlib?
   result = if b.startswith(a): b else: a & b
 
-proc `&?.`(a, b: string): string =
+#proc `&?.`(a, b: string): string = # not used
   # candidate for the stdlib?
-  result = if a.endswith(b): a else: a & b
+  #result = if a.endswith(b): a else: a & b
 
 proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
   let test = "tests" & DirSep &.? cat.string / test
@@ -429,6 +449,8 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
     jsTests(r, cat, options)
   of "dll":
     dllTests(r, cat, options)
+  of "flags":
+    flagTests(r, cat, options)
   of "gc":
     gcTests(r, cat, options)
   of "longgc":
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index bf26a956d..4a888427e 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -121,7 +121,7 @@ proc generateAllTestsContent(outfile: File, allResults: AllTests,
 
 proc generateHtml*(filename: string, onlyFailing: bool) =
   let
-    currentTime = getTime().getLocalTime()
+    currentTime = getTime().local()
     timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz")
   var outfile = open(filename, fmWrite)
 
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 856f95f3b..f08c83079 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -16,7 +16,7 @@ import
 
 const
   resultsFile = "testresults.html"
-  jsonFile = "testresults.json"
+  #jsonFile = "testresults.json" # not used
   Usage = """Usage:
   tester [options] command [arguments]
 
@@ -150,11 +150,11 @@ proc initResults: TResults =
   result.skipped = 0
   result.data = ""
 
-proc readResults(filename: string): TResults =
-  result = marshal.to[TResults](readFile(filename).string)
+#proc readResults(filename: string): TResults = # not used
+#  result = marshal.to[TResults](readFile(filename).string)
 
-proc writeResults(filename: string, r: TResults) =
-  writeFile(filename, $$r)
+#proc writeResults(filename: string, r: TResults) = # not used
+#  writeFile(filename, $$r)
 
 proc `$`(x: TResults): string =
   result = ("Tests passed: $1 / $3 <br />\n" &
@@ -404,6 +404,21 @@ proc testC(r: var TResults, test: TTest) =
     if exitCode != 0: given.err = reExitCodesDiffer
   if given.err == reSuccess: inc(r.passed)
 
+proc testExec(r: var TResults, test: TTest) =
+  # runs executable or script, just goes by exit code
+  inc(r.total)
+  let (outp, errC) = execCmdEx(test.options.strip())
+  var given: TSpec
+  specDefaults(given)
+  if errC == 0:
+    given.err = reSuccess
+  else:
+    given.err = reExitCodesDiffer
+    given.msg = outp.string
+
+  if given.err == reSuccess: inc(r.passed)
+  r.addResult(test, targetC, "", given.msg, given.err)
+
 proc makeTest(test, options: string, cat: Category, action = actionCompile,
               env: string = ""): TTest =
   # start with 'actionCompile', will be overwritten in the spec:
diff --git a/tools/nim.bash-completion b/tools/nim.bash-completion
index 1c199a0cf..8e569079a 100644
--- a/tools/nim.bash-completion
+++ b/tools/nim.bash-completion
@@ -15,7 +15,7 @@ _nim()
    return 0
  fi
   case $prev in
-    --stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks|--deadCodeElim)
+    --stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks)
       # Options that require on/off
       [[ "$cur" == "=" ]] && cur=""
       COMPREPLY=( $(compgen -W 'on off' -- "$cur") )
@@ -32,7 +32,7 @@ _nim()
       return 0
     ;;
     *)
-      kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks= --deadCodeElim="
+      kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks="
       COMPREPLY=( $( compgen -W "${kw}" -- $cur ) )
       _filedir '@(nim)'
       #$split
diff --git a/tools/nim.zsh-completion b/tools/nim.zsh-completion
index 57b5e163e..e9b9002fb 100644
--- a/tools/nim.zsh-completion
+++ b/tools/nim.zsh-completion
@@ -60,8 +60,6 @@ _nim() {
     '*--infChecks=off[turn Inf checks off]' \
     '*--nilChecks=on[turn nil checks on]' \
     '*--nilChecks=off[turn nil checks off]' \
-    '*--deadCodeElim=on[whole program dead code elimination on]' \
-    '*--deadCodeElim=off[whole program dead code elimination off]' \
     '*--opt=none[do not optimize]' \
     '*--opt=speed[optimize for speed|size - use -d:release for a release build]' \
     '*--opt=size[optimize for size]' \
diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim
index 8dc076ad9..4cfcbe9bc 100644
--- a/tools/nimgrep.nim
+++ b/tools/nimgrep.nim
@@ -11,7 +11,7 @@ import
   os, strutils, parseopt, pegs, re, terminal
 
 const
-  Version = "1.1"
+  Version = "1.2"
   Usage = "nimgrep - Nim Grep Utility Version " & Version & """
 
   (c) 2012 Andreas Rumpf
@@ -35,6 +35,8 @@ Options:
   --nocolor           output will be given without any colours.
   --oneline           show file on each matched line
   --verbose           be verbose: list every processed file
+  --filenames         find the pattern in the filenames, not in the contents
+                      of the file
   --help, -h          shows this help
   --version, -v       shows the version
 """
@@ -42,7 +44,7 @@ Options:
 type
   TOption = enum
     optFind, optReplace, optPeg, optRegex, optRecursive, optConfirm, optStdin,
-    optWord, optIgnoreCase, optIgnoreStyle, optVerbose
+    optWord, optIgnoreCase, optIgnoreStyle, optVerbose, optFilenames
   TOptions = set[TOption]
   TConfirmEnum = enum
     ceAbort, ceYes, ceAll, ceNo, ceNone
@@ -135,11 +137,14 @@ proc processFile(pattern; filename: string) =
       filenameShown = true
 
   var buffer: string
-  try:
-    buffer = system.readFile(filename)
-  except IOError:
-    echo "cannot open file: ", filename
-    return
+  if optFilenames in options:
+    buffer = filename
+  else:
+    try:
+      buffer = system.readFile(filename)
+    except IOError:
+      echo "cannot open file: ", filename
+      return
   if optVerbose in options:
     stdout.writeLine(filename)
     stdout.flushFile()
@@ -293,6 +298,7 @@ for kind, key, val in getopt():
     of "nocolor": useWriteStyled = false
     of "oneline": oneline = true
     of "verbose": incl(options, optVerbose)
+    of "filenames": incl(options, optFilenames)
     of "help", "h": writeHelp()
     of "version", "v": writeVersion()
     else: writeHelp()
@@ -304,6 +310,7 @@ when defined(posix):
 checkOptions({optFind, optReplace}, "find", "replace")
 checkOptions({optPeg, optRegex}, "peg", "re")
 checkOptions({optIgnoreCase, optIgnoreStyle}, "ignore_case", "ignore_style")
+checkOptions({optFilenames, optReplace}, "filenames", "replace")
 
 if optStdin in options:
   pattern = ask("pattern [ENTER to exit]: ")