C++ backend: use .noInit pragma for non-public default constructors; refs #4687

This commit is contained in:
Andreas Rumpf 2016-09-04 22:27:38 +02:00
commit dfa0699e73
5 changed files with 45 additions and 18 deletions

View file

@ -437,7 +437,7 @@ type
nfExplicitCall # x.y() was used instead of x.y nfExplicitCall # x.y() was used instead of x.y
nfExprCall # this is an attempt to call a regular expression nfExprCall # this is an attempt to call a regular expression
nfIsRef # this node is a 'ref' node; used for the VM nfIsRef # this node is a 'ref' node; used for the VM
nfIsCursor # this node is attached a cursor; used for idetools nfPreventCg # this node should be ignored by the codegen
TNodeFlags* = set[TNodeFlag] TNodeFlags* = set[TNodeFlag]
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 28) TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 28)
@ -925,7 +925,7 @@ const
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias} skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
nfDotSetter, nfDotField, nfDotSetter, nfDotField,
nfIsRef, nfIsCursor, nfLL} nfIsRef, nfPreventCg, nfLL}
namePos* = 0 namePos* = 0
patternPos* = 1 # empty except for term rewriting macros patternPos* = 1 # empty except for term rewriting macros
genericParamsPos* = 2 genericParamsPos* = 2

View file

@ -2084,11 +2084,14 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkCaseStmt: genCase(p, n, d) of nkCaseStmt: genCase(p, n, d)
of nkReturnStmt: genReturnStmt(p, n) of nkReturnStmt: genReturnStmt(p, n)
of nkBreakStmt: genBreakStmt(p, n) of nkBreakStmt: genBreakStmt(p, n)
of nkAsgn: genAsgn(p, n, fastAsgn=false) of nkAsgn:
if nfPreventCg notin n.flags:
genAsgn(p, n, fastAsgn=false)
of nkFastAsgn: of nkFastAsgn:
# transf is overly aggressive with 'nkFastAsgn', so we work around here. if nfPreventCg notin n.flags:
# See tests/run/tcnstseq3 for an example that would fail otherwise. # transf is overly aggressive with 'nkFastAsgn', so we work around here.
genAsgn(p, n, fastAsgn=p.prc != nil) # See tests/run/tcnstseq3 for an example that would fail otherwise.
genAsgn(p, n, fastAsgn=p.prc != nil)
of nkDiscardStmt: of nkDiscardStmt:
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
genLineDir(p, n) genLineDir(p, n)

View file

@ -359,6 +359,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
linefmt(p, cpsStmts, "#popCurrentException();$n") linefmt(p, cpsStmts, "#popCurrentException();$n")
proc genReturnStmt(p: BProc, t: PNode) = proc genReturnStmt(p: BProc, t: PNode) =
if nfPreventCg in t.flags: return
p.beforeRetNeeded = true p.beforeRetNeeded = true
genLineDir(p, t) genLineDir(p, t)
if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0]) if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])

View file

