summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJuan M Gómez <info@jmgomez.me>2023-07-29 17:05:31 +0100
committerGitHub <noreply@github.com>2023-07-29 18:05:31 +0200
commite70992d2910e418e3e6d51ae097558ca123e354e (patch)
treeb317085ac376df0b8e7ba4b84410a6e8ff23d46b
parentf0f3904ff04a46bae6f876b0326162354466f415 (diff)
downloadNim-e70992d2910e418e3e6d51ae097558ca123e354e.tar.gz
fixes an issue where byref wasnt properly handled when using it in a generic param (#22337)
* fixes an issue where byref wasnt properly handled when using it in a generic param

* removes unreachable check
-rw-r--r--compiler/ccgtypes.nim13
-rw-r--r--tests/cpp/tpassbypragmas.nim27
2 files changed, 37 insertions, 3 deletions
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index e4a0fe84b..2aa92c130 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -18,6 +18,7 @@ type
   TypeDescKind = enum
     dkParam #skParam
     dkRefParam #param passed by ref when {.byref.} is used. Cpp only. C goes straight to dkParam and is handled as a regular pointer
+    dkRefGenericParam #param passed by ref when {.byref.} is used that is also a generic. Cpp only. C goes straight to dkParam and is handled as a regular pointer
     dkVar #skVar
     dkField #skField
     dkResult #skResult
@@ -519,7 +520,10 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, params: var
     var param = t.n[i].sym
     var descKind = dkParam
     if optByRef in param.options:
-      descKind = dkRefParam
+      if param.typ.kind == tyGenericInst:
+        descKind = dkRefGenericParam
+      else:
+        descKind = dkRefParam
     var typ, name : string
     fillParamName(m, param)
     fillLoc(param.loc, locParam, t.n[i],
@@ -570,7 +574,10 @@ proc genProcParams(m: BModule; t: PType, rettype, params: var Rope,
     var param = t.n[i].sym
     var descKind = dkParam
     if m.config.backend == backendCpp and optByRef in param.options:
-      descKind = dkRefParam
+      if param.typ.kind == tyGenericInst:
+        descKind = dkRefGenericParam
+      else:
+        descKind = dkRefParam
     if isCompileTimeOnly(param.typ): continue
     if params != "(": params.add(", ")
     fillParamName(m, param)
@@ -873,7 +880,7 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
   result = getTypePre(m, t, sig)
   if result != "" and t.kind != tyOpenArray:
     excl(check, t.id)
-    if kind == dkRefParam:
+    if kind == dkRefParam or kind == dkRefGenericParam and origTyp.kind == tyGenericInst:
       result.add("&")
     return
   case t.kind
diff --git a/tests/cpp/tpassbypragmas.nim b/tests/cpp/tpassbypragmas.nim
new file mode 100644
index 000000000..f4301656a
--- /dev/null
+++ b/tests/cpp/tpassbypragmas.nim
@@ -0,0 +1,27 @@
+discard """
+  targets: "cpp"
+  cmd: "nim cpp $file"
+"""
+{.emit:"""/*TYPESECTION*/
+
+  template<typename T>
+  struct Box {
+      T first;
+  };
+  struct Foo {
+  void test(void (*func)(Box<Foo>& another)){
+
+    };
+  };
+""".}
+
+type 
+  Foo {.importcpp.} = object
+  Box[T] {.importcpp:"Box<'0>".} = object
+    first: T
+
+proc test(self: Foo, fn: proc(another {.byref.}: Box[Foo]) {.cdecl.}) {.importcpp.}
+
+proc fn(another {.byref.} : Box[Foo]) {.cdecl.} = discard
+
+Foo().test(fn)
\ No newline at end of file