summary refs log tree commit diff stats
path: root/compiler/pragmas.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2015-08-02 00:35:02 +0200
committerAraq <rumpf_a@web.de>2015-08-02 02:55:59 +0200
commitbd786812e7fd1cbd1b7a8f038000ac06ad08505e (patch)
treed8b27176a52c8c3bc969f4307c9fe92d9f51f7c1 /compiler/pragmas.nim
parent9275d5c6178e7674882dbbaa257f6bb2b5a7b6bf (diff)
downloadNim-bd786812e7fd1cbd1b7a8f038000ac06ad08505e.tar.gz
fixes #3171
Diffstat (limited to 'compiler/pragmas.nim')
-rw-r--r--compiler/pragmas.nim544
1 files changed, 273 insertions, 271 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index c771155af..128a90138 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -591,280 +591,282 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
                   validPragmas: TSpecialWords): bool =
   var it = n.sons[i]
   var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
-  if key.kind == nkIdent:
-    var userPragma = strTableGet(c.userPragmas, key.ident)
-    if userPragma != nil:
-      inc c.instCounter
-      if c.instCounter > 100:
-        globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
-      pragma(c, sym, userPragma.ast, validPragmas)
-      # ensure the pragma is also remember for generic instantiations in other
-      # modules:
-      n.sons[i] = userPragma.ast
-      dec c.instCounter
-    else:
-      var k = whichKeyword(key.ident)
-      if k in validPragmas:
-        case k
-        of wExportc:
-          makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
-          incl(sym.flags, sfUsed) # avoid wrong hints
-        of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
-        of wImportCompilerProc:
-          processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
-        of wExtern: setExternName(sym, expectStrLit(c, it))
-        of wImmediate:
-          if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
-          else: invalidPragma(it)
-        of wDirty:
-          if sym.kind == skTemplate: incl(sym.flags, sfDirty)
-          else: invalidPragma(it)
-        of wImportCpp:
-          processImportCpp(sym, getOptionalStr(c, it, "$1"))
-        of wImportObjC:
-          processImportObjC(sym, getOptionalStr(c, it, "$1"))
-        of wAlign:
-          if sym.typ == nil: invalidPragma(it)
-          var align = expectIntLit(c, it)
-          if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
-            localError(it.info, errPowerOfTwoExpected)
-          else:
-            sym.typ.align = align.int16
-        of wSize:
-          if sym.typ == nil: invalidPragma(it)
-          var size = expectIntLit(c, it)
-          if not isPowerOfTwo(size) or size <= 0 or size > 8:
-            localError(it.info, errPowerOfTwoExpected)
-          else:
-            sym.typ.size = size
-        of wNodecl:
-          noVal(it)
-          incl(sym.loc.flags, lfNoDecl)
-        of wPure, wAsmNoStackFrame:
-          noVal(it)
-          if sym != nil:
-            if k == wPure and sym.kind in routineKinds: invalidPragma(it)
-            else: incl(sym.flags, sfPure)
-        of wVolatile:
-          noVal(it)
-          incl(sym.flags, sfVolatile)
-        of wRegister:
-          noVal(it)
-          incl(sym.flags, sfRegister)
-        of wThreadVar:
-          noVal(it)
-          incl(sym.flags, sfThread)
-        of wDeadCodeElim: pragmaDeadCodeElim(c, it)
-        of wNoForward: pragmaNoForward(c, it)
-        of wMagic: processMagic(c, it, sym)
-        of wCompileTime:
-          noVal(it)
-          incl(sym.flags, sfCompileTime)
-          incl(sym.loc.flags, lfNoDecl)
-        of wGlobal:
-          noVal(it)
-          incl(sym.flags, sfGlobal)
-          incl(sym.flags, sfPure)
-        of wMerge:
-          # only supported for backwards compat, doesn't do anything anymore
-          noVal(it)
-        of wConstructor:
-          noVal(it)
-          incl(sym.flags, sfConstructor)
-        of wHeader:
-          var lib = getLib(c, libHeader, getStrLitNode(c, it))
-          addToLib(lib, sym)
-          incl(sym.flags, sfImportc)
-          incl(sym.loc.flags, lfHeader)
-          incl(sym.loc.flags, lfNoDecl)
-          # implies nodecl, because otherwise header would not make sense
-          if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
-        of wDestructor:
-          sym.flags.incl sfOverriden
-          if sym.name.s.normalize != "destroy":
-            localError(n.info, errGenerated, "destructor has to be named 'destroy'")
-        of wOverride:
-          sym.flags.incl sfOverriden
-        of wNosideeffect:
-          noVal(it)
-          incl(sym.flags, sfNoSideEffect)
-          if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
-        of wSideeffect:
-          noVal(it)
-          incl(sym.flags, sfSideEffect)
-        of wNoreturn:
-          noVal(it)
-          incl(sym.flags, sfNoReturn)
-        of wDynlib:
-          processDynLib(c, it, sym)
-        of wCompilerproc:
-          noVal(it)           # compilerproc may not get a string!
-          if sfFromGeneric notin sym.flags: markCompilerProc(sym)
-        of wProcVar:
-          noVal(it)
-          incl(sym.flags, sfProcvar)
-        of wDeprecated:
-          if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
-          elif sym != nil: incl(sym.flags, sfDeprecated)
-          else: incl(c.module.flags, sfDeprecated)
-        of wVarargs:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfVarargs)
-        of wBorrow:
-          if sym.kind == skType:
-            typeBorrow(sym, it)
-          else:
-            noVal(it)
-            incl(sym.flags, sfBorrow)
-        of wFinal:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfFinal)
-        of wInheritable:
-          noVal(it)
-          if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it)
-          else: incl(sym.typ.flags, tfInheritable)
-        of wAcyclic:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfAcyclic)
-        of wShallow:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfShallow)
-        of wThread:
-          noVal(it)
-          incl(sym.flags, sfThread)
-          incl(sym.flags, sfProcvar)
-          if sym.typ != nil: incl(sym.typ.flags, tfThread)
-        of wGcSafe:
-          noVal(it)
-          if sym.kind != skType: incl(sym.flags, sfThread)
-          if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
-          else: invalidPragma(it)
-        of wPacked:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfPacked)
-        of wHint: message(it.info, hintUser, expectStrLit(c, it))
-        of wWarning: message(it.info, warnUser, expectStrLit(c, it))
-        of wError:
-          if sym != nil and sym.isRoutine:
-            # This is subtle but correct: the error *statement* is only
-            # allowed for top level statements. Seems to be easier than
-            # distinguishing properly between
-            # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
-            noVal(it)
-            incl(sym.flags, sfError)
-          else:
-            localError(it.info, errUser, expectStrLit(c, it))
-        of wFatal: fatal(it.info, errUser, expectStrLit(c, it))
-        of wDefine: processDefine(c, it)
-        of wUndef: processUndef(c, it)
-        of wCompile: processCompile(c, it)
-        of wLink: processCommonLink(c, it, linkNormal)
-        of wLinksys: processCommonLink(c, it, linkSys)
-        of wPassl: extccomp.addLinkOption(expectStrLit(c, it))
-        of wPassc: extccomp.addCompileOption(expectStrLit(c, it))
-        of wBreakpoint: pragmaBreakpoint(c, it)
-        of wWatchPoint: pragmaWatchpoint(c, it)
-        of wPush:
-          processPush(c, n, i + 1)
-          result = true
-        of wPop: processPop(c, it)
-        of wPragma:
-          processPragma(c, n, i)
-          result = true
-        of wDiscardable:
-          noVal(it)
-          if sym != nil: incl(sym.flags, sfDiscardable)
-        of wNoInit:
-          noVal(it)
-          if sym != nil: incl(sym.flags, sfNoInit)
-        of wCodegenDecl: processCodegenDecl(c, it, sym)
-        of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
-           wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
-           wLinedir, wStacktrace, wLinetrace, wOptimization,
-           wCallconv,
-           wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
-           wPatterns:
-          if processOption(c, it):
-            # calling conventions (boring...):
-            localError(it.info, errOptionExpected)
-        of FirstCallConv..LastCallConv:
-          assert(sym != nil)
-          if sym.typ == nil: invalidPragma(it)
-          else: sym.typ.callConv = wordToCallConv(k)
-        of wEmit: pragmaEmit(c, it)
-        of wUnroll: pragmaUnroll(c, it)
-        of wLinearScanEnd, wComputedGoto: noVal(it)
-        of wEffects:
-          # is later processed in effect analysis:
-          noVal(it)
-        of wIncompleteStruct:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfIncompleteStruct)
-        of wUnchecked:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfUncheckedArray)
-        of wUnion:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfUnion)
-        of wRequiresInit:
-          noVal(it)
-          if sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfNeedsInit)
-        of wByRef:
-          noVal(it)
-          if sym == nil or sym.typ == nil:
-            if processOption(c, it): localError(it.info, errOptionExpected)
-          else:
-            incl(sym.typ.flags, tfByRef)
-        of wByCopy:
-          noVal(it)
-          if sym.kind != skType or sym.typ == nil: invalidPragma(it)
-          else: incl(sym.typ.flags, tfByCopy)
-        of wInject, wGensym:
-          # We check for errors, but do nothing with these pragmas otherwise
-          # as they are handled directly in 'evalTemplate'.
-          noVal(it)
-          if sym == nil: invalidPragma(it)
-        of wLine: pragmaLine(c, it)
-        of wRaises, wTags: pragmaRaisesOrTags(c, it)
-        of wLocks:
-          if sym == nil: pragmaLockStmt(c, it)
-          elif sym.typ == nil: invalidPragma(it)
-          else: sym.typ.lockLevel = pragmaLocks(c, it)
-        of wGuard:
-          if sym == nil or sym.kind notin {skVar, skLet, skField}:
-            invalidPragma(it)
-          else:
-            sym.guard = pragmaGuard(c, it, sym.kind)
-        of wGoto:
-          if sym == nil or sym.kind notin {skVar, skLet}:
-            invalidPragma(it)
-          else:
-            sym.flags.incl sfGoto
-        of wInjectStmt:
-          if it.kind != nkExprColonExpr:
-            localError(it.info, errExprExpected)
-          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")
-        of wNoRewrite:
+  if key.kind == nkBracketExpr:
+    processNote(c, it)
+    return
+  let ident = considerQuotedIdent(key)
+  var userPragma = strTableGet(c.userPragmas, ident)
+  if userPragma != nil:
+    inc c.instCounter
+    if c.instCounter > 100:
+      globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
+    pragma(c, sym, userPragma.ast, validPragmas)
+    # ensure the pragma is also remember for generic instantiations in other
+    # modules:
+    n.sons[i] = userPragma.ast
+    dec c.instCounter
+  else:
+    var k = whichKeyword(ident)
+    if k in validPragmas:
+      case k
+      of wExportc:
+        makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
+        incl(sym.flags, sfUsed) # avoid wrong hints
+      of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
+      of wImportCompilerProc:
+        processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
+      of wExtern: setExternName(sym, expectStrLit(c, it))
+      of wImmediate:
+        if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
+        else: invalidPragma(it)
+      of wDirty:
+        if sym.kind == skTemplate: incl(sym.flags, sfDirty)
+        else: invalidPragma(it)
+      of wImportCpp:
+        processImportCpp(sym, getOptionalStr(c, it, "$1"))
+      of wImportObjC:
+        processImportObjC(sym, getOptionalStr(c, it, "$1"))
+      of wAlign:
+        if sym.typ == nil: invalidPragma(it)
+        var align = expectIntLit(c, it)
+        if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
+          localError(it.info, errPowerOfTwoExpected)
+        else:
+          sym.typ.align = align.int16
+      of wSize:
+        if sym.typ == nil: invalidPragma(it)
+        var size = expectIntLit(c, it)
+        if not isPowerOfTwo(size) or size <= 0 or size > 8:
+          localError(it.info, errPowerOfTwoExpected)
+        else:
+          sym.typ.size = size
+      of wNodecl:
+        noVal(it)
+        incl(sym.loc.flags, lfNoDecl)
+      of wPure, wAsmNoStackFrame:
+        noVal(it)
+        if sym != nil:
+          if k == wPure and sym.kind in routineKinds: invalidPragma(it)
+          else: incl(sym.flags, sfPure)
+      of wVolatile:
+        noVal(it)
+        incl(sym.flags, sfVolatile)
+      of wRegister:
+        noVal(it)
+        incl(sym.flags, sfRegister)
+      of wThreadVar:
+        noVal(it)
+        incl(sym.flags, sfThread)
+      of wDeadCodeElim: pragmaDeadCodeElim(c, it)
+      of wNoForward: pragmaNoForward(c, it)
+      of wMagic: processMagic(c, it, sym)
+      of wCompileTime:
+        noVal(it)
+        incl(sym.flags, sfCompileTime)
+        incl(sym.loc.flags, lfNoDecl)
+      of wGlobal:
+        noVal(it)
+        incl(sym.flags, sfGlobal)
+        incl(sym.flags, sfPure)
+      of wMerge:
+        # only supported for backwards compat, doesn't do anything anymore
+        noVal(it)
+      of wConstructor:
+        noVal(it)
+        incl(sym.flags, sfConstructor)
+      of wHeader:
+        var lib = getLib(c, libHeader, getStrLitNode(c, it))
+        addToLib(lib, sym)
+        incl(sym.flags, sfImportc)
+        incl(sym.loc.flags, lfHeader)
+        incl(sym.loc.flags, lfNoDecl)
+        # implies nodecl, because otherwise header would not make sense
+        if sym.loc.r == nil: sym.loc.r = rope(sym.name.s)
+      of wDestructor:
+        sym.flags.incl sfOverriden
+        if sym.name.s.normalize != "destroy":
+          localError(n.info, errGenerated, "destructor has to be named 'destroy'")
+      of wOverride:
+        sym.flags.incl sfOverriden
+      of wNosideeffect:
+        noVal(it)
+        incl(sym.flags, sfNoSideEffect)
+        if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
+      of wSideeffect:
+        noVal(it)
+        incl(sym.flags, sfSideEffect)
+      of wNoreturn:
+        noVal(it)
+        incl(sym.flags, sfNoReturn)
+      of wDynlib:
+        processDynLib(c, it, sym)
+      of wCompilerproc:
+        noVal(it)           # compilerproc may not get a string!
+        if sfFromGeneric notin sym.flags: markCompilerProc(sym)
+      of wProcVar:
+        noVal(it)
+        incl(sym.flags, sfProcvar)
+      of wDeprecated:
+        if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
+        elif sym != nil: incl(sym.flags, sfDeprecated)
+        else: incl(c.module.flags, sfDeprecated)
+      of wVarargs:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfVarargs)
+      of wBorrow:
+        if sym.kind == skType:
+          typeBorrow(sym, it)
+        else:
           noVal(it)
+          incl(sym.flags, sfBorrow)
+      of wFinal:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfFinal)
+      of wInheritable:
+        noVal(it)
+        if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it)
+        else: incl(sym.typ.flags, tfInheritable)
+      of wAcyclic:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfAcyclic)
+      of wShallow:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfShallow)
+      of wThread:
+        noVal(it)
+        incl(sym.flags, sfThread)
+        incl(sym.flags, sfProcvar)
+        if sym.typ != nil: incl(sym.typ.flags, tfThread)
+      of wGcSafe:
+        noVal(it)
+        if sym.kind != skType: incl(sym.flags, sfThread)
+        if sym.typ != nil: incl(sym.typ.flags, tfGcSafe)
         else: invalidPragma(it)
+      of wPacked:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfPacked)
+      of wHint: message(it.info, hintUser, expectStrLit(c, it))
+      of wWarning: message(it.info, warnUser, expectStrLit(c, it))
+      of wError:
+        if sym != nil and sym.isRoutine:
+          # This is subtle but correct: the error *statement* is only
+          # allowed for top level statements. Seems to be easier than
+          # distinguishing properly between
+          # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
+          noVal(it)
+          incl(sym.flags, sfError)
+        else:
+          localError(it.info, errUser, expectStrLit(c, it))
+      of wFatal: fatal(it.info, errUser, expectStrLit(c, it))
+      of wDefine: processDefine(c, it)
+      of wUndef: processUndef(c, it)
+      of wCompile: processCompile(c, it)
+      of wLink: processCommonLink(c, it, linkNormal)
+      of wLinksys: processCommonLink(c, it, linkSys)
+      of wPassl: extccomp.addLinkOption(expectStrLit(c, it))
+      of wPassc: extccomp.addCompileOption(expectStrLit(c, it))
+      of wBreakpoint: pragmaBreakpoint(c, it)
+      of wWatchPoint: pragmaWatchpoint(c, it)
+      of wPush:
+        processPush(c, n, i + 1)
+        result = true
+      of wPop: processPop(c, it)
+      of wPragma:
+        processPragma(c, n, i)
+        result = true
+      of wDiscardable:
+        noVal(it)
+        if sym != nil: incl(sym.flags, sfDiscardable)
+      of wNoInit:
+        noVal(it)
+        if sym != nil: incl(sym.flags, sfNoInit)
+      of wCodegenDecl: processCodegenDecl(c, it, sym)
+      of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
+         wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
+         wLinedir, wStacktrace, wLinetrace, wOptimization,
+         wCallconv,
+         wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
+         wPatterns:
+        if processOption(c, it):
+          # calling conventions (boring...):
+          localError(it.info, errOptionExpected)
+      of FirstCallConv..LastCallConv:
+        assert(sym != nil)
+        if sym.typ == nil: invalidPragma(it)
+        else: sym.typ.callConv = wordToCallConv(k)
+      of wEmit: pragmaEmit(c, it)
+      of wUnroll: pragmaUnroll(c, it)
+      of wLinearScanEnd, wComputedGoto: noVal(it)
+      of wEffects:
+        # is later processed in effect analysis:
+        noVal(it)
+      of wIncompleteStruct:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfIncompleteStruct)
+      of wUnchecked:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfUncheckedArray)
+      of wUnion:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfUnion)
+      of wRequiresInit:
+        noVal(it)
+        if sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfNeedsInit)
+      of wByRef:
+        noVal(it)
+        if sym == nil or sym.typ == nil:
+          if processOption(c, it): localError(it.info, errOptionExpected)
+        else:
+          incl(sym.typ.flags, tfByRef)
+      of wByCopy:
+        noVal(it)
+        if sym.kind != skType or sym.typ == nil: invalidPragma(it)
+        else: incl(sym.typ.flags, tfByCopy)
+      of wInject, wGensym:
+        # We check for errors, but do nothing with these pragmas otherwise
+        # as they are handled directly in 'evalTemplate'.
+        noVal(it)
+        if sym == nil: invalidPragma(it)
+      of wLine: pragmaLine(c, it)
+      of wRaises, wTags: pragmaRaisesOrTags(c, it)
+      of wLocks:
+        if sym == nil: pragmaLockStmt(c, it)
+        elif sym.typ == nil: invalidPragma(it)
+        else: sym.typ.lockLevel = pragmaLocks(c, it)
+      of wGuard:
+        if sym == nil or sym.kind notin {skVar, skLet, skField}:
+          invalidPragma(it)
+        else:
+          sym.guard = pragmaGuard(c, it, sym.kind)
+      of wGoto:
+        if sym == nil or sym.kind notin {skVar, skLet}:
+          invalidPragma(it)
+        else:
+          sym.flags.incl sfGoto
+      of wInjectStmt:
+        if it.kind != nkExprColonExpr:
+          localError(it.info, errExprExpected)
+        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")
+      of wNoRewrite:
+        noVal(it)
       else: invalidPragma(it)
-  else: processNote(c, it)
+    else: invalidPragma(it)
 
 proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
                       validPragmas: TSpecialWords) =