summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBuldram <buldram@proton.me>2024-07-24 02:13:55 -0400
committerGitHub <noreply@github.com>2024-07-24 08:13:55 +0200
commit925dc5c1319bce935593cc12380feec1538e2ce5 (patch)
tree3195c47235a02847a8e8828ed45f463510d201b9
parent0db742df7cd20efd030d7b20fe1e523c06325efa (diff)
downloadNim-925dc5c1319bce935593cc12380feec1538e2ce5.tar.gz
fixes #19171; have `openArray` converted from `ptr UncheckedArray` be mutable (#23882)
Makes `toOpenArray(x: ptr UncheckedArray)` always return a `var
openArray` regardless of if `x` is mutable.
-rw-r--r--compiler/parampatterns.nim11
-rw-r--r--tests/openarray/tuncheckedarray.nim19
2 files changed, 28 insertions, 2 deletions
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index 84c2980c4..b9d84f7eb 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -283,8 +283,15 @@ proc isAssignable*(owner: PSym, n: PNode): TAssignableResult =
   of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
     result = isAssignable(owner, n[0])
   of nkCallKinds:
-    # builtin slice keeps lvalue-ness:
-    if getMagic(n) in {mArrGet, mSlice}:
+    let m = getMagic(n)
+    if m == mSlice:
+      # builtin slice keeps l-value-ness
+      # except for pointers because slice dereferences
+      if n[1].typ.kind == tyPtr:
+        result = arLValue
+      else:
+        result = isAssignable(owner, n[1])
+    elif m == mArrGet:
       result = isAssignable(owner, n[1])
     elif n.typ != nil:
       case n.typ.kind
diff --git a/tests/openarray/tuncheckedarray.nim b/tests/openarray/tuncheckedarray.nim
new file mode 100644
index 000000000..c8ca9d2d4
--- /dev/null
+++ b/tests/openarray/tuncheckedarray.nim
@@ -0,0 +1,19 @@
+discard """
+  exitcode: 0
+  targets: "c cpp"
+"""
+
+proc main =
+  block: # issue 19171
+    var a = ['A']
+    proc mutB(x: var openArray[char]) =
+      x[0] = 'B'
+    mutB(toOpenArray(cast[ptr UncheckedArray[char]](addr a), 0, 0))
+    doAssert a[0] == 'B'
+    proc mutC(x: var openArray[char]; c: char) =
+      x[0] = c
+    let p = cast[ptr UncheckedArray[char]](addr a)
+    mutC(toOpenArray(p, 0, 0), 'C')
+    doAssert p[0] == 'C'
+
+main()