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
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}) result = qualifiedLookUp(c, n, {checkUndeclared})
proc semCustomPragma(c: PContext, n: PNode): PNode = proc semCustomPragma(c: PContext, n: PNode): PNode =
var callNode: PNode
if n.kind == nkIdent: if n.kind == nkIdent:
result = newTree(nkCall, n) # pragma -> pragma()
callNode = newTree(nkCall, n)
elif n.kind == nkExprColonExpr: elif n.kind == nkExprColonExpr:
# pragma: arg -> pragma(arg) # pragma: arg -> pragma(arg)
result = newTree(nkCall, n[0], n[1]) callNode = newTree(nkCall, n[0], n[1])
elif n.kind in nkPragmaCallKinds: elif n.kind in nkPragmaCallKinds:
result = n callNode = n
else: else:
invalidPragma(c, n) invalidPragma(c, n)
return 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: if r.isNil or sfCustomPragma notin r[0].sym.flags:
invalidPragma(c, n) invalidPragma(c, n)
else: return n
result = r
if n.kind == nkIdent: result = r
result = result[0] # Transform the nkCall node back to its original form if possible
elif n.kind == nkExprColonExpr: if n.kind == nkIdent and r.len == 1:
result.kind = n.kind # pragma(arg) -> pragma: arg # 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, proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
validPragmas: TSpecialWords, comesFromPush: bool) : bool = validPragmas: TSpecialWords, comesFromPush: bool) : bool =

View file

@ -1515,7 +1515,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
else: else:
let def = p[0].getImpl[3] let def = p[0].getImpl[3]
result = newTree(nnkPar) result = newTree(nnkPar)
for i in 1..<p.len: for i in 1 ..< def.len:
let key = def[i][0] let key = def[i][0]
let val = p[i] let val = p[i]
result.add newTree(nnkExprColonExpr, key, val) result.add newTree(nnkExprColonExpr, key, val)

View file

@ -233,3 +233,10 @@ block:
doAssert ps.first == ps[0] and ps.first == "one" doAssert ps.first == ps[0] and ps.first == "one"
doAssert ps.second == ps[1] and ps.second == 2 doAssert ps.second == ps[1] and ps.second == 2
doAssert ps.third == ps[2] and ps.third == 3.0 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)