mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 20:17:42 +00:00
* fix: `var a{.foo.} = expr` inside templates
* add test
* improve tdecls test
* improve tests
* add failing test
* PRTEMP
* fixup
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -10,3 +10,55 @@ block:
|
||||
static: doAssert defined(tpragmas_misc_def)
|
||||
{.undef(tpragmas_misc_def).}
|
||||
static: doAssert not defined(tpragmas_misc_def)
|
||||
|
||||
block: # (partial fix) bug #15920
|
||||
block: # var template pragmas don't work in templates
|
||||
template foo(lhs, typ, expr) =
|
||||
let lhs = expr
|
||||
proc fun1()=
|
||||
let a {.foo.} = 1
|
||||
template fun2()=
|
||||
let a {.foo.} = 1
|
||||
fun1() # ok
|
||||
fun2() # WAS bug
|
||||
|
||||
template foo2() = discard # distractor (template or other symbol kind)
|
||||
block:
|
||||
template foo2(lhs, typ, expr) =
|
||||
let lhs = expr
|
||||
proc fun1()=
|
||||
let a {.foo2.} = 1
|
||||
template fun2()=
|
||||
let a {.foo2.} = 1
|
||||
fun1() # ok
|
||||
when false: # bug: Error: invalid pragma: foo2
|
||||
fun2()
|
||||
|
||||
block: # proc template pragmas don't work in templates
|
||||
# adapted from $nim/lib/std/private/since.nim
|
||||
# case without overload
|
||||
template since3(version: (int, int), body: untyped) {.dirty.} =
|
||||
when (NimMajor, NimMinor) >= version:
|
||||
body
|
||||
when false: # bug
|
||||
template fun3(): int {.since3: (1, 3).} = 12
|
||||
|
||||
block: # ditto, w
|
||||
# case with overload
|
||||
template since2(version: (int, int), body: untyped) {.dirty.} =
|
||||
when (NimMajor, NimMinor) >= version:
|
||||
body
|
||||
template since2(version: (int, int, int), body: untyped) {.dirty.} =
|
||||
when (NimMajor, NimMinor, NimPatch) >= version:
|
||||
body
|
||||
when false: # bug
|
||||
template fun3(): int {.since2: (1, 3).} = 12
|
||||
|
||||
when true: # D20210801T100514:here
|
||||
from macros import genSym
|
||||
block:
|
||||
template fn() =
|
||||
var ret {.gensym.}: int # must special case template pragmas so it doesn't get confused
|
||||
discard ret
|
||||
fn()
|
||||
static: discard genSym()
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
discard """
|
||||
targets: "c cpp js"
|
||||
"""
|
||||
|
||||
import std/decls
|
||||
|
||||
block:
|
||||
template fun() =
|
||||
var s = @[10,11,12]
|
||||
var a {.byaddr.} = s[0]
|
||||
a+=100
|
||||
@@ -34,6 +38,13 @@ block:
|
||||
doAssert compiles(block:
|
||||
var b2 {.byaddr.}: int = s[2])
|
||||
|
||||
proc fun2() = fun()
|
||||
fun()
|
||||
fun2()
|
||||
static: fun2()
|
||||
when false: # pending bug #13887
|
||||
static: fun()
|
||||
|
||||
## We can define custom pragmas in user code
|
||||
template byUnsafeAddr(lhs, typ, expr) =
|
||||
when typ is type(nil):
|
||||
@@ -68,3 +79,13 @@ block: # nkAccQuoted
|
||||
let a {.`cast`.} = s[0]
|
||||
doAssert a == "foo"
|
||||
doAssert a[0].unsafeAddr == s[0][0].unsafeAddr
|
||||
|
||||
block: # bug #15920
|
||||
template foo(lhs, typ, expr) =
|
||||
let lhs = expr
|
||||
proc fun1()=
|
||||
let a {.foo.} = 1
|
||||
template fun2()=
|
||||
let a {.foo.} = 1
|
||||
fun1() # ok
|
||||
fun2() # BUG
|
||||
|
||||
@@ -27,6 +27,6 @@ since (99, 3):
|
||||
doAssert false
|
||||
|
||||
when false:
|
||||
# pending https://github.com/timotheecour/Nim/issues/129
|
||||
# pending bug #15920
|
||||
# Error: cannot attach a custom pragma to 'fun3'
|
||||
template fun3(): int {.since: (1, 3).} = 12
|
||||
|
||||
Reference in New Issue
Block a user