Skip to content

Commit

Permalink
Fix nim-lang#13093 C++ Atomics: operator= is implicitly deleted becau…
Browse files Browse the repository at this point in the history
…se the default definition would be ill-formed (nim-lang#21169)

* add test

* fix nim-lang#17982 Invalid C++ code generation when returning discardable var T

* fix nim-lang#13093

* cpp atomic good example

* clearify the condition
  • Loading branch information
bung87 authored and capocasa committed Mar 31, 2023
1 parent 326c1c7 commit 53aba6c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
4 changes: 4 additions & 0 deletions compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,10 @@ proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
nilLoc.r = rope("NIM_NIL")
genRefAssign(p, loc, nilLoc)
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),
getTypeDesc(p.module, typ, mapTypeChooser(loc))])
else:
Expand Down
6 changes: 5 additions & 1 deletion compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -717,7 +717,11 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
tyUserTypeClassInst})
if actualType.kind in {tyObject, tyDistinct} and
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:
checkNilable(c, v)
# allow let to not be initialised if imported from C:
Expand Down
2 changes: 1 addition & 1 deletion lib/pure/concurrency/atomics.nim
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ when defined(cpp) or defined(nimdoc):
## with other moSequentiallyConsistent operations.

type
Atomic*[T] {.importcpp: "std::atomic", completeStruct.} = object
Atomic*[T] {.importcpp: "std::atomic", completeStruct, requiresInit.} = object
## An atomic object with underlying type `T`.
raw: T

Expand Down
24 changes: 24 additions & 0 deletions tests/cpp/t13093.nim
Original file line number Diff line number Diff line change
@@ -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 changes: 20 additions & 0 deletions tests/cpp/t17982.nim
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 53aba6c

Please sign in to comment.