Skip to content

Commit d72b848

Browse files
authored
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.
1 parent d6633ae commit d72b848

File tree

4 files changed

+37
-1
lines changed

4 files changed

+37
-1
lines changed

compiler/semgnrc.nim

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,24 @@ proc semGenericStmt(c: PContext, n: PNode,
616616
let bodyFlags = if n.kind == nkTemplateDef: flags + {withinMixin} else: flags
617617
n[bodyPos] = semGenericStmtScope(c, body, bodyFlags, ctx)
618618
closeScope(c)
619-
of nkPragma, nkPragmaExpr: discard
619+
of nkPragmaExpr:
620+
result[1] = semGenericStmt(c, n[1], flags, ctx)
621+
of nkPragma:
622+
for i in 0 ..< n.len:
623+
let x = n[i]
624+
let prag = whichPragma(x)
625+
if x.kind in nkPragmaCallKinds:
626+
# process each child individually to prevent untyped macros/templates
627+
# from instantiating
628+
# if pragma is language-level pragma, skip name node:
629+
let start = ord(prag != wInvalid)
630+
for j in start ..< x.len:
631+
# treat as mixin context for user pragmas & macro args
632+
x[j] = semGenericStmt(c, x[j], flags+{withinMixin}, ctx)
633+
elif prag == wInvalid:
634+
# only sem if not a language-level pragma
635+
# treat as mixin context for user pragmas & macro args
636+
result[i] = semGenericStmt(c, x, flags+{withinMixin}, ctx)
620637
of nkExprColonExpr, nkExprEqExpr:
621638
checkMinSonsLen(n, 2, c.config)
622639
result[1] = semGenericStmt(c, n[1], flags, ctx)

tests/generics/mpragma1.nim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
macro aMacro*(u:untyped):untyped =
2+
echo "in macro"
3+
result = u

tests/generics/mpragma2.nim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import mpragma1
2+
proc p*[T]() =
3+
proc inner() {.aMacro.} =
4+
discard
5+
inner()
6+
discard

tests/generics/tpragma.nim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
discard """
2+
nimout: '''
3+
in macro
4+
'''
5+
"""
6+
7+
# issue #18649
8+
9+
import mpragma2
10+
p[string]()

0 commit comments

Comments
 (0)