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
This commit is contained in:
Timothee Cour 2021-08-11 03:17:17 -07:00 • committed by GitHub
commit 6c1bd4bb1c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 20 deletions

View file

@ -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:

View file

@ -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: