summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sempass2.nim15
-rw-r--r--tests/effects/tgcsafe2.nim12
2 files changed, 15 insertions, 12 deletions
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 9ce317f80..e9a1160e5 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -19,18 +19,6 @@ when defined(useDfa):
 #
 # * effect+exception tracking
 # * "usage before definition" checking
-# * checks for invalid usages of compiletime magics (not implemented)
-# * checks for invalid usages of NimNode (not implemented)
-# * later: will do an escape analysis for closures at least
-
-# Predefined effects:
-#   io, time (time dependent), gc (performs GC'ed allocation), exceptions,
-#   side effect (accesses global), store (stores into *type*),
-#   store_unknown (performs some store) --> store(any)|store(x)
-#   load (loads from *type*), recursive (recursive call), unsafe,
-#   endless (has endless loops), --> user effects are defined over *patterns*
-#   --> a TR macro can annotate the proc with user defined annotations
-#   --> the effect system can access these
 
 # ------------------------ exception and tag tracking -------------------------
 
@@ -593,6 +581,9 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
   if paramType != nil and paramType.kind == tyVar:
     if n.kind == nkSym and isLocalVar(tracked, n.sym):
       makeVolatile(tracked, n.sym)
+  if paramType != nil and paramType.kind == tyProc and tfGcSafe in paramType.flags:
+    if tfGcSafe notin a.typ.flags and not tracked.inEnforcedGcSafe:
+      localError(n.info, $n & " is not GC safe")
   notNilCheck(tracked, n, paramType)
 
 proc breaksBlock(n: PNode): bool =
diff --git a/tests/effects/tgcsafe2.nim b/tests/effects/tgcsafe2.nim
new file mode 100644
index 000000000..dbc4540c4
--- /dev/null
+++ b/tests/effects/tgcsafe2.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: ''' (proc (s: string) = res &= &(s, "abc"), nil) is not GC safe'''
+  line: 11
+"""
+#5620
+var res = ""
+
+proc takeCallback(foo: (proc(s: string) {.gcsafe.})) =
+  foo "string"
+
+takeCallback(proc (s: string) =
+  res &= s & "abc")