I'd like to check that some "memory location" is annotated with {.volatile.}, to make sure my code only compiles, if I use {.volatile.} in the right place. I searc the lib code but didn't really find much, except this (asyncmacro.nim):

proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
  # ...
  # LINE NO: 385
  # If proc has an explicit gcsafe pragma, we add it to iterator as well.
  if prc.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == "gcsafe") != nil:
    closureIterator.addPragma(newIdentNode("gcsafe"))

I gave it a try, but did not get very far, as I'm still "practicing" the language itself, and haven't learned (or more precisely already forgot), how the meta-programming works.

Here is what I tried:

import macros, strutils

type
  VolatilePtr*[T] = distinct ptr T
  # Means it's a pointer to some volatile value

proc hasAnnotation(stuff: NimNode, annotation: static[string]): bool {.compileTime.} =
  (stuff.pragma.findChild(it.kind in {nnkSym, nnkIdent} and $it == annotation) != nil)

template toVolatilePtr*[T](t: untyped) =
  when hasAnnotation(t, "volatile"):
    VolatilePtr[T](addr t)
  else:
    {.error: "t is not volatile!".}


when isMainModule:
  var tua = 42'i32
  let p: VolatilePtr[int32] = toVolatilePtr[int32](tua)
  let tua2: int32 = 42'i32 #atomicLoadNSeqCST[int32](p)
  assert(tua2 == tua)

2017-11-12 19:33:48
I'm not sure it's possible, actually. You can retrieve t's initialization value (!), using t.symbol.getImpl, which is useful when handling const, but I can't see any way (or at least an obvious way) how to extract variable pragmas from a variable symbol.
2017-11-12 22:10:25