summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2021-08-11 03:17:17 -0700
committerGitHub <noreply@github.com>2021-08-11 12:17:17 +0200
commit6c1bd4bb1cb7a6af38b5929fe02b069b03e39db4 (patch)
tree526b758f8fb41d6e3d86c6f71ae1018ed6bd2529 /compiler
parent854006575498704c42b5ac465fdc74c3efdb5b97 (diff)
downloadNim-6c1bd4bb1cb7a6af38b5929fe02b069b03e39db4.tar.gz
fix: `var a{.foo.} = expr` inside templates (refs #15920) (except when `foo` is overloaded) (#13869)
* fix: `var a{.foo.} = expr` inside templates
* add test
* improve tdecls test
* improve tests
* add failing test
* PRTEMP
* fixup
Diffstat (limited to 'compiler')
-rw-r--r--compiler/semstmts.nim35
-rw-r--r--compiler/semtempl.nim15
2 files changed, 32 insertions, 18 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index cc09291c5..14dc89781 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -453,23 +453,29 @@ proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode =
       return nil
     let nodePragma = b[1][0]
     # see: `singlePragma`
-    if nodePragma.kind notin {nkIdent, nkAccQuoted}:
-      return nil
-    let ident = considerQuotedIdent(c, nodePragma)
-    var userPragma = strTableGet(c.userPragmas, ident)
-    if userPragma != nil: return nil
-
-    let w = nodePragma.whichPragma
-    if n.kind == nkVarSection and w in varPragmas or
-      n.kind == nkLetSection and w in letPragmas or
-      n.kind == nkConstSection and w in constPragmas:
-      return nil
 
     var amb = false
-    let sym = searchInScopes(c, ident, amb)
-    # XXX what if amb is true?
-    if sym == nil or sfCustomPragma in sym.flags: return nil
+    var sym: PSym = nil
+    case nodePragma.kind
+    of nkIdent, nkAccQuoted:
+      let ident = considerQuotedIdent(c, nodePragma)
+      var userPragma = strTableGet(c.userPragmas, ident)
+      if userPragma != nil: return nil
+      let w = nodePragma.whichPragma
+      if n.kind == nkVarSection and w in varPragmas or
+        n.kind == nkLetSection and w in letPragmas or
+        n.kind == nkConstSection and w in constPragmas:
+        return nil
+      sym = searchInScopes(c, ident, amb)
+      # XXX what if amb is true?
+      # CHECKME: should that test also apply to `nkSym` case?
+      if sym == nil or sfCustomPragma in sym.flags: return nil
+    of nkSym:
+      sym = nodePragma.sym
+    else:
+      return nil
       # skip if not in scope; skip `template myAttr() {.pragma.}`
+
     let lhs = b[0]
     let clash = strTableGet(c.currentScope.symbols, lhs.ident)
     if clash != nil:
@@ -477,7 +483,6 @@ proc semLowerLetVarCustomPragma(c: PContext, a: PNode, n: PNode): PNode =
       wrongRedefinition(c, lhs.info, lhs.ident.s, clash.info)
 
     result = newTree(nkCall)
-    doAssert nodePragma.kind in {nkIdent, nkAccQuoted}, $nodePragma.kind
     result.add nodePragma
     result.add lhs
     if a[1].kind != nkEmpty:
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index a2b0f99ba..2636784af 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -208,9 +208,18 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
     if (n.kind == nkPragmaExpr and n.len >= 2 and n[1].kind == nkPragma):
       let pragmaNode = n[1]
       for i in 0..<pragmaNode.len:
-        openScope(c)
-        pragmaNode[i] = semTemplBody(c, pragmaNode[i])
-        closeScope(c)
+        let ni = pragmaNode[i]
+        # see D20210801T100514
+        var found = false
+        if ni.kind == nkIdent:
+          for a in templatePragmas:
+            if ni.ident == getIdent(c.c.cache, $a):
+              found = true
+              break
+        if not found:
+          openScope(c)
+          pragmaNode[i] = semTemplBody(c, pragmaNode[i])
+          closeScope(c)
     let ident = getIdentNode(c, n)
     if not isTemplParam(c, ident):
       if n.kind != nkSym: