From 34430b2a3e5de511edc798b5c3b10a1793cf5500 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 27 Jan 2022 09:38:31 +0800 Subject: [PATCH 01/14] add tfCDecl flags; nvro don't touch cdecl types fix 19342 again --- compiler/ast.nim | 3 ++- compiler/ccgtypes.nim | 3 ++- compiler/semstmts.nim | 3 +++ tests/objects/t19342_2.nim | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/objects/t19342_2.nim diff --git a/compiler/ast.nim b/compiler/ast.nim index 4286f940f138e..b8724c8301ecb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -501,7 +501,7 @@ type nfHasComment # node has a comment TNodeFlags* = set[TNodeFlag] - TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 43) + TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 44) tfVarargs, # procedure has C styled varargs # tyArray type represeting a varargs list tfNoSideEffect, # procedure type does not allow side effects @@ -570,6 +570,7 @@ type tfExplicitCallConv tfIsConstructor tfEffectSystemWorkaround + tfCDecl TTypeFlags* = set[TTypeFlag] diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index df1874b268707..3838e00d4219d 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -220,7 +220,8 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool = # such a poor programming language. # We exclude records with refs too. This enhances efficiency and # is necessary for proper code generation of assignments. - if rettype == nil or (tfByCopy notin rettype.flags and getSize(conf, rettype) > conf.target.floatSize*3): + if rettype == nil or ({tfByCopy, tfCDecl} * rettype.flags == {} and + getSize(conf, rettype) > conf.target.floatSize*3): result = true else: case mapType(conf, rettype, skResult) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 33e304ab22642..44767fa01008f 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -2137,6 +2137,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, incl(s.flags, sfWasForwarded) elif sfBorrow in s.flags: semBorrow(c, n, s) sideEffectsCheck(c, s) + + if s.typ.callConv == ccCDecl and s.typ[0] != nil: + s.typ[0].flags.incl tfCDecl closeScope(c) # close scope for parameters # c.currentScope = oldScope popOwner(c) diff --git a/tests/objects/t19342_2.nim b/tests/objects/t19342_2.nim new file mode 100644 index 0000000000000..2e2b40fcff04e --- /dev/null +++ b/tests/objects/t19342_2.nim @@ -0,0 +1,14 @@ +{.compile: "mtest.c".} + +# bug #19342 +type + Node* {.byRef.} = object + data: array[25, cint] + +proc myproc(name: cint): Node {.importc: "hello", cdecl.} + +proc parse = + let node = myproc(10) + doAssert node.data[0] == 999 + +parse() \ No newline at end of file From 0b95406dde2e2cc5939edbceb0c5a394413b5c88 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 27 Jan 2022 10:18:54 +0800 Subject: [PATCH 02/14] fix tests --- tests/objects/t19342_2.nim | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/objects/t19342_2.nim b/tests/objects/t19342_2.nim index 2e2b40fcff04e..6f6d0f2b3d31c 100644 --- a/tests/objects/t19342_2.nim +++ b/tests/objects/t19342_2.nim @@ -1,4 +1,8 @@ -{.compile: "mtest.c".} +discard """ + targets: "c cpp" +""" + +{.compile: "m19342.c".} # bug #19342 type From 9c4ec369afb4de102fec77db14f7795f001f7509 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 27 Jan 2022 22:05:49 +0800 Subject: [PATCH 03/14] checkpoint --- compiler/ast.nim | 1 - compiler/ccgcalls.nim | 6 +++--- compiler/ccgstmts.nim | 2 +- compiler/ccgtypes.nim | 32 ++++++++++++++++++++++++++------ compiler/cgen.nim | 4 ++-- compiler/semstmts.nim | 2 -- 6 files changed, 32 insertions(+), 15 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index b8724c8301ecb..229aba87d43ee 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -570,7 +570,6 @@ type tfExplicitCallConv tfIsConstructor tfEffectSystemWorkaround - tfCDecl TTypeFlags* = set[TTypeFlag] diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index fe0516f9a5845..197728ccfc7b9 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -76,7 +76,7 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, # getUniqueType() is too expensive here: var typ = skipTypes(ri[0].typ, abstractInst) if typ[0] != nil: - if isInvalidReturnType(p.config, typ[0]): + if isInvalidReturnType(p.config, typ): if params != nil: pl.add(~", ") # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri): @@ -439,7 +439,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) = let rawProc = getClosureType(p.module, typ, clHalf) let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0]) if typ[0] != nil: - if isInvalidReturnType(p.config, typ[0]): + if isInvalidReturnType(p.config, typ): if ri.len > 1: pl.add(~", ") # beware of 'result = p(result)'. We may need to allocate a temporary: if d.k in {locTemp, locNone} or not preventNrvo(p, le, ri): @@ -737,7 +737,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) = pl.add(~": ") pl.add(genArg(p, ri[i], param, ri)) if typ[0] != nil: - if isInvalidReturnType(p.config, typ[0]): + if isInvalidReturnType(p.config, typ): if ri.len > 1: pl.add(~" ") # beware of 'result = p(result)'. We always allocate a temporary: if d.k in {locTemp, locNone}: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 7fecc14752919..3372f1a712474 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -33,7 +33,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: return false - if isInvalidReturnType(conf, n.typ): + if isInvalidReturnType2(conf, n.typ): # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 3838e00d4219d..2e167455e0283 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -215,12 +215,13 @@ proc isObjLackingTypeField(typ: PType): bool {.inline.} = result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and (typ[0] == nil) or isPureObject(typ)) -proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool = +proc isInvalidReturnType(conf: ConfigRef; proctype: PType): bool = # Arrays and sets cannot be returned by a C procedure, because C is # such a poor programming language. # We exclude records with refs too. This enhances efficiency and # is necessary for proper code generation of assignments. - if rettype == nil or ({tfByCopy, tfCDecl} * rettype.flags == {} and + let rettype = proctype[0] + if rettype == nil or (proctype.callConv in {ccClosure, ccInline, ccNimCall} and getSize(conf, rettype) > conf.target.floatSize*3): result = true else: @@ -235,6 +236,25 @@ proc isInvalidReturnType(conf: ConfigRef; rettype: PType): bool = (t.kind == tyObject and not isObjLackingTypeField(t)) else: result = false +proc isInvalidReturnType2(conf: ConfigRef; rettype: PType): bool = + # Arrays and sets cannot be returned by a C procedure, because C is + # such a poor programming language. + # We exclude records with refs too. This enhances efficiency and + # is necessary for proper code generation of assignments. + if rettype == nil or getSize(conf, rettype) > conf.target.floatSize*3: + result = true + else: + case mapType(conf, rettype, skResult) + of ctArray: + result = not (skipTypes(rettype, typedescInst).kind in + {tyVar, tyLent, tyRef, tyPtr}) + of ctStruct: + let t = skipTypes(rettype, typedescInst) + if rettype.isImportedCppType or t.isImportedCppType: return false + result = containsGarbageCollectedRef(t) or + (t.kind == tyObject and not isObjLackingTypeField(t)) + else: result = false + const CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", "N_STDCALL", "N_CDECL", "N_SAFECALL", @@ -258,11 +278,11 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) = # see `testCodegenABICheck` for example error message it generates -proc fillResult(conf: ConfigRef; param: PNode) = +proc fillResult(conf: ConfigRef; param: PNode, proctype: PType) = fillLoc(param.sym.loc, locParam, param, ~"Result", OnStack) let t = param.sym.typ - if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, t): + if mapReturnType(conf, t) != ctArray and isInvalidReturnType(conf, proctype): incl(param.sym.loc.flags, lfIndirect) param.sym.loc.storage = OnUnknown @@ -427,7 +447,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope, check: var IntSet, declareEnvironment=true; weakDep=false) = params = nil - if t[0] == nil or isInvalidReturnType(m.config, t[0]): + if t[0] == nil or isInvalidReturnType(m.config, t): rettype = ~"void" else: rettype = getTypeDescAux(m, t[0], check, skResult) @@ -462,7 +482,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var Rope, params.addf(", NI $1Len_$2", [param.loc.r, j.rope]) inc(j) arr = arr[0].skipTypes({tySink}) - if t[0] != nil and isInvalidReturnType(m.config, t[0]): + if t[0] != nil and isInvalidReturnType(m.config, t): var arr = t[0] if params != nil: params.add(", ") if mapReturnType(m.config, t[0]) != ctArray: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 246b8c0e9eae2..10b4b55d0f2cb 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1039,7 +1039,7 @@ proc genProcAux(m: BModule, prc: PSym) = internalError(m.config, prc.info, "proc has no result symbol") let resNode = prc.ast[resultPos] let res = resNode.sym # get result symbol - if not isInvalidReturnType(m.config, prc.typ[0]): + if not isInvalidReturnType(m.config, prc.typ): if sfNoInit in prc.flags: incl(res.flags, sfNoInit) if sfNoInit in prc.flags and p.module.compileToCpp and (let val = easyResultAsgn(procBody); val != nil): var decl = localVarDecl(p, resNode) @@ -1053,7 +1053,7 @@ proc genProcAux(m: BModule, prc: PSym) = initLocalVar(p, res, immediateAsgn=false) returnStmt = ropecg(p.module, "\treturn $1;$n", [rdLoc(res.loc)]) else: - fillResult(p.config, resNode) + fillResult(p.config, resNode, prc.typ) assignParam(p, res, prc.typ[0]) # We simplify 'unsureAsgn(result, nil); unsureAsgn(result, x)' # to 'unsureAsgn(result, x)' diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 44767fa01008f..c2b385c80d58a 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -2138,8 +2138,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, elif sfBorrow in s.flags: semBorrow(c, n, s) sideEffectsCheck(c, s) - if s.typ.callConv == ccCDecl and s.typ[0] != nil: - s.typ[0].flags.incl tfCDecl closeScope(c) # close scope for parameters # c.currentScope = oldScope popOwner(c) From ce8791a64089f3aedee2ffc040e7107ad920e0f8 Mon Sep 17 00:00:00 2001 From: flywind Date: Thu, 27 Jan 2022 22:49:42 +0800 Subject: [PATCH 04/14] remove transient changes --- compiler/ast.nim | 2 +- compiler/ccgstmts.nim | 8 +++++--- compiler/ccgtypes.nim | 19 ------------------- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 229aba87d43ee..ad5ec12f530f9 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -501,7 +501,7 @@ type nfHasComment # node has a comment TNodeFlags* = set[TNodeFlag] - TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 44) + TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 45) tfVarargs, # procedure has C styled varargs # tyArray type represeting a varargs list tfNoSideEffect, # procedure type does not allow side effects diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 3372f1a712474..e2e89fa2759f6 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -33,12 +33,14 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: return false - if isInvalidReturnType2(conf, n.typ): + if n.kind in nkCallKinds and n[0] != nil and n[0].typ.kind == tyProc and + isInvalidReturnType(conf, n[0].typ): # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! - return false - result = true + result = false + else: + result = true proc inExceptBlockLen(p: BProc): int = for x in p.nestedTryStmts: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 2e167455e0283..986708df7425d 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -236,25 +236,6 @@ proc isInvalidReturnType(conf: ConfigRef; proctype: PType): bool = (t.kind == tyObject and not isObjLackingTypeField(t)) else: result = false -proc isInvalidReturnType2(conf: ConfigRef; rettype: PType): bool = - # Arrays and sets cannot be returned by a C procedure, because C is - # such a poor programming language. - # We exclude records with refs too. This enhances efficiency and - # is necessary for proper code generation of assignments. - if rettype == nil or getSize(conf, rettype) > conf.target.floatSize*3: - result = true - else: - case mapType(conf, rettype, skResult) - of ctArray: - result = not (skipTypes(rettype, typedescInst).kind in - {tyVar, tyLent, tyRef, tyPtr}) - of ctStruct: - let t = skipTypes(rettype, typedescInst) - if rettype.isImportedCppType or t.isImportedCppType: return false - result = containsGarbageCollectedRef(t) or - (t.kind == tyObject and not isObjLackingTypeField(t)) - else: result = false - const CallingConvToStr: array[TCallingConvention, string] = ["N_NIMCALL", "N_STDCALL", "N_CDECL", "N_SAFECALL", From 14aa057d971159d2bd5ce3e85fd22b15c60a170b Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 09:15:38 +0800 Subject: [PATCH 05/14] checkpoint3 --- compiler/ccgstmts.nim | 10 +++++++--- compiler/ccgtypes.nim | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e2e89fa2759f6..d74632aaf2758 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -32,15 +32,19 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = "$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc]) proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = - if n.kind == nkEmpty: return false - if n.kind in nkCallKinds and n[0] != nil and n[0].typ.kind == tyProc and + if n.kind == nkEmpty: + result = false + elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.kind == tyProc and isInvalidReturnType(conf, n[0].typ): # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! result = false else: - result = true + if isInvalidReturnType(conf, n.typ, false): + result = false + else: + result = true proc inExceptBlockLen(p: BProc): int = for x in p.nestedTryStmts: diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 986708df7425d..f010b25c906b0 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -215,13 +215,17 @@ proc isObjLackingTypeField(typ: PType): bool {.inline.} = result = (typ.kind == tyObject) and ((tfFinal in typ.flags) and (typ[0] == nil) or isPureObject(typ)) -proc isInvalidReturnType(conf: ConfigRef; proctype: PType): bool = +proc isInvalidReturnType(conf: ConfigRef; typ: PType, isProc = true): bool = # Arrays and sets cannot be returned by a C procedure, because C is # such a poor programming language. # We exclude records with refs too. This enhances efficiency and # is necessary for proper code generation of assignments. - let rettype = proctype[0] - if rettype == nil or (proctype.callConv in {ccClosure, ccInline, ccNimCall} and + var rettype = typ + var isAllowedCall = true + if isProc: + rettype = rettype[0] + isAllowedCall = typ.callConv in {ccClosure, ccInline, ccNimCall} + if rettype == nil or (isAllowedCall and getSize(conf, rettype) > conf.target.floatSize*3): result = true else: From fc47e3dcd3e11d2c1b837b5164e1cfb2cc1bc91c Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 09:39:53 +0800 Subject: [PATCH 06/14] another try --- compiler/ccgstmts.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index d74632aaf2758..73d8a61bb0653 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -34,7 +34,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: result = false - elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.kind == tyProc and + elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractRange).kind == tyProc and isInvalidReturnType(conf, n[0].typ): # var v = f() # is transformed into: var v; f(addr v) From 8f0fd8ccbcee5c70905aa45ac035ea643cf60de4 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 09:41:03 +0800 Subject: [PATCH 07/14] typo --- compiler/ccgstmts.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 73d8a61bb0653..0e4689b156c98 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -34,7 +34,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: result = false - elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractRange).kind == tyProc and + elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc and isInvalidReturnType(conf, n[0].typ): # var v = f() # is transformed into: var v; f(addr v) From bee4a145563644d6cc92ca2f9edafb566928d7b5 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 11:15:46 +0800 Subject: [PATCH 08/14] try nkSym --- compiler/ccgstmts.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 0e4689b156c98..a50738dd0fe56 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -34,7 +34,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: result = false - elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc and + elif n.kind in nkCallKinds and n[0].kind == nkSym and n[0].typ.skipTypes(abstractInst).kind == tyProc and isInvalidReturnType(conf, n[0].typ): # var v = f() # is transformed into: var v; f(addr v) From d19c9a16d563c938d542e32885ddfb4ce2d76928 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 11:51:52 +0800 Subject: [PATCH 09/14] fit --- compiler/ccgstmts.nim | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index a50738dd0fe56..e1b6a95f75c9a 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -32,19 +32,16 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = "$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc]) proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = + let isProc = n.kind in nkCallKinds and n[0].kind == nkSym and n[0].typ.skipTypes(abstractInst).kind == tyProc if n.kind == nkEmpty: result = false - elif n.kind in nkCallKinds and n[0].kind == nkSym and n[0].typ.skipTypes(abstractInst).kind == tyProc and - isInvalidReturnType(conf, n[0].typ): + elif isInvalidReturnType(conf, n[0].typ, isProc): # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! result = false else: - if isInvalidReturnType(conf, n.typ, false): - result = false - else: - result = true + result = true proc inExceptBlockLen(p: BProc): int = for x in p.nestedTryStmts: From f506fa0479c991991fb5be45ae343a1dfe77d162 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 12:27:57 +0800 Subject: [PATCH 10/14] check --- compiler/ccgstmts.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index e1b6a95f75c9a..f985dc8af5721 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -32,7 +32,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = "$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc]) proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = - let isProc = n.kind in nkCallKinds and n[0].kind == nkSym and n[0].typ.skipTypes(abstractInst).kind == tyProc + let isProc = n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc if n.kind == nkEmpty: result = false elif isInvalidReturnType(conf, n[0].typ, isProc): From 335cc11ebdd241fa44787b747636dc32a50e4272 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 12:39:46 +0800 Subject: [PATCH 11/14] another --- compiler/ccgstmts.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index f985dc8af5721..adf89dcc2ab60 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -35,10 +35,12 @@ proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = let isProc = n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc if n.kind == nkEmpty: result = false - elif isInvalidReturnType(conf, n[0].typ, isProc): + elif isProc: + result = isInvalidReturnType(conf, n[0].typ, true): # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! + elif isInvalidReturnType(conf, n.typ, false): result = false else: result = true From f2741a7d0a67449798cd06e74a8274c53f1a76d0 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 13:16:38 +0800 Subject: [PATCH 12/14] little more --- compiler/ccgstmts.nim | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index adf89dcc2ab60..db4e7714ee144 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -32,11 +32,10 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = "$n\t#nimRegisterGlobalMarker($1);$n$n", [traverseProc]) proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = - let isProc = n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc if n.kind == nkEmpty: result = false - elif isProc: - result = isInvalidReturnType(conf, n[0].typ, true): + elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc: + result = isInvalidReturnType(conf, n[0].typ, true) # var v = f() # is transformed into: var v; f(addr v) # where 'f' **does not** initialize the result! From cf3b9658db95760fbce94ed75fb59969e7dbbae5 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 13:21:50 +0800 Subject: [PATCH 13/14] send --- compiler/ccgstmts.nim | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index db4e7714ee144..dd000a23d8069 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -35,10 +35,13 @@ proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: result = false elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc: - result = isInvalidReturnType(conf, n[0].typ, true) - # var v = f() - # is transformed into: var v; f(addr v) - # where 'f' **does not** initialize the result! + if isInvalidReturnType(conf, n[0].typ, true): + # var v = f() + # is transformed into: var v; f(addr v) + # where 'f' **does not** initialize the result! + result = false + else: + result = true elif isInvalidReturnType(conf, n.typ, false): result = false else: From 4c1d7e570bc8f65a81549d6c8a600ced98161f96 Mon Sep 17 00:00:00 2001 From: flywind Date: Fri, 28 Jan 2022 15:34:28 +0800 Subject: [PATCH 14/14] one more time --- compiler/ccgstmts.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index dd000a23d8069..58a6dd015c0a7 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -34,7 +34,7 @@ proc registerTraverseProc(p: BProc, v: PSym, traverseProc: Rope) = proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} = if n.kind == nkEmpty: result = false - elif n.kind in nkCallKinds and n[0] != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc: + elif n.kind in nkCallKinds and n[0] != nil and n[0].typ != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc: if isInvalidReturnType(conf, n[0].typ, true): # var v = f() # is transformed into: var v; f(addr v)