summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBung <crc32@qq.com>2023-01-27 00:50:44 -0800
committerGitHub <noreply@github.com>2023-01-27 09:50:44 +0100
commita7bae919adb952362cb53206140872d2b7424b47 (patch)
treed72beb7e1a02e9ed7bd4308b363f27e4e08fb4a3
parent7031ea65cd220360b8e9f566fd28f01bc0bf53c4 (diff)
downloadNim-a7bae919adb952362cb53206140872d2b7424b47.tar.gz
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
-rw-r--r--compiler/cgen.nim4
-rw-r--r--compiler/semstmts.nim6
-rw-r--r--lib/pure/concurrency/atomics.nim2
-rw-r--r--tests/cpp/t13093.nim24
-rw-r--r--tests/cpp/t17982.nim20
5 files changed, 54 insertions, 2 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 5bf9400c5..869c1bfdd 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -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:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c7e48db4c..12a346f63 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -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:
diff --git a/lib/pure/concurrency/atomics.nim b/lib/pure/concurrency/atomics.nim
index c7b881bc5..49204bd4d 100644
--- a/lib/pure/concurrency/atomics.nim
+++ b/lib/pure/concurrency/atomics.nim
@@ -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
 
diff --git a/tests/cpp/t13093.nim b/tests/cpp/t13093.nim
new file mode 100644
index 000000000..17c730d16
--- /dev/null
+++ b/tests/cpp/t13093.nim
@@ -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()
diff --git a/tests/cpp/t17982.nim b/tests/cpp/t17982.nim
new file mode 100644
index 000000000..5413f06ff
--- /dev/null
+++ b/tests/cpp/t17982.nim
@@ -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