fixes #3171
This commit is contained in:
parent
9275d5c617
commit
bd786812e7
2 changed files with 282 additions and 272 deletions
|
|
@ -591,280 +591,282 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||||
validPragmas: TSpecialWords): bool =
|
validPragmas: TSpecialWords): bool =
|
||||||
var it = n.sons[i]
|
var it = n.sons[i]
|
||||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||||
if key.kind == nkIdent:
|
if key.kind == nkBracketExpr:
|
||||||
var userPragma = strTableGet(c.userPragmas, key.ident)
|
processNote(c, it)
|
||||||
if userPragma != nil:
|
return
|
||||||
inc c.instCounter
|
let ident = considerQuotedIdent(key)
|
||||||
if c.instCounter > 100:
|
var userPragma = strTableGet(c.userPragmas, ident)
|
||||||
globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
|
if userPragma != nil:
|
||||||
pragma(c, sym, userPragma.ast, validPragmas)
|
inc c.instCounter
|
||||||
# ensure the pragma is also remember for generic instantiations in other
|
if c.instCounter > 100:
|
||||||
# modules:
|
globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
|
||||||
n.sons[i] = userPragma.ast
|
pragma(c, sym, userPragma.ast, validPragmas)
|
||||||
dec c.instCounter
|
# ensure the pragma is also remember for generic instantiations in other
|
||||||
else:
|
# modules:
|
||||||
var k = whichKeyword(key.ident)
|
n.sons[i] = userPragma.ast
|
||||||
if k in validPragmas:
|
dec c.instCounter
|
||||||
case k
|
else:
|
||||||
of wExportc:
|
var k = whichKeyword(ident)
|
||||||
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
if k in validPragmas:
|
||||||
incl(sym.flags, sfUsed) # avoid wrong hints
|
case k
|
||||||
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
|
of wExportc:
|
||||||
of wImportCompilerProc:
|
makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info)
|
||||||
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
|
incl(sym.flags, sfUsed) # avoid wrong hints
|
||||||
of wExtern: setExternName(sym, expectStrLit(c, it))
|
of wImportc: makeExternImport(sym, getOptionalStr(c, it, "$1"))
|
||||||
of wImmediate:
|
of wImportCompilerProc:
|
||||||
if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
|
processImportCompilerProc(sym, getOptionalStr(c, it, "$1"))
|
||||||
else: invalidPragma(it)
|
of wExtern: setExternName(sym, expectStrLit(c, it))
|
||||||
of wDirty:
|
of wImmediate:
|
||||||
if sym.kind == skTemplate: incl(sym.flags, sfDirty)
|
if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate)
|
||||||
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: 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: invalidPragma(it)
|
||||||
else: processNote(c, it)
|
else: invalidPragma(it)
|
||||||
|
|
||||||
proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
|
proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
|
||||||
validPragmas: TSpecialWords) =
|
validPragmas: TSpecialWords) =
|
||||||
|
|
|
||||||
8
tests/pragmas/tsym_as_pragma.nim
Normal file
8
tests/pragmas/tsym_as_pragma.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
# bug #3171
|
||||||
|
|
||||||
|
template newDataWindow(): stmt =
|
||||||
|
let eventClosure = proc (closure: pointer): bool {.closure, cdecl.} =
|
||||||
|
discard
|
||||||
|
|
||||||
|
newDataWindow()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue