Skip to content

Commit

Permalink
process non-language pragma nodes in generics (#24254)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
metagn authored Oct 7, 2024
1 parent d6633ae commit d72b848
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 1 deletion.
19 changes: 18 additions & 1 deletion compiler/semgnrc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions tests/generics/mpragma1.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
macro aMacro*(u:untyped):untyped =
echo "in macro"
result = u
6 changes: 6 additions & 0 deletions tests/generics/mpragma2.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import mpragma1
proc p*[T]() =
proc inner() {.aMacro.} =
discard
inner()
discard
10 changes: 10 additions & 0 deletions tests/generics/tpragma.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
discard """
nimout: '''
in macro
'''
"""

# issue #18649

import mpragma2
p[string]()

0 comments on commit d72b848

Please sign in to comment.