@ -616,6 +616,24 @@ proc closureSetup(p: BProc, prc: PSym) =
linefmt(p, cpsStmts, "$1 = ($2) ClEnv;$n", linefmt(p, cpsStmts, "$1 = ($2) ClEnv;$n",
rdLoc(env.loc), getTypeDesc(p.module, env.typ)) rdLoc(env.loc), getTypeDesc(p.module, env.typ))
proc easyResultAsgn(n: PNode): PNode =
const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt} +
declarativeDefs
case n.kind
of nkStmtList, nkStmtListExpr:
var i = 0
while i < n.len and n[i].kind in harmless: inc i
if i < n.len: result = easyResultAsgn(n[i])
of nkAsgn, nkFastAsgn:
if n[0].kind == nkSym and skResult == n[0].sym.kind:
incl n.flags, nfPreventCg
return n[1]
of nkReturnStmt:
if n.len > 0:
result = easyResultAsgn(n[0])
if result != nil: incl n.flags, nfPreventCg
else: discard
proc genProcAux(m: BModule, prc: PSym) = proc genProcAux(m: BModule, prc: PSym) =
var p = newProc(prc, m) var p = newProc(prc, m)
var header = genProcHeader(m, prc) var header = genProcHeader(m, prc)
@ -627,11 +645,17 @@ proc genProcAux(m: BModule, prc: PSym) =
var res = prc.ast.sons[resultPos].sym # get result symbol var res = prc.ast.sons[resultPos].sym # get result symbol
if not isInvalidReturnType(prc.typ.sons[0]): if not isInvalidReturnType(prc.typ.sons[0]):
if sfNoInit in prc.flags: incl(res.flags, sfNoInit) if sfNoInit in prc.flags: incl(res.flags, sfNoInit)
# declare the result symbol: if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(prc.getBody); val != nil):
assignLocalVar(p, res) var decl = localVarDecl(p, res)
assert(res.loc.r != nil) var a: TLoc
initLocExprSingleUse(p, val, a)
linefmt(p, cpsStmts, "$1 = $2;$n", decl, rdLoc(a))
else:
# declare the result symbol:
assignLocalVar(p, res)
assert(res.loc.r != nil)
initLocalVar(p, res, immediateAsgn=false)
returnStmt = rfmt(nil, "\treturn $1;$n", rdLoc(res.loc)) returnStmt = rfmt(nil, "\treturn $1;$n", rdLoc(res.loc))
initLocalVar(p, res, immediateAsgn=false)
else: else:
fillResult(res) fillResult(res)
assignParam(p, res) assignParam(p, res)
@ -791,12 +815,12 @@ proc addIntTypes(result: var Rope) {.inline.} =
proc getCopyright(cfile: string): Rope = proc getCopyright(cfile: string): Rope =
if optCompileOnly in gGlobalOptions: if optCompileOnly in gGlobalOptions:
result = ("/* Generated by Nim Compiler v$1 */$N" & result = ("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2015 Andreas Rumpf */$N" & "/* (c) 2016 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N") % "/* The generated code is subject to the original license. */$N") %
[rope(VersionAsString)] [rope(VersionAsString)]
else: else:
result = ("/* Generated by Nim Compiler v$1 */$N" & result = ("/* Generated by Nim Compiler v$1 */$N" &
"/* (c) 2015 Andreas Rumpf */$N" & "/* (c) 2016 Andreas Rumpf */$N" &
"/* The generated code is subject to the original license. */$N" & "/* The generated code is subject to the original license. */$N" &
"/* Compiled for: $2, $3, $4 */$N" & "/* Compiled for: $2, $3, $4 */$N" &
"/* Command for C compiler:$n $5 */$N") % "/* Command for C compiler:$n $5 */$N") %

View file

@ -413,17 +413,16 @@ proc safeSemExpr*(c: PContext, n: PNode): PNode =
result = ast.emptyNode result = ast.emptyNode
proc suggestExpr*(c: PContext, node: PNode) = proc suggestExpr*(c: PContext, node: PNode) =
if nfIsCursor notin node.flags: if gTrackPos.line < 0: return
if gTrackPos.line < 0: return var cp = inCheckpoint(node.info)
var cp = inCheckpoint(node.info) if cp == cpNone: return
if cp == cpNone: return
var outputs = 0 var outputs = 0
# This keeps semExpr() from coming here recursively: # This keeps semExpr() from coming here recursively:
if c.compilesContextId > 0: return if c.compilesContextId > 0: return
inc(c.compilesContextId) inc(c.compilesContextId)
if gIdeCmd == ideSug: if gIdeCmd == ideSug:
var n = if nfIsCursor in node.flags: node else: findClosestDot(node) var n = findClosestDot(node)
if n == nil: n = node if n == nil: n = node
if n.kind == nkDotExpr: if n.kind == nkDotExpr:
var obj = safeSemExpr(c, n.sons[0]) var obj = safeSemExpr(c, n.sons[0])
@ -436,7 +435,7 @@ proc suggestExpr*(c: PContext, node: PNode) =
suggestEverything(c, n, outputs) suggestEverything(c, n, outputs)
elif gIdeCmd == ideCon: elif gIdeCmd == ideCon:
var n = if nfIsCursor in node.flags: node else: findClosestCall(node) var n = findClosestCall(node)
if n == nil: n = node if n == nil: n = node
if n.kind in nkCallKinds: if n.kind in nkCallKinds:
var a = copyNode(n) var a = copyNode(n)