mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-10 00:58:10 +00:00
move now uses its declaration for overridden =wasMoved
This commit is contained in:
@@ -2842,6 +2842,9 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
var op = getAttachedOp(p.module.g.graph, n.typ, attachedWasMoved)
|
||||
if op == nil:
|
||||
resetLoc(p, a)
|
||||
elif sfOverridden in op.flags:
|
||||
internalError(p.config, n.info,
|
||||
"overridden =wasMoved should be emitted by instantiated move")
|
||||
else:
|
||||
var b = initLocExpr(p, newSymNode(op))
|
||||
case skipTypes(a.t, abstractVar+{tyStatic}).kind
|
||||
|
||||
@@ -853,6 +853,12 @@ proc compactVoidArgs(n: PNode): PNode =
|
||||
if n[i] != nil:
|
||||
result.add n[i]
|
||||
|
||||
proc hasOverriddenWasMoved(c: PContext; call: PNode): bool =
|
||||
if call.len != 2 or call[1].typ == nil: return false
|
||||
let typ = call[1].typ.skipTypes({tyAlias, tyVar, tySink})
|
||||
let op = getAttachedOp(c.graph, typ, attachedWasMoved)
|
||||
result = op != nil and sfOverridden in op.flags
|
||||
|
||||
proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
n: PNode, flags: TExprFlags;
|
||||
expectedType: PType = nil): PNode =
|
||||
@@ -880,6 +886,13 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
else:
|
||||
c.inheritBindings(x, expectedType)
|
||||
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||
if x.calleeSym.magic == mMove and hasOverriddenWasMoved(c, x.call):
|
||||
# Let system.move[T]'s instantiated body perform the overridable
|
||||
# =wasMoved call. The mMove codegen path stays the compact default
|
||||
# implementation for non-overridden hooks.
|
||||
ensureMutable finalCallee
|
||||
finalCallee.magic = mNone
|
||||
setOwner(finalCallee, c.module)
|
||||
else:
|
||||
# For macros and templates, the resolved generic params
|
||||
# are added as normal params.
|
||||
|
||||
@@ -166,7 +166,7 @@ proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.}
|
||||
## it was "moved" and to signify its destructor should do nothing and
|
||||
## ideally be optimized away.
|
||||
|
||||
proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
|
||||
proc move*[T](x: var T): T {.magic: "Move", noSideEffect, nodestroy.} =
|
||||
result = x
|
||||
{.cast(raises: []), cast(tags: []).}:
|
||||
`=wasMoved`(x)
|
||||
|
||||
30
tests/ccgbugs2/t25800.nim
Normal file
30
tests/ccgbugs2/t25800.nim
Normal file
@@ -0,0 +1,30 @@
|
||||
discard """
|
||||
cmd: "nim cpp $file"
|
||||
action: "compile"
|
||||
"""
|
||||
|
||||
# Bug Report 1: {.importcpp.} on =wasMoved generates invalid preprocessor directive #.
|
||||
{.emit: """/*TYPESECTION*/
|
||||
struct CppRef {
|
||||
int* data;
|
||||
CppRef() : data(new int(42)) {}
|
||||
~CppRef() { delete data; data = nullptr; }
|
||||
void reset() { delete data; data = nullptr; }
|
||||
};
|
||||
""".}
|
||||
|
||||
type CppRef* {.importcpp, bycopy, noInit.} = object
|
||||
|
||||
proc `=destroy`(x: var CppRef) {.importcpp: "#.~CppRef()".}
|
||||
proc `=wasMoved`(x: var CppRef) {.importcpp: "#.reset()".}
|
||||
proc `=copy`(dest: var CppRef; src: CppRef) {.importcpp: "dest = src".}
|
||||
proc `=sink`(dest: var CppRef; src: CppRef) {.importcpp: "dest = std::move(src)".}
|
||||
|
||||
# This triggers =wasMoved when passing to sink parameter
|
||||
proc consume(x: sink CppRef) = discard
|
||||
|
||||
proc test() =
|
||||
var x: CppRef
|
||||
consume(move(x)) # =wasMoved MUST be called here after the move
|
||||
|
||||
test()
|
||||
Reference in New Issue
Block a user