mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 18:34:43 +00:00
fixes #23837
This commit is contained in:
@@ -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
|
||||
|
||||
51
tests/destructor/t23837.nim
Normal file
51
tests/destructor/t23837.nim
Normal file
@@ -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()
|
||||
Reference in New Issue
Block a user