summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semexprs.nim6
-rw-r--r--tests/template/tdefined_overload.nim46
2 files changed, 48 insertions, 4 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 92b9c365a..1296bddaa 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1613,10 +1613,8 @@ proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
   # we replace this node by a 'true' or 'false' node:
   result = newIntNode(nkIntLit, 0)
   if not onlyCurrentScope and considerQuotedIdent(c.config, n[0], n).s == "defined":
-    if n.sons[1].kind != nkIdent:
-      localError(c.config, n.info, "obsolete usage of 'defined', use 'declared' instead")
-    elif isDefined(c.config, n.sons[1].ident.s):
-      result.intVal = 1
+    let d = considerQuotedIdent(c.config, n[1], n)
+    result.intVal = ord isDefined(c.config, d.s)
   elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
     result.intVal = 1
   result.info = n.info
diff --git a/tests/template/tdefined_overload.nim b/tests/template/tdefined_overload.nim
new file mode 100644
index 000000000..bcc83e414
--- /dev/null
+++ b/tests/template/tdefined_overload.nim
@@ -0,0 +1,46 @@
+discard """
+  output: "Valid and not defined"
+"""
+# test for issue #7997
+# checking for `when not defined` in a template for some compile time symbol
+# results in a compilation error of:
+# Error: obsolete usage of 'defined', use 'declared' instead
+# if the symbol is 'overloaded' by some variable or procedure, because in
+# that case the argument of `defined` is of kind `nkSym` instead of `nkIdent`
+# (for which was checked in `semexprs.semDefined`).
+
+block:
+  # check whether a proc with the same name as the argument to `defined`
+  # compiles
+  proc overloaded() =
+    discard
+
+  template definedCheck(): untyped =
+    when not defined(overloaded): true
+    else: false
+  doAssert definedCheck == true
+
+block:
+  # check whether a variable with the same name as the argument to `defined`
+  # compiles
+  var overloaded: int
+
+  template definedCheck(): untyped =
+    when not defined(overloaded): true
+    else: false
+  doAssert definedCheck == true
+
+block:
+  # check whether a non overloaded when check still works properly
+  when not defined(validIdentifier):
+    echo "Valid and not defined"
+
+block:
+  # now check that invalid identifiers cause a compilation error
+  # by using reject template.
+  template reject(b) =
+    static: doAssert(not compiles(b))
+
+  reject:
+    when defined(123):
+      echo "Invalid identifier! Will not be echoed"