summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorClyybber <darkmine956@gmail.com>2021-06-16 16:40:22 +0200
committerGitHub <noreply@github.com>2021-06-16 16:40:22 +0200
commit13b94c0297806911cf317ff6169dba8595a0333d (patch)
tree9b46d161503b511120ce225c74e9fedf594ee2d6
parentc51680e7012bff32156623fad0996d62f7918222 (diff)
downloadNim-13b94c0297806911cf317ff6169dba8595a0333d.tar.gz
Fix doubly typed forward declarations (#18279)
* Add testcase

* Fix testcase

* Fix doubly typed forward decls

* Better fix
-rw-r--r--compiler/semstmts.nim7
-rw-r--r--tests/macros/tmacros_issues.nim22
2 files changed, 27 insertions, 2 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index d6ad7ab54..f29dc24ef 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1890,11 +1890,16 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   var (proto, comesFromShadowScope) =
       if isAnon: (nil, false)
       else: searchForProc(c, declarationScope, s)
-  if proto == nil and sfForward in s.flags:
+  if proto == nil and sfForward in s.flags and n[bodyPos].kind != nkEmpty:
     ## In cases such as a macro generating a proc with a gensymmed name we
     ## know `searchForProc` will not find it and sfForward will be set. In
     ## such scenarios the sym is shared between forward declaration and we
     ## can treat the `s` as the proto.
+    ## To differentiate between that happening and a macro just returning a
+    ## forward declaration that has been typed before we check if the body
+    ## is not empty. This has the sideeffect of allowing multiple forward
+    ## declarations if they share the same sym.
+    ## See the "doubly-typed forward decls" case in tmacros_issues.nim
     proto = s
   let hasProto = proto != nil
 
diff --git a/tests/macros/tmacros_issues.nim b/tests/macros/tmacros_issues.nim
index a964f46ba..a81c51658 100644
--- a/tests/macros/tmacros_issues.nim
+++ b/tests/macros/tmacros_issues.nim
@@ -484,6 +484,26 @@ func expMin: float {.aadMin.} = 1
 echo expMin()
 
 
+# doubly-typed forward decls
+macro noop(x: typed) = x
+noop:
+  proc cally() = discard
+
+cally()
+
+noop:
+  proc barry()
+
+proc barry() = discard
+
+# some more:
+proc barry2() {.noop.}
+proc barry2() = discard
+
+proc barry3() {.noop.}
+proc barry3() {.noop.} = discard
+
+
 # issue #15389
 block double_sem_for_procs:
 
@@ -498,4 +518,4 @@ block double_sem_for_procs:
       return x1 + 1.0
     result = 10.0
 
-  discard exp(5.0)
\ No newline at end of file
+  discard exp(5.0)