Fix #13093 C++ Atomics: operator= is implicitly deleted because the default definition would be ill-formed (#21169)
* add test * fix #17982 Invalid C++ code generation when returning discardable var T * fix #13093 * cpp atomic good example * clearify the condition
This commit is contained in:
parent
7031ea65cd
commit
a7bae919ad
5 changed files with 54 additions and 2 deletions
|
|
@ -491,6 +491,10 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
|
||||||
nilLoc.r = rope("NIM_NIL")
|
nilLoc.r = rope("NIM_NIL")
|
||||||
genRefAssign(p, loc, nilLoc)
|
genRefAssign(p, loc, nilLoc)
|
||||||
else:
|
else:
|
||||||
|
if typ.kind == tyVar:
|
||||||
|
let tt = typ.skipTypes({tyVar})
|
||||||
|
if isImportedType(tt) and tfRequiresInit in tt.flags:
|
||||||
|
return
|
||||||
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
linefmt(p, cpsStmts, "$1 = ($2)0;$n", [rdLoc(loc),
|
||||||
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
|
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -717,7 +717,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
tyUserTypeClassInst})
|
tyUserTypeClassInst})
|
||||||
if actualType.kind in {tyObject, tyDistinct} and
|
if actualType.kind in {tyObject, tyDistinct} and
|
||||||
actualType.requiresInit:
|
actualType.requiresInit:
|
||||||
defaultConstructionError(c, v.typ, v.info)
|
# imported type use requiresInit pragma prevent implicit initialization
|
||||||
|
if (tfRequiresInit in actualType.flags and sfImportc in actualType.sym.flags):
|
||||||
|
discard
|
||||||
|
else:
|
||||||
|
defaultConstructionError(c, v.typ, v.info)
|
||||||
else:
|
else:
|
||||||
checkNilable(c, v)
|
checkNilable(c, v)
|
||||||
# allow let to not be initialised if imported from C:
|
# allow let to not be initialised if imported from C:
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ when defined(cpp) or defined(nimdoc):
|
||||||
## with other moSequentiallyConsistent operations.
|
## with other moSequentiallyConsistent operations.
|
||||||
|
|
||||||
type
|
type
|
||||||
Atomic*[T] {.importcpp: "std::atomic", completeStruct.} = object
|
Atomic*[T] {.importcpp: "std::atomic", completeStruct, requiresInit.} = object
|
||||||
## An atomic object with underlying type `T`.
|
## An atomic object with underlying type `T`.
|
||||||
raw: T
|
raw: T
|
||||||
|
|
||||||
|
|
|
||||||
24
tests/cpp/t13093.nim
Normal file
24
tests/cpp/t13093.nim
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
discard """
|
||||||
|
targets: "cpp"
|
||||||
|
action: reject
|
||||||
|
errormsg: "The PledgeObj type requires the following fields to be initialized: refCount"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import atomics
|
||||||
|
|
||||||
|
type
|
||||||
|
Pledge* = object
|
||||||
|
p: PledgePtr
|
||||||
|
|
||||||
|
PledgePtr = ptr PledgeObj
|
||||||
|
PledgeObj = object
|
||||||
|
refCount: Atomic[int32]
|
||||||
|
|
||||||
|
proc main() =
|
||||||
|
var pledge: Pledge
|
||||||
|
pledge.p = createShared(PledgeObj)
|
||||||
|
let tmp = PledgeObj() # <---- not allowed: atomics are not copyable
|
||||||
|
|
||||||
|
pledge.p[] = tmp
|
||||||
|
|
||||||
|
main()
|
||||||
20
tests/cpp/t17982.nim
Normal file
20
tests/cpp/t17982.nim
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
discard """
|
||||||
|
targets: "cpp"
|
||||||
|
action: "compile"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
String* {.importcpp: "std::string", header: "string".} = object
|
||||||
|
|
||||||
|
proc initString*(): String
|
||||||
|
{.importcpp: "std::string()", header: "string".}
|
||||||
|
|
||||||
|
proc append*(this: var String, str: String): String
|
||||||
|
# bug seems to trigger when `#`, `@`, or `$1` is used inside `importcpp`
|
||||||
|
{.importcpp: "#.append(@)", header: "string", discardable.} # <- changed from `importcpp: "append"`
|
||||||
|
|
||||||
|
var
|
||||||
|
s1 = initString()
|
||||||
|
s2 = initString()
|
||||||
|
|
||||||
|
s1.append s2
|
||||||
Loading…
Add table
Add a link
Reference in a new issue