don't generate memset calls for C++ objects

This commit is contained in:
Araq 2015-03-17 21:36:40 +01:00
commit 1fc590b6ea
5 changed files with 448 additions and 440 deletions

View file

@ -9,19 +9,19 @@
# This module implements semantic checking for pragmas
import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
import
os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
rodread, types, lookups
const
const
FirstCallConv* = wNimcall
LastCallConv* = wNoconv
const
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wMagic, wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
@ -33,7 +33,7 @@ const
macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc,
wNodecl, wMagic, wNosideeffect, wCompilerproc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator}
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
wTags, wLocks, wGcSafe}
@ -46,18 +46,18 @@ const
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
wInjectStmt, wDeprecated, wExperimental}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
wRaises, wLocks, wTags, wGcSafe}
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
wBorrow, wGcSafe}
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
wImportCpp, wImportObjC, wError, wGuard}
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
wGensym, wInject, wCodegenDecl, wGuard}
@ -74,18 +74,18 @@ proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
proc invalidPragma(n: PNode) =
localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments}))
proc pragmaAsm*(c: PContext, n: PNode): char =
proc pragmaAsm*(c: PContext, n: PNode): char =
result = '\0'
if n != nil:
for i in countup(0, sonsLen(n) - 1):
if n != nil:
for i in countup(0, sonsLen(n) - 1):
let it = n.sons[i]
if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent:
case whichKeyword(it.sons[0].ident)
of wSubsChar:
of wSubsChar:
if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal))
else: invalidPragma(it)
else: invalidPragma(it)
else:
else:
invalidPragma(it)
proc setExternName(s: PSym, extname: string) =
@ -94,7 +94,7 @@ proc setExternName(s: PSym, extname: string) =
# note that '{.importc.}' is transformed into '{.importc: "$1".}'
s.loc.flags.incl(lfFullExternalName)
proc makeExternImport(s: PSym, extname: string) =
proc makeExternImport(s: PSym, extname: string) =
setExternName(s, extname)
incl(s.flags, sfImportc)
excl(s.flags, sfForward)
@ -145,7 +145,7 @@ proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
result.strVal = ""
proc getStrLitNode(c: PContext, n: PNode): PNode =
if n.kind != nkExprColonExpr:
if n.kind != nkExprColonExpr:
localError(n.info, errStringLiteralExpected)
# error correction:
result = newEmptyStrNode(n)
@ -153,62 +153,62 @@ proc getStrLitNode(c: PContext, n: PNode): PNode =
n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind
of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
else:
else:
localError(n.info, errStringLiteralExpected)
# error correction:
result = newEmptyStrNode(n)
proc expectStrLit(c: PContext, n: PNode): string =
proc expectStrLit(c: PContext, n: PNode): string =
result = getStrLitNode(c, n).strVal
proc expectIntLit(c: PContext, n: PNode): int =
if n.kind != nkExprColonExpr:
proc expectIntLit(c: PContext, n: PNode): int =
if n.kind != nkExprColonExpr:
localError(n.info, errIntLiteralExpected)
else:
else:
n.sons[1] = c.semConstExpr(c, n.sons[1])
case n.sons[1].kind
of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal)
else: localError(n.info, errIntLiteralExpected)
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string =
if n.kind == nkExprColonExpr: result = expectStrLit(c, n)
else: result = defaultStr
proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) =
sym.constraint = getStrLitNode(c, n)
proc processMagic(c: PContext, n: PNode, s: PSym) =
proc processMagic(c: PContext, n: PNode, s: PSym) =
#if sfSystemModule notin c.module.flags:
# liMessage(n.info, errMagicOnlyInSystem)
if n.kind != nkExprColonExpr:
if n.kind != nkExprColonExpr:
localError(n.info, errStringLiteralExpected)
return
var v: string
if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s
else: v = expectStrLit(c, n)
for m in countup(low(TMagic), high(TMagic)):
if substr($m, 1) == v:
for m in countup(low(TMagic), high(TMagic)):
if substr($m, 1) == v:
s.magic = m
break
if s.magic == mNone: message(n.info, warnUnknownMagic, v)
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
proc wordToCallConv(sw: TSpecialWord): TCallingConvention =
# this assumes that the order of special words and calling conventions is
# the same
result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall))
proc isTurnedOn(c: PContext, n: PNode): bool =
proc isTurnedOn(c: PContext, n: PNode): bool =
if n.kind == nkExprColonExpr:
let x = c.semConstBoolExpr(c, n.sons[1])
n.sons[1] = x
if x.kind == nkIntLit: return x.intVal != 0
localError(n.info, errOnOrOffExpected)
proc onOff(c: PContext, n: PNode, op: TOptions) =
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) =
proc pragmaDeadCodeElim(c: PContext, n: PNode) =
if isTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
else: excl(c.module.flags, sfDeadCodeElim)
@ -216,20 +216,20 @@ proc pragmaNoForward(c: PContext, n: PNode) =
if isTurnedOn(c, n): incl(c.module.flags, sfNoForward)
else: excl(c.module.flags, sfNoForward)
proc processCallConv(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
proc processCallConv(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
var sw = whichKeyword(n.sons[1].ident)
case sw
of FirstCallConv..LastCallConv:
of FirstCallConv..LastCallConv:
POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
else: localError(n.info, errCallConvExpected)
else:
else:
localError(n.info, errCallConvExpected)
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
var it = PLib(c.libs.head)
while it != nil:
if it.kind == kind:
while it != nil:
if it.kind == kind:
if trees.exprStructuralEquivalent(it.path, path): return it
it = PLib(it.next)
result = newLib(kind)
@ -252,10 +252,10 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode =
if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}:
localError(n.info, errStringLiteralExpected)
result = newEmptyStrNode(n)
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
proc processDynLib(c: PContext, n: PNode, sym: PSym) =
if (sym == nil) or (sym.kind == skModule):
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
POptionEntry(c.optionStack.tail).dynlib = getLib(c, libDynamic,
expectDynlibNode(c, n))
else:
if n.kind == nkExprColonExpr:
@ -268,7 +268,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
# since we'll be loading the dynlib symbols dynamically, we must use
# a calling convention that doesn't introduce custom name mangling
# cdecl is the default - the user can override this explicitly
if sym.kind in routineKinds and sym.typ != nil and
if sym.kind in routineKinds and sym.typ != nil and
sym.typ.callConv == ccDefault:
sym.typ.callConv = ccCDecl
@ -295,10 +295,10 @@ proc processNote(c: PContext, n: PNode) =
n.sons[1] = x
if x.kind == nkIntLit and x.intVal != 0: incl(gNotes, nk)
else: excl(gNotes, nk)
else:
else:
invalidPragma(n)
proc processOption(c: PContext, n: PNode): bool =
proc processOption(c: PContext, n: PNode): bool =
if n.kind != nkExprColonExpr: result = true
elif n.sons[0].kind == nkBracketExpr: processNote(c, n)
elif n.sons[0].kind != nkIdent: result = true
@ -318,34 +318,34 @@ proc processOption(c: PContext, n: PNode): bool =
of wAssertions: onOff(c, n, {optAssert})
of wWarnings: onOff(c, n, {optWarns})
of wHints: onOff(c, n, {optHints})
of wCallconv: processCallConv(c, n)
of wCallconv: processCallConv(c, n)
of wLinedir: onOff(c, n, {optLineDir})
of wStacktrace: onOff(c, n, {optStackTrace})
of wLinetrace: onOff(c, n, {optLineTrace})
of wDebugger: onOff(c, n, {optEndb})
of wProfiler: onOff(c, n, {optProfiler})
of wByRef: onOff(c, n, {optByRef})
of wDynlib: processDynLib(c, n, nil)
of wOptimization:
if n.sons[1].kind != nkIdent:
of wDynlib: processDynLib(c, n, nil)
of wOptimization:
if n.sons[1].kind != nkIdent:
invalidPragma(n)
else:
else:
case n.sons[1].ident.s.normalize
of "speed":
of "speed":
incl(gOptions, optOptimizeSpeed)
excl(gOptions, optOptimizeSize)
of "size":
excl(gOptions, optOptimizeSpeed)
incl(gOptions, optOptimizeSize)
of "none":
of "none":
excl(gOptions, optOptimizeSpeed)
excl(gOptions, optOptimizeSize)
else: localError(n.info, errNoneSpeedOrSizeExpected)
of wImplicitStatic: onOff(c, n, {optImplicitStatic})
of wPatterns: onOff(c, n, {optPatterns})
else: result = true
proc processPush(c: PContext, n: PNode, start: int) =
proc processPush(c: PContext, n: PNode, start: int) =
if n.sons[start-1].kind == nkExprColonExpr:
localError(n.info, errGenerated, "':' after 'push' not supported")
var x = newOptionEntry()
@ -355,41 +355,41 @@ proc processPush(c: PContext, n: PNode, start: int) =
x.dynlib = y.dynlib
x.notes = gNotes
append(c.optionStack, x)
for i in countup(start, sonsLen(n) - 1):
for i in countup(start, sonsLen(n) - 1):
if processOption(c, n.sons[i]):
# simply store it somewhere:
if x.otherPragmas.isNil:
x.otherPragmas = newNodeI(nkPragma, n.info)
x.otherPragmas.add n.sons[i]
#localError(n.info, errOptionExpected)
proc processPop(c: PContext, n: PNode) =
if c.optionStack.counter <= 1:
proc processPop(c: PContext, n: PNode) =
if c.optionStack.counter <= 1:
localError(n.info, errAtPopWithoutPush)
else:
gOptions = POptionEntry(c.optionStack.tail).options
else:
gOptions = POptionEntry(c.optionStack.tail).options
gNotes = POptionEntry(c.optionStack.tail).notes
remove(c.optionStack, c.optionStack.tail)
proc processDefine(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
proc processDefine(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
defineSymbol(n.sons[1].ident.s)
message(n.info, warnDeprecated, "define")
else:
else:
invalidPragma(n)
proc processUndef(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
proc processUndef(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
undefSymbol(n.sons[1].ident.s)
message(n.info, warnDeprecated, "undef")
else:
else:
invalidPragma(n)
type
TLinkFeature = enum
type
TLinkFeature = enum
linkNormal, linkSys
proc processCompile(c: PContext, n: PNode) =
proc processCompile(c: PContext, n: PNode) =
var s = expectStrLit(c, n)
var found = findFile(s)
if found == "": found = s
@ -397,7 +397,7 @@ proc processCompile(c: PContext, n: PNode) =
extccomp.addExternalFileToCompile(found)
extccomp.addFileToLink(completeCFilePath(trunc, false))
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
var f = expectStrLit(c, n)
if splitFile(f).ext == "": f = addFileExt(f, CC[cCompiler].objExt)
var found = findFile(f)
@ -407,8 +407,8 @@ proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) =
of linkSys:
extccomp.addFileToLink(libpath / completeCFilePath(found, false))
else: internalError(n.info, "processCommonLink")
proc pragmaBreakpoint(c: PContext, n: PNode) =
proc pragmaBreakpoint(c: PContext, n: PNode) =
discard getOptionalStr(c, n, "")
proc pragmaWatchpoint(c: PContext, n: PNode) =
@ -427,59 +427,59 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
return
# now parse the string literal and substitute symbols:
var a = 0
while true:
while true:
var b = strutils.find(str, marker, a)
var sub = if b < 0: substr(str, a) else: substr(str, a, b - 1)
if sub != "": addSon(result, newStrNode(nkStrLit, sub))
if b < 0: break
if b < 0: break
var c = strutils.find(str, marker, b + 1)
if c < 0: sub = substr(str, b + 1)
else: sub = substr(str, b + 1, c - 1)
if sub != "":
if sub != "":
var e = searchInScopes(con, getIdent(sub))
if e != nil:
if e != nil:
if e.kind == skStub: loadStub(e)
addSon(result, newSymNode(e))
else:
else:
addSon(result, newStrNode(nkStrLit, sub))
else:
# an empty '``' produces a single '`'
addSon(result, newStrNode(nkStrLit, $marker))
if c < 0: break
if c < 0: break
a = c + 1
else:
illFormedAstLocal(n)
result = newNode(nkAsmStmt, n.info)
proc pragmaEmit(c: PContext, n: PNode) =
proc pragmaEmit(c: PContext, n: PNode) =
discard getStrLitNode(c, n)
n.sons[1] = semAsmOrEmit(c, n, '`')
proc noVal(n: PNode) =
proc noVal(n: PNode) =
if n.kind == nkExprColonExpr: invalidPragma(n)
proc pragmaUnroll(c: PContext, n: PNode) =
if c.p.nestedLoopCounter <= 0:
proc pragmaUnroll(c: PContext, n: PNode) =
if c.p.nestedLoopCounter <= 0:
invalidPragma(n)
elif n.kind == nkExprColonExpr:
var unrollFactor = expectIntLit(c, n)
if unrollFactor <% 32:
if unrollFactor <% 32:
n.sons[1] = newIntNode(nkIntLit, unrollFactor)
else:
else:
invalidPragma(n)
proc pragmaLine(c: PContext, n: PNode) =
if n.kind == nkExprColonExpr:
n.sons[1] = c.semConstExpr(c, n.sons[1])
let a = n.sons[1]
if a.kind == nkPar:
if a.kind == nkPar:
var x = a.sons[0]
var y = a.sons[1]
if x.kind == nkExprColonExpr: x = x.sons[1]
if y.kind == nkExprColonExpr: y = y.sons[1]
if x.kind != nkStrLit:
if x.kind != nkStrLit:
localError(n.info, errStringLiteralExpected)
elif y.kind != nkIntLit:
elif y.kind != nkIntLit:
localError(n.info, errIntLiteralExpected)
else:
n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
@ -490,12 +490,12 @@ proc pragmaLine(c: PContext, n: PNode) =
# sensible default:
n.info = getInfoContext(-1)
proc processPragma(c: PContext, n: PNode, i: int) =
proc processPragma(c: PContext, n: PNode, i: int) =
var it = n.sons[i]
if it.kind != nkExprColonExpr: invalidPragma(n)
elif it.sons[0].kind != nkIdent: invalidPragma(n)
elif it.sons[1].kind != nkIdent: invalidPragma(n)
var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info)
var body = newNodeI(nkPragma, n.info)
for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j])
@ -508,7 +508,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
if t.kind != tyObject:
localError(x.info, errGenerated, "invalid type for raises/tags list")
x.typ = t
if n.kind == nkExprColonExpr:
let it = n.sons[1]
if it.kind notin {nkCurly, nkBracket}:
@ -569,7 +569,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) =
localError(n.info, "key:value pair expected")
proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
if it.kind != nkExprColonExpr:
if it.kind != nkExprColonExpr:
invalidPragma(it); return
let n = it[1]
if n.kind == nkSym:
@ -592,9 +592,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
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:
if userPragma != nil:
inc c.instCounter
if c.instCounter > 100:
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
@ -603,9 +603,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
dec c.instCounter
else:
var k = whichKeyword(key.ident)
if k in validPragmas:
if k in validPragmas:
case k
of wExportc:
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"))
@ -627,16 +627,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
var align = expectIntLit(c, it)
if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
localError(it.info, errPowerOfTwoExpected)
else:
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:
if not isPowerOfTwo(size) or size <= 0 or size > 8:
localError(it.info, errPowerOfTwoExpected)
else:
sym.typ.size = size
of wNodecl:
of wNodecl:
noVal(it)
incl(sym.loc.flags, lfNoDecl)
of wPure, wAsmNoStackFrame:
@ -644,19 +644,19 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if sym != nil:
if k == wPure and sym.kind in routineKinds: invalidPragma(it)
else: incl(sym.flags, sfPure)
of wVolatile:
of wVolatile:
noVal(it)
incl(sym.flags, sfVolatile)
of wRegister:
of wRegister:
noVal(it)
incl(sym.flags, sfRegister)
of wThreadVar:
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:
of wCompileTime:
noVal(it)
incl(sym.flags, sfCompileTime)
incl(sym.loc.flags, lfNoDecl)
@ -664,15 +664,15 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it)
incl(sym.flags, sfGlobal)
incl(sym.flags, sfPure)
of wMerge:
of wMerge:
noVal(it)
incl(sym.flags, sfMerge)
of wHeader:
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)
incl(sym.loc.flags, lfNoDecl)
# implies nodecl, because otherwise header would not make sense
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
of wDestructor:
@ -685,13 +685,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it)
incl(sym.flags, sfNoSideEffect)
if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect)
of wSideeffect:
of wSideeffect:
noVal(it)
incl(sym.flags, sfSideEffect)
of wNoreturn:
of wNoreturn:
noVal(it)
incl(sym.flags, sfNoReturn)
of wDynlib:
of wDynlib:
processDynLib(c, it, sym)
of wCompilerproc:
noVal(it) # compilerproc may not get a string!
@ -703,7 +703,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
elif sym != nil: incl(sym.flags, sfDeprecated)
else: incl(c.module.flags, sfDeprecated)
of wVarargs:
of wVarargs:
noVal(it)
if sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfVarargs)
@ -713,7 +713,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
else:
noVal(it)
incl(sym.flags, sfBorrow)
of wFinal:
of wFinal:
noVal(it)
if sym.typ == nil: invalidPragma(it)
else: incl(sym.typ.flags, tfFinal)
@ -745,10 +745,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
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:
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
# allowed for top level statements. Seems to be easier than
# distinguishing properly between
# ``proc p() {.error}`` and ``proc p() = {.error: "msg".}``
noVal(it)
@ -765,11 +765,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
of wPassc: extccomp.addCompileOption(expectStrLit(c, it))
of wBreakpoint: pragmaBreakpoint(c, it)
of wWatchPoint: pragmaWatchpoint(c, it)
of wPush:
of wPush:
processPush(c, n, i + 1)
result = true
result = true
of wPop: processPop(c, it)
of wPragma:
of wPragma:
processPragma(c, n, i)
result = true
of wDiscardable:
@ -779,16 +779,16 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
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,
of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
wLinedir, wStacktrace, wLinetrace, wOptimization,
wCallconv,
wCallconv,
wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
wPatterns:
if processOption(c, it):
# calling conventions (boring...):
localError(it.info, errOptionExpected)
of FirstCallConv..LastCallConv:
of FirstCallConv..LastCallConv:
assert(sym != nil)
if sym.typ == nil: invalidPragma(it)
else: sym.typ.callConv = wordToCallConv(k)
@ -843,14 +843,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
of wInjectStmt:
if it.kind != nkExprColonExpr:
localError(it.info, errExprExpected)
else:
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")
localError(it.info, "'experimental' pragma only valid as toplevel statement")
else: invalidPragma(it)
else: invalidPragma(it)
else: processNote(c, it)
@ -884,7 +884,7 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
var key = if p.kind == nkExprColonExpr: p[0] else: p
if key.kind == nkIdent and whichKeyword(key.ident) == pragma:
return true
return false
proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =