diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index c4be1223b8..9a298cd90e 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -1344,6 +1344,16 @@ proc mergePragmas(n, pragmas: PNode) = else: for p in pragmas: n[pragmasPos].add p +proc mergeValidPragmas(n, pragmas: PNode, validPragmas: TSpecialWords) = + if n[pragmasPos].kind == nkEmpty: + n[pragmasPos] = newNodeI(nkPragma, n.info) + for p in pragmas: + let prag = whichPragma(p) + if prag in validPragmas: + let copy = copyTree(p) + overwriteLineInfo copy, n.info + n[pragmasPos].add copy + proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo, validPragmas: TSpecialWords) = if sym != nil and sym.kind != skModule: @@ -1357,7 +1367,8 @@ proc implicitPragmas*(c: PContext, sym: PSym, info: TLineInfo, internalError(c.config, info, "implicitPragmas") inc i popInfoContext(c.config) - if sym.kind in routineKinds and sym.ast != nil: mergePragmas(sym.ast, o) + if sym.kind in routineKinds and sym.ast != nil: + mergeValidPragmas(sym.ast, o, validPragmas) if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: localError(c.config, info, ".dynlib requires .exportc") diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 8bc68728cb..817cb62491 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -693,6 +693,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = pushOwner(c, s) openScope(c) n[namePos] = newSymNode(s) + s.ast = n # for implicitPragmas to use pragmaCallable(c, s, n, templatePragmas) implicitPragmas(c, s, n.info, templatePragmas) @@ -763,11 +764,6 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = closeScope(c) popOwner(c) - # set the symbol AST after pragmas, at least. This stops pragma that have - # been pushed (implicit) to be explicitly added to the template definition - # and misapplied to the body. see #18113 - s.ast = n - if sfCustomPragma in s.flags: if n[bodyPos].kind != nkEmpty: localError(c.config, n[bodyPos].info, errImplOfXNotAllowed % s.name.s) diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim index a505bb32f1..9c6b85c4e8 100644 --- a/tests/pragmas/tpush.nim +++ b/tests/pragmas/tpush.nim @@ -125,8 +125,20 @@ foo41() {.pop.} +import macros + block: {.push deprecated.} template test() = discard test() {.pop.} + macro foo(): bool = + let ast = getImpl(bindSym"test") + var found = false + if ast[4].kind == nnkPragma: + for x in ast[4]: + if x.eqIdent"deprecated": + found = true + break + result = newLit(found) + doAssert foo() diff --git a/tests/template/m19277_1.nim b/tests/template/m19277_1.nim new file mode 100644 index 0000000000..840bd47674 --- /dev/null +++ b/tests/template/m19277_1.nim @@ -0,0 +1,2 @@ +template foo*(x: untyped) = + echo "got: ", x diff --git a/tests/template/m19277_2.nim b/tests/template/m19277_2.nim new file mode 100644 index 0000000000..de72dad450 --- /dev/null +++ b/tests/template/m19277_2.nim @@ -0,0 +1,2 @@ +proc foo*(a: string) = + echo "got string: ", a diff --git a/tests/template/t19277.nim b/tests/template/t19277.nim new file mode 100644 index 0000000000..16435a09c4 --- /dev/null +++ b/tests/template/t19277.nim @@ -0,0 +1,19 @@ +discard """ + output: ''' +got: 0 +''' +""" + +# issue #19277 + +import m19277_1, m19277_2 + +template injector(val: untyped): untyped = + template subtemplate: untyped = val + subtemplate() + +template methodCall(val: untyped): untyped = val + +{.push raises: [Defect].} + +foo(injector(0).methodCall())