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).
This commit is contained in:
LemonBoy
2019-02-18 12:17:00 +01:00
committed by Andreas Rumpf
parent 8b39551fca
commit cf32d61fa5
3 changed files with 26 additions and 11 deletions

View File

@@ -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 =

View File

@@ -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)

View File

@@ -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)