From b8efee444cbfb6c370fb68f52bbcf266ed2f65a8 Mon Sep 17 00:00:00 2001 From: metagn Date: Tue, 8 Oct 2024 00:18:45 +0300 Subject: [PATCH] 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 d72b848d1799191b4b5535336b3a708205374b31) --- compiler/semgnrc.nim | 19 ++++++++++++++++++- tests/generics/mpragma1.nim | 3 +++ tests/generics/mpragma2.nim | 6 ++++++ tests/generics/tpragma.nim | 10 ++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/generics/mpragma1.nim create mode 100644 tests/generics/mpragma2.nim create mode 100644 tests/generics/tpragma.nim diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index 2639aba6cb..74f77a679c 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -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) diff --git a/tests/generics/mpragma1.nim b/tests/generics/mpragma1.nim new file mode 100644 index 0000000000..138d035df1 --- /dev/null +++ b/tests/generics/mpragma1.nim @@ -0,0 +1,3 @@ +macro aMacro*(u:untyped):untyped = + echo "in macro" + result = u diff --git a/tests/generics/mpragma2.nim b/tests/generics/mpragma2.nim new file mode 100644 index 0000000000..3c7251daf8 --- /dev/null +++ b/tests/generics/mpragma2.nim @@ -0,0 +1,6 @@ +import mpragma1 +proc p*[T]() = + proc inner() {.aMacro.} = + discard + inner() + discard diff --git a/tests/generics/tpragma.nim b/tests/generics/tpragma.nim new file mode 100644 index 0000000000..e83ef9cf45 --- /dev/null +++ b/tests/generics/tpragma.nim @@ -0,0 +1,10 @@ +discard """ + nimout: ''' +in macro +''' +""" + +# issue #18649 + +import mpragma2 +p[string]()