process non-language pragma nodes in generics (#24254)

fixes #18649, refs #24183

Same as in #24183 for templates, we now process pragma nodes in generics
so that macro symbols are captured and the pragma arguments are checked,
but ignoring language pragma keywords.

A difference is that we cannot process call nodes as is, we have to
process their children individually so that the early untyped
macro/template instantiation in generics does not kick in.

(cherry picked from commit d72b848d17)
This commit is contained in:
metagn
2024-10-08 00:18:45 +03:00
committed by narimiran
parent 336549c49d
commit b8efee444c
4 changed files with 37 additions and 1 deletions

View File

@@ -616,7 +616,24 @@ proc semGenericStmt(c: PContext, n: PNode,
let bodyFlags = if n.kind == nkTemplateDef: flags + {withinMixin} else: flags
n[bodyPos] = semGenericStmtScope(c, body, bodyFlags, ctx)
closeScope(c)
of nkPragma, nkPragmaExpr: discard
of nkPragmaExpr:
result[1] = semGenericStmt(c, n[1], flags, ctx)
of nkPragma:
for i in 0 ..< n.len:
let x = n[i]
let prag = whichPragma(x)
if x.kind in nkPragmaCallKinds:
# process each child individually to prevent untyped macros/templates
# from instantiating
# if pragma is language-level pragma, skip name node:
let start = ord(prag != wInvalid)
for j in start ..< x.len:
# treat as mixin context for user pragmas & macro args
x[j] = semGenericStmt(c, x[j], flags+{withinMixin}, ctx)
elif prag == wInvalid:
# only sem if not a language-level pragma
# treat as mixin context for user pragmas & macro args
result[i] = semGenericStmt(c, x, flags+{withinMixin}, ctx)
of nkExprColonExpr, nkExprEqExpr:
checkMinSonsLen(n, 2, c.config)
result[1] = semGenericStmt(c, n[1], flags, ctx)

View File

@@ -0,0 +1,3 @@
macro aMacro*(u:untyped):untyped =
echo "in macro"
result = u

View File

@@ -0,0 +1,6 @@
import mpragma1
proc p*[T]() =
proc inner() {.aMacro.} =
discard
inner()
discard

View File

@@ -0,0 +1,10 @@
discard """
nimout: '''
in macro
'''
"""
# issue #18649
import mpragma2
p[string]()