mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
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:
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user