diff options
author | ringabout <43030857+ringabout@users.noreply.github.com> | 2024-07-17 11:17:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-17 05:17:52 +0200 |
commit | fe48de44067c2d68d764f7476738d6fd3aee38a7 (patch) | |
tree | 1d0d208064596e3999e2f6f755f7aec53da44319 | |
parent | cd946084abdf3ab64b2540e2f29c1034ae1511e5 (diff) | |
download | Nim-fe48de44067c2d68d764f7476738d6fd3aee38a7.tar.gz |
fixes #23837; cursor now processes distinct types with a destructor (#23845)
fixes #23837
-rw-r--r-- | compiler/varpartitions.nim | 13 | ||||
-rw-r--r-- | tests/destructor/t23837.nim | 51 |
2 files changed, 62 insertions, 2 deletions
diff --git a/compiler/varpartitions.nim b/compiler/varpartitions.nim index 6b2f677a7..84cf3265c 100644 --- a/compiler/varpartitions.nim +++ b/compiler/varpartitions.nim @@ -106,6 +106,7 @@ type unanalysableMutation: bool inAsgnSource, inConstructor, inNoSideEffectSection: int inConditional, inLoop: int + inConvHasDestructor: int owner: PSym g: ModuleGraph @@ -427,9 +428,17 @@ proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) = # primitive literals including the empty are harmless: discard - of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkCast, nkConv: + of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv, nkCast: destMightOwn(c, dest, n[1]) + of nkConv: + if hasDestructor(n.typ): + inc c.inConvHasDestructor + destMightOwn(c, dest, n[1]) + dec c.inConvHasDestructor + else: + destMightOwn(c, dest, n[1]) + of nkIfStmt, nkIfExpr: for i in 0..<n.len: destMightOwn(c, dest, n[i].lastSon) @@ -481,7 +490,7 @@ proc destMightOwn(c: var Partitions; dest: var VarIndex; n: PNode) = of nkCallKinds: if n.typ != nil: - if hasDestructor(n.typ): + if hasDestructor(n.typ) or c.inConvHasDestructor > 0: # calls do construct, what we construct must be destroyed, # so dest cannot be a cursor: dest.flags.incl ownsData diff --git a/tests/destructor/t23837.nim b/tests/destructor/t23837.nim new file mode 100644 index 000000000..e219dd6b5 --- /dev/null +++ b/tests/destructor/t23837.nim @@ -0,0 +1,51 @@ +discard """ + output: ''' +Deallocating OwnedString +HelloWorld +''' + matrix: "--cursorinference:on; --cursorinference:off" + target: "c" +""" + +# bug #23837 +{. + emit: [ + """ +#include <stdlib.h> +#include <string.h> +char *allocCString() { + char *result = (char *) malloc(10 + 1); + strcpy(result, "HelloWorld"); + return result; +} + +""" + ] +.} + +proc rawWrapper(): cstring {.importc: "allocCString", cdecl.} +proc free(p: pointer) {.importc: "free", cdecl.} + +# ------------------------- + +type OwnedString = distinct cstring + +proc `=destroy`(s: OwnedString) = + free(cstring s) + echo "Deallocating OwnedString" + +func `$`(s: OwnedString): string {.borrow.} + +proc leakyWrapper(): string = + let ostring = rawWrapper().OwnedString + $ostring + +# ------------------------- + +proc main() = + # destructor not called - definitely lost: 11 bytes in 1 blocks + # doesn't leak with --cursorInference:off + let s = leakyWrapper() + echo s + +main() \ No newline at end of file |