diff options
author | LemonBoy <LemonBoy@users.noreply.github.com> | 2019-02-18 12:17:00 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-02-18 12:17:00 +0100 |
commit | cf32d61fa5084ce0f8577fd7e52c8d2070188462 (patch) | |
tree | c5134ef6b029e94841165ceb90a85e96a220261e | |
parent | 8b39551fca81e95b51393a2a8e702eebe3ba7c51 (diff) | |
download | Nim-cf32d61fa5084ce0f8577fd7e52c8d2070188462.tar.gz |
Prevent crash on pragma templates w/ generics (#10685)
* Prevent crash on pragma templates w/ generics * Remove incorrect call to pragma reconversion `semOverloadedCall` may return a node with more elements than the original nkCall node had (implicit and/or explicit generics).
-rw-r--r-- | compiler/pragmas.nim | 28 | ||||
-rw-r--r-- | lib/core/macros.nim | 2 | ||||
-rw-r--r-- | tests/pragmas/tcustom_pragma.nim | 7 |
3 files changed, 26 insertions, 11 deletions
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index f88035a07..3eedf15a9 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -719,26 +719,34 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = result = qualifiedLookUp(c, n, {checkUndeclared}) proc semCustomPragma(c: PContext, n: PNode): PNode = + var callNode: PNode + if n.kind == nkIdent: - result = newTree(nkCall, n) + # pragma -> pragma() + callNode = newTree(nkCall, n) elif n.kind == nkExprColonExpr: # pragma: arg -> pragma(arg) - result = newTree(nkCall, n[0], n[1]) + callNode = newTree(nkCall, n[0], n[1]) elif n.kind in nkPragmaCallKinds: - result = n + callNode = n else: invalidPragma(c, n) return n - let r = c.semOverloadedCall(c, result, n, {skTemplate}, {efNoUndeclared}) + let r = c.semOverloadedCall(c, callNode, n, {skTemplate}, {efNoUndeclared}) + if r.isNil or sfCustomPragma notin r[0].sym.flags: invalidPragma(c, n) - else: - result = r - if n.kind == nkIdent: - result = result[0] - elif n.kind == nkExprColonExpr: - result.kind = n.kind # pragma(arg) -> pragma: arg + return n + + result = r + # Transform the nkCall node back to its original form if possible + if n.kind == nkIdent and r.len == 1: + # pragma() -> pragma + result = result[0] + elif n.kind == nkExprColonExpr and r.len == 2: + # pragma(arg) -> pragma: arg + result.kind = n.kind proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, validPragmas: TSpecialWords, comesFromPush: bool) : bool = diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 43e61d660..7ec1eefc6 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1515,7 +1515,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped = else: let def = p[0].getImpl[3] result = newTree(nnkPar) - for i in 1..<p.len: + for i in 1 ..< def.len: let key = def[i][0] let val = p[i] result.add newTree(nnkExprColonExpr, key, val) diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index 0dc85cf67..9f2fc024b 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -233,3 +233,10 @@ block: doAssert ps.first == ps[0] and ps.first == "one" doAssert ps.second == ps[1] and ps.second == 2 doAssert ps.third == ps[2] and ps.third == 3.0 + +# pragma with implicit&explicit generic types +block: + template fooBar[T](x: T; c: static[int] = 42; m: char) {.pragma.} + var e {.fooBar("foo", 123, 'u').}: int + doAssert(hasCustomPragma(e, fooBar)) + doAssert(getCustomPragmaVal(e, fooBar).c == 123) |