summary refs log tree commit diff stats
path: root/tests/pragmas
diff options
context:
space:
mode:
Diffstat (limited to 'tests/pragmas')
-rw-r--r--tests/pragmas/cfunction.c4
-rw-r--r--tests/pragmas/custom_pragma.nim5
-rw-r--r--tests/pragmas/foobar.nim3
-rw-r--r--tests/pragmas/monoff1.nim1
-rw-r--r--tests/pragmas/mpushexperimental.nim30
-rw-r--r--tests/pragmas/mqualifiedmacro.nim10
-rw-r--r--tests/pragmas/t12558.nim15
-rw-r--r--tests/pragmas/t12640.nim26
-rw-r--r--tests/pragmas/t13306.nim10
-rw-r--r--tests/pragmas/t22713.nim12
-rw-r--r--tests/pragmas/t4384.nim3
-rw-r--r--tests/pragmas/t5149.nim12
-rw-r--r--tests/pragmas/t6448.nim17
-rw-r--r--tests/pragmas/t8741.nim29
-rw-r--r--tests/pragmas/tbitsize.nim22
-rw-r--r--tests/pragmas/tcompile_missing_file.nim5
-rw-r--r--tests/pragmas/tcompile_pragma.nim10
-rw-r--r--tests/pragmas/tcustom_pragma.nim540
-rw-r--r--tests/pragmas/tdeprecated.nim10
-rw-r--r--tests/pragmas/thintprocessing.nim18
-rw-r--r--tests/pragmas/tinvalid_user_pragma.nim9
-rw-r--r--tests/pragmas/tinvalidcustompragma.nim23
-rw-r--r--tests/pragmas/tlocks.nim12
-rw-r--r--tests/pragmas/tnoreturn.nim27
-rw-r--r--tests/pragmas/tonoff1.nim8
-rw-r--r--tests/pragmas/tonoff2.nim14
-rw-r--r--tests/pragmas/tpragmas_misc.nim75
-rw-r--r--tests/pragmas/tpragmas_reorder.nim19
-rw-r--r--tests/pragmas/tpush.nim144
-rw-r--r--tests/pragmas/tpushexperimental.nim13
-rw-r--r--tests/pragmas/tpushnotes.nim13
-rw-r--r--tests/pragmas/tqualifiedmacro.nim14
-rw-r--r--tests/pragmas/treorder.nim75
-rw-r--r--tests/pragmas/tsym_as_pragma.nim8
-rw-r--r--tests/pragmas/ttypedef_macro.nim66
-rw-r--r--tests/pragmas/tused.nim43
-rw-r--r--tests/pragmas/tuserpragma.nim7
-rw-r--r--tests/pragmas/tuserpragma2.nim12
-rw-r--r--tests/pragmas/tuserpragmaargs.nim5
-rw-r--r--tests/pragmas/tvar_macro.nim128
-rw-r--r--tests/pragmas/twarning_off.nim15
-rw-r--r--tests/pragmas/warn_module.nim7
42 files changed, 1519 insertions, 0 deletions
diff --git a/tests/pragmas/cfunction.c b/tests/pragmas/cfunction.c
new file mode 100644
index 000000000..bf49d6a29
--- /dev/null
+++ b/tests/pragmas/cfunction.c
@@ -0,0 +1,4 @@
+
+int cfunction(void) {
+  return NUMBER_HERE;
+}
diff --git a/tests/pragmas/custom_pragma.nim b/tests/pragmas/custom_pragma.nim
new file mode 100644
index 000000000..d2fc969d0
--- /dev/null
+++ b/tests/pragmas/custom_pragma.nim
@@ -0,0 +1,5 @@
+# imported by tcustom_pragmas to test scoping
+
+template serializationKey*(s: string) {.pragma.}
+template defaultValue*(V: typed) {.pragma.}
+template alternativeKey*(s: string = "", V: typed) {.pragma.}
diff --git a/tests/pragmas/foobar.nim b/tests/pragmas/foobar.nim
new file mode 100644
index 000000000..46032e187
--- /dev/null
+++ b/tests/pragmas/foobar.nim
@@ -0,0 +1,3 @@
+import macros
+macro async*(body: untyped): untyped =
+  return newStmtList()
diff --git a/tests/pragmas/monoff1.nim b/tests/pragmas/monoff1.nim
new file mode 100644
index 000000000..85d6c57b3
--- /dev/null
+++ b/tests/pragmas/monoff1.nim
@@ -0,0 +1 @@
+proc on*() = discard
diff --git a/tests/pragmas/mpushexperimental.nim b/tests/pragmas/mpushexperimental.nim
new file mode 100644
index 000000000..569861c1d
--- /dev/null
+++ b/tests/pragmas/mpushexperimental.nim
@@ -0,0 +1,30 @@
+
+import macros
+
+macro enumerate(x: ForLoopStmt): untyped =
+  expectKind x, nnkForStmt
+  # we strip off the first for loop variable and use
+  # it as an integer counter:
+  result = newStmtList()
+  result.add newVarStmt(x[0], newLit(0))
+  var body = x[^1]
+  if body.kind != nnkStmtList:
+    body = newTree(nnkStmtList, body)
+  body.add newCall(bindSym"inc", x[0])
+  var newFor = newTree(nnkForStmt)
+  for i in 1..x.len-3:
+    newFor.add x[i]
+  # transform enumerate(X) to 'X'
+  newFor.add x[^2][1]
+  newFor.add body
+  result.add newFor
+
+proc main*[T](x: T) =
+  {.push experimental: "forLoopMacros".}
+
+  for a, b in enumerate(items([1, 2, 3])):
+    echo a, " ", b
+
+  for a2, b2 in enumerate([1, 2, 3, 5]):
+    echo a2, " ", b2
+  {.pop.}
diff --git a/tests/pragmas/mqualifiedmacro.nim b/tests/pragmas/mqualifiedmacro.nim
new file mode 100644
index 000000000..908973206
--- /dev/null
+++ b/tests/pragmas/mqualifiedmacro.nim
@@ -0,0 +1,10 @@
+template t*(x:untyped): untyped = 
+  echo "template t"
+
+import macros
+macro m*(name: static string, x: untyped): untyped =
+  let newName = ident(name)
+  result = quote do:
+    type `newName` = object
+  if result.kind == nnkStmtList:
+    result = result[^1]
diff --git a/tests/pragmas/t12558.nim b/tests/pragmas/t12558.nim
new file mode 100644
index 000000000..14fc74cee
--- /dev/null
+++ b/tests/pragmas/t12558.nim
@@ -0,0 +1,15 @@
+discard """
+  nimout: '''@["1", "2", "3"]'''
+"""
+
+import sequtils
+
+{.push compile_time.}
+
+proc foo =
+  echo map_it([1, 2, 3], $it)
+
+{.pop.}
+
+static:
+  foo()
diff --git a/tests/pragmas/t12640.nim b/tests/pragmas/t12640.nim
new file mode 100644
index 000000000..c85185699
--- /dev/null
+++ b/tests/pragmas/t12640.nim
@@ -0,0 +1,26 @@
+discard """
+  matrix: "--mm:refc"
+  nimout: '''1
+2
+3
+[1, 2, 3]'''
+
+  output: '''1
+2
+3
+[1, 2, 3]'''
+"""
+
+# todo fixme it doesn't work with ORC
+proc doIt(a: openArray[int]) =
+  echo a
+
+proc foo() = 
+  var bug {.global, compiletime.}: seq[int]
+  bug = @[1, 2 ,3]
+  for i in 0 .. high(bug): echo bug[i]
+  doIt(bug)
+
+static:
+  foo()
+foo()
diff --git a/tests/pragmas/t13306.nim b/tests/pragmas/t13306.nim
new file mode 100644
index 000000000..36713dd04
--- /dev/null
+++ b/tests/pragmas/t13306.nim
@@ -0,0 +1,10 @@
+discard """
+  errormsg: "'testEpo' can have side effects"
+  line: 8
+"""
+
+import times
+
+func testEpo(x: float): float = epochTime() + x
+
+echo testEpo(1.0)
diff --git a/tests/pragmas/t22713.nim b/tests/pragmas/t22713.nim
new file mode 100644
index 000000000..3d3384632
--- /dev/null
+++ b/tests/pragmas/t22713.nim
@@ -0,0 +1,12 @@
+import std/macros
+
+
+template myPragma(x: int) {.pragma.}
+
+type
+  A = object
+    x: int64
+
+  B {.myPragma(sizeof(A)).} = object
+
+doAssert B.getCustomPragmaVal(myPragma) == 8
\ No newline at end of file
diff --git a/tests/pragmas/t4384.nim b/tests/pragmas/t4384.nim
new file mode 100644
index 000000000..e6b193f79
--- /dev/null
+++ b/tests/pragmas/t4384.nim
@@ -0,0 +1,3 @@
+macro testMacro(body: untyped): untyped = discard
+macro testMacro(s: string, body: untyped): untyped = discard
+proc foo() {.testMacro: "foo".} = discard
diff --git a/tests/pragmas/t5149.nim b/tests/pragmas/t5149.nim
new file mode 100644
index 000000000..2d242a8d5
--- /dev/null
+++ b/tests/pragmas/t5149.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: "{.exportc.} not allowed for type aliases"
+  line: 9
+"""
+
+type
+  X* = object
+    a: int
+  Y* {.exportc.} = X
+
+proc impl*(x: X) =
+  echo "it works"
diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim
new file mode 100644
index 000000000..6efb56e08
--- /dev/null
+++ b/tests/pragmas/t6448.nim
@@ -0,0 +1,17 @@
+discard """
+  errormsg: '''ambiguous call'''
+  line: 10
+  disabled: "32bit"
+"""
+
+import foobar
+import asyncdispatch, macros
+
+proc bar() {.async.} =
+  echo 42
+
+proc foo() {.async.} =
+  await bar()
+
+asyncCheck foo()
+runForever()
diff --git a/tests/pragmas/t8741.nim b/tests/pragmas/t8741.nim
new file mode 100644
index 000000000..bf97b0e29
--- /dev/null
+++ b/tests/pragmas/t8741.nim
@@ -0,0 +1,29 @@
+discard """
+  cmd: "nim check --hint:processing:off $file"
+  errormsg: "3 is not two"
+  nimout: '''t8741.nim(13, 9) Error: invalid pragma: foobar
+t8741.nim(29, 15) template/generic instantiation of `onlyTwo` from here
+t8741.nim(25, 12) Error: 3 is not two
+'''
+"""
+
+for a {.gensym, inject.} in @[1,2,3]:
+  discard
+
+for a {.foobar.} in @[1,2,3]:
+  discard
+
+type Foo[N: static[int]] = distinct int
+
+proc isTwo(n: int): bool =
+  n == 2
+
+proc onlyTwo[N: static[int]](a: Foo[N]): int =
+  when isTwo(N):
+    int(a)
+  else:
+    {.error: $(N) & " is not two".}
+
+when isMainModule:
+  let foo: Foo[3] = Foo[3](5)
+  echo onlyTwo(foo)
diff --git a/tests/pragmas/tbitsize.nim b/tests/pragmas/tbitsize.nim
new file mode 100644
index 000000000..39aee445f
--- /dev/null
+++ b/tests/pragmas/tbitsize.nim
@@ -0,0 +1,22 @@
+discard """
+ccodeCheck: "\\i @'unsigned int flag:1;' .*"
+"""
+
+type
+  bits* = object
+    flag* {.bitsize: 1.}: cuint
+    opts* {.bitsize: 4.}: cint
+
+var
+  b: bits
+
+doAssert b.flag == 0
+b.flag = 1
+doAssert b.flag == 1
+b.flag = 2
+doAssert b.flag == 0
+
+b.opts = 7
+doAssert b.opts == 7
+b.opts = 9
+doAssert b.opts == -7
diff --git a/tests/pragmas/tcompile_missing_file.nim b/tests/pragmas/tcompile_missing_file.nim
new file mode 100644
index 000000000..fd90bd57d
--- /dev/null
+++ b/tests/pragmas/tcompile_missing_file.nim
@@ -0,0 +1,5 @@
+discard """
+  joinable: false
+  errormsg: "cannot find: noexist.c"
+"""
+{.compile: "noexist.c".}
diff --git a/tests/pragmas/tcompile_pragma.nim b/tests/pragmas/tcompile_pragma.nim
new file mode 100644
index 000000000..5b99352dd
--- /dev/null
+++ b/tests/pragmas/tcompile_pragma.nim
@@ -0,0 +1,10 @@
+discard """
+  output: '''34'''
+  joinable: false
+"""
+
+{.compile("cfunction.c", "-DNUMBER_HERE=34").}
+
+proc cfunction(): cint {.importc.}
+
+echo cfunction()
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
new file mode 100644
index 000000000..11a6df813
--- /dev/null
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -0,0 +1,540 @@
+{.experimental: "notnil".}
+
+import macros, asyncmacro, asyncfutures
+
+block:
+  template myAttr() {.pragma.}
+
+  proc myProc():int {.myAttr.} = 2
+  const hasMyAttr = myProc.hasCustomPragma(myAttr)
+  static:
+    doAssert(hasMyAttr)
+
+block:
+  template myAttr(a: string) {.pragma.}
+
+  type
+    MyObj = object
+      myField1, myField2 {.myAttr: "hi".}: int
+
+    MyGenericObj[T] = object
+      myField1, myField2 {.myAttr: "hi".}: int
+
+    MyOtherObj = MyObj
+
+
+  var o: MyObj
+  static:
+    doAssert o.myField2.hasCustomPragma(myAttr)
+    doAssert(not o.myField1.hasCustomPragma(myAttr))
+    doAssert(not o.myField1.hasCustomPragma(MyObj))
+    doAssert(not o.myField1.hasCustomPragma(MyOtherObj))
+
+  var ogen: MyGenericObj[int]
+  static:
+    doAssert ogen.myField2.hasCustomPragma(myAttr)
+    doAssert(not ogen.myField1.hasCustomPragma(myAttr))
+    doAssert(not ogen.myField1.hasCustomPragma(MyGenericObj))
+    doAssert(not ogen.myField1.hasCustomPragma(MyGenericObj))
+
+
+import custom_pragma
+block: # A bit more advanced case
+  type
+    Subfield {.defaultValue: "catman".} = object
+      `c`* {.serializationKey: "cc".}: float
+
+    MySerializable = object
+      a {.serializationKey"asdf", defaultValue: 5.} : int
+      b {.custom_pragma.defaultValue"hello".} : int
+      field: Subfield
+      d {.alternativeKey("df", 5).}: float
+      e {.alternativeKey(V = 5).}: seq[bool]
+
+  proc myproc(x: int, s: string) {.alternativeKey(V = 5), serializationKey"myprocSS".} =
+    echo x, s
+
+
+  var s: MySerializable
+
+  const aDefVal = s.a.getCustomPragmaVal(defaultValue)
+  static: doAssert(aDefVal == 5)
+
+  const aSerKey = s.a.getCustomPragmaVal(serializationKey)
+  static: doAssert(aSerKey == "asdf")
+
+  const cSerKey = getCustomPragmaVal(s.field.c, serializationKey)
+  static: doAssert(cSerKey == "cc")
+
+  const procSerKey = getCustomPragmaVal(myproc, serializationKey)
+  static: doAssert(procSerKey == "myprocSS")
+
+  static: doAssert(hasCustomPragma(myproc, alternativeKey))
+
+  const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue)
+  static: doAssert(hasFieldCustomPragma == false)
+
+  # pragma on an object
+  static:
+    doAssert Subfield.hasCustomPragma(defaultValue)
+    doAssert(Subfield.getCustomPragmaVal(defaultValue) == "catman")
+
+    doAssert hasCustomPragma(type(s.field), defaultValue)
+
+  proc foo(s: var MySerializable) =
+    static: doAssert(s.a.getCustomPragmaVal(defaultValue) == 5)
+
+  foo(s)
+
+block: # ref types
+  type
+    Node = object of RootObj
+      left {.serializationKey:"l".}, right {.serializationKey:"r".}: NodeRef
+    NodeRef = ref Node
+    NodePtr = ptr Node
+
+    SpecialNodeRef = ref object of NodeRef
+      data {.defaultValue"none".}: string
+
+    MyFile {.defaultValue: "closed".} = ref object
+      path {.defaultValue: "invalid".}: string
+
+    TypeWithoutPragma = object
+
+  var s = NodeRef()
+
+  const
+    leftSerKey = getCustomPragmaVal(s.left, serializationKey)
+    rightSerKey = getCustomPragmaVal(s.right, serializationKey)
+  static:
+    doAssert leftSerKey == "l"
+    doAssert rightSerKey == "r"
+
+  var specS = SpecialNodeRef()
+
+  const
+    dataDefVal = hasCustomPragma(specS.data, defaultValue)
+    specLeftSerKey = hasCustomPragma(specS.left, serializationKey)
+  static:
+    doAssert dataDefVal == true
+    doAssert specLeftSerKey == true
+
+  var ptrS = NodePtr(nil)
+  const
+    ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey)
+  static:
+    doAssert ptrRightSerKey == "r"
+
+  var f = MyFile()
+  const
+    fileDefVal = f.getCustomPragmaVal(defaultValue)
+    filePathDefVal = f.path.getCustomPragmaVal(defaultValue)
+  static:
+    doAssert fileDefVal == "closed"
+    doAssert filePathDefVal == "invalid"
+
+  static:
+    doAssert TypeWithoutPragma.hasCustomPragma(defaultValue) == false
+
+block:
+  type
+    VariantKind = enum
+      variInt,
+      variFloat
+      variString
+      variNestedCase
+    Variant = object
+      case kind: VariantKind
+      of variInt: integer {.serializationKey: "int".}: BiggestInt
+      of variFloat: floatp: BiggestFloat
+      of variString: str {.serializationKey: "string".}: string
+      of variNestedCase:
+        case nestedKind: VariantKind
+        of variInt..variNestedCase: nestedItem {.defaultValue: "Nimmers of the world, unite!".}: int
+
+  let vari = Variant(kind: variInt)
+
+  const
+    hasIntSerKey = vari.integer.hasCustomPragma(serializationKey)
+    strSerKey = vari.str.getCustomPragmaVal(serializationKey)
+    nestedItemDefVal = vari.nestedItem.getCustomPragmaVal(defaultValue)
+
+  static:
+    doAssert hasIntSerKey
+    doAssert strSerKey == "string"
+    doAssert nestedItemDefVal == "Nimmers of the world, unite!"
+
+block:
+  template simpleAttr {.pragma.}
+
+  type Annotated {.simpleAttr.} = object
+
+  proc generic_proc[T]() =
+    doAssert Annotated.hasCustomPragma(simpleAttr)
+
+#--------------------------------------------------------------------------
+# Pragma on proc type
+
+type
+  MyAnnotatedProcType {.defaultValue(4).} = proc(x: int)
+
+let a {.defaultValue(4).}: proc(x: int)  = nil
+var b: MyAnnotatedProcType = nil
+var c: proc(x: int): void {.defaultValue(5).}  = nil
+var d {.defaultValue(44).}: MyAnnotatedProcType = nil
+static:
+  doAssert hasCustomPragma(a, defaultValue)
+  doAssert hasCustomPragma(MyAnnotatedProcType, defaultValue)
+  doAssert hasCustomPragma(b, defaultValue)
+  doAssert hasCustomPragma(typeof(c), defaultValue)
+  doAssert getCustomPragmaVal(d, defaultValue) == 44
+  doAssert getCustomPragmaVal(typeof(d), defaultValue) == 4
+
+# bug #8371
+template thingy {.pragma.}
+
+type
+  Cardinal = enum
+    north, east, south, west
+  Something = object
+    a: float32
+    case cardinal: Cardinal
+    of north:
+      b {.thingy.}: int
+    of east:
+      c: int
+    of south: discard
+    else: discard
+
+var foo: Something
+foo.cardinal = north
+doAssert foo.b.hasCustomPragma(thingy) == true
+
+proc myproc(s: string): int =
+  {.thingy.}:
+    s.len
+
+doAssert myproc("123") == 3
+
+let xx = compiles:
+  proc myproc_bad(s: string): int =
+    {.not_exist.}:
+      s.len
+doAssert: xx == false
+
+macro checkSym(s: typed{nkSym}): untyped =
+  let body = s.getImpl.body
+  doAssert body[1].kind == nnkPragmaBlock
+  doAssert body[1][0].kind == nnkPragma
+  doAssert body[1][0][0] == bindSym"thingy"
+
+checkSym(myproc)
+
+# var and let pragmas
+block:
+  template myAttr() {.pragma.}
+  template myAttr2(x: int) {.pragma.}
+  template myAttr3(x: string) {.pragma.}
+
+  type
+    MyObj2 = ref object
+    MyObjNotNil = MyObj2 not nil
+
+  let a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
+  let b {.myAttr,myAttr2(2),myAttr3:"test".} = 0
+  var x {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
+  var y {.myAttr,myAttr2(2),myAttr3:"test".}: int
+  var z {.myAttr,myAttr2(2),myAttr3:"test".} = 0
+  var z2 {.myAttr.}: MyObjNotNil
+
+  template check(s: untyped) =
+    doAssert s.hasCustomPragma(myAttr)
+    doAssert s.hasCustomPragma(myAttr2)
+    doAssert s.getCustomPragmaVal(myAttr2) == 2
+    doAssert s.hasCustomPragma(myAttr3)
+    doAssert s.getCustomPragmaVal(myAttr3) == "test"
+
+  check(a)
+  check(b)
+  check(x)
+  check(y)
+  check(z)
+
+# pragma with multiple fields
+block:
+  template myAttr(first: string, second: int, third: float) {.pragma.}
+  let a {.myAttr("one", 2, 3.0).} = 0
+  let ps = a.getCustomPragmaVal(myAttr)
+  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)
+
+block:
+  macro expectedAst(expectedRepr: static[string], input: untyped): untyped =
+    doAssert input.treeRepr & "\n" == expectedRepr
+    return input
+
+  macro expectedAstRepr(expectedRepr: static[string], input: untyped): untyped =
+    doAssert input.repr == expectedRepr
+    return input
+
+  const procTypeAst = """
+ProcTy
+  FormalParams
+    Empty
+    IdentDefs
+      Ident "x"
+      Ident "int"
+      Empty
+  Pragma
+    Ident "async"
+"""
+
+  type
+    Foo = proc (x: int) {.expectedAst(procTypeAst), async.}
+
+  static: doAssert Foo is proc(x: int): Future[void]
+
+  const asyncProcTypeAst = """
+proc (s: string): Future[void] {..}"""
+  # using expectedAst would show `OpenSymChoice` for Future[void], which is fragile.
+  type
+    Bar = proc (s: string) {.async, expectedAstRepr(asyncProcTypeAst).}
+
+  static: doAssert Bar is proc(x: string): Future[void]
+
+  const typeAst = """
+TypeDef
+  PragmaExpr
+    Ident "Baz"
+    Pragma
+  Empty
+  ObjectTy
+    Empty
+    Empty
+    RecList
+      IdentDefs
+        Ident "x"
+        Ident "string"
+        Empty
+"""
+
+  type
+    Baz {.expectedAst(typeAst).} = object
+      x: string
+
+  static: doAssert Baz.x is string
+
+  const procAst = """
+ProcDef
+  Ident "bar"
+  Empty
+  Empty
+  FormalParams
+    Ident "string"
+    IdentDefs
+      Ident "s"
+      Ident "string"
+      Empty
+  Empty
+  Empty
+  StmtList
+    ReturnStmt
+      Ident "s"
+"""
+
+  proc bar(s: string): string {.expectedAst(procAst).} =
+    return s
+
+  static: doAssert bar("x") == "x"
+
+#------------------------------------------------------
+# bug #13909
+
+template dependency*(id: string, weight = 0.0) {.pragma.}
+
+type
+  MyObject* = object
+    provider*: proc(obj: string): pointer {.dependency("Data/" & obj, 16.1), noSideEffect.}
+
+proc myproc(obj: string): string {.dependency("Data/" & obj, 16.1).} =
+  result = obj
+
+# bug 12523
+template myCustomPragma {.pragma.}
+
+type
+  RefType = ref object
+    field {.myCustomPragma.}: int
+
+  ObjType = object
+    field {.myCustomPragma.}: int
+  RefType2 = ref ObjType
+
+block:
+  let x = RefType()
+  for fieldName, fieldSym in fieldPairs(x[]):
+    doAssert hasCustomPragma(fieldSym, myCustomPragma)
+
+block:
+  let x = RefType2()
+  for fieldName, fieldSym in fieldPairs(x[]):
+    doAssert hasCustomPragma(fieldSym, myCustomPragma)
+
+# bug 8457
+block:
+  template world {.pragma.}
+
+  type
+    Hello = ref object
+      a: float32
+      b {.world.}: int
+
+  discard Hello(a: 1.0, b: 12)
+
+# test routines
+block:
+  template prag {.pragma.}
+  proc hello {.prag.} = discard
+  iterator hello2: int {.prag.} = discard
+  template hello3(x: int): int {.prag.} = x
+  macro hello4(x: int): int {.prag.} = x
+  func hello5(x: int): int {.prag.} = x
+  doAssert hello.hasCustomPragma(prag)
+  doAssert hello2.hasCustomPragma(prag)
+  doAssert hello3.hasCustomPragma(prag)
+  doAssert hello4.hasCustomPragma(prag)
+  doAssert hello5.hasCustomPragma(prag)
+
+# test push doesn't break
+block:
+  template prag {.pragma.}
+  {.push prag.}
+  proc hello = discard
+  iterator hello2: int = discard
+  template hello3(x: int): int = x
+  macro hello4(x: int): int = x
+  func hello5(x: int): int = x
+  type
+    Foo = enum a
+    Bar[T] = ref object of RootObj
+      x: T
+      case y: bool
+      of false: discard
+      else:
+        when true: discard
+  for a in [1]: discard a
+  {.pop.}
+
+# issue #11511
+when false:
+  template myAttr {.pragma.}
+
+  type TObj = object
+      a {.myAttr.}: int
+
+  macro hasMyAttr(t: typedesc): untyped =
+    let objTy = t.getType[1].getType
+    let recList = objTy[2]
+    let sym = recList[0]
+    assert sym.kind == nnkSym and sym.eqIdent("a")
+    let hasAttr = sym.hasCustomPragma(myAttr)
+    newLit(hasAttr)
+
+  doAssert hasMyAttr(TObj)
+
+
+# bug #11415
+template noserialize() {.pragma.}
+
+type
+  Point[T] = object
+    x, y: T
+
+  ReplayEventKind = enum
+    FoodAppeared, FoodEaten, DirectionChanged
+
+  ReplayEvent = object
+    case kind: ReplayEventKind
+    of FoodEaten, FoodAppeared: # foodPos is in multiple branches
+      foodPos {.noserialize.}: Point[float]
+    of DirectionChanged:
+      playerPos: float
+let ev = ReplayEvent(
+    kind: FoodEaten,
+    foodPos: Point[float](x: 5.0, y: 1.0)
+  )
+
+doAssert ev.foodPos.hasCustomPragma(noserialize)
+
+
+when false:
+  # misc
+  {.pragma: haha.}
+  {.pragma: hoho.}
+  template hehe(key, val: string, haha) {.pragma.}
+
+  type A {.haha, hoho, haha, hehe("hi", "hu", "he").} = int
+
+  assert A.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he")
+
+  template hehe(key, val: int) {.pragma.}
+
+  var bb {.haha, hoho, hehe(1, 2), haha, hehe("hi", "hu", "he").} = 3
+
+  # left-to-right priority/override order for getCustomPragmaVal
+  assert bb.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he")
+
+{.experimental: "dynamicBindSym".}
+
+# const
+block:
+  template myAttr() {.pragma.}
+  template myAttr2(x: int) {.pragma.}
+  template myAttr3(x: string) {.pragma.}
+
+  type
+    MyObj2 = ref object
+
+  const a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
+  const b {.myAttr,myAttr2(2),myAttr3:"test".} = 0
+
+  macro forceHasCustomPragma(x: untyped, y: typed): untyped =
+    var x = bindSym(x.repr)
+    for c in x:
+      if c.symKind == nskConst:
+        x = c
+        break
+    result = getAst(hasCustomPragma(x, y))
+
+  macro forceGetCustomPragmaVal(x: untyped, y: typed): untyped =
+    var x = bindSym(x.repr)
+    for c in x:
+      if c.symKind == nskConst:
+        x = c
+        break
+    result = getAst(getCustomPragmaVal(x, y))
+
+  template check(s: untyped) =
+    doAssert forceHasCustomPragma(s, myAttr)
+    doAssert forceHasCustomPragma(s, myAttr2)
+    doAssert forceGetCustomPragmaVal(s, myAttr2) == 2
+    doAssert forceHasCustomPragma(s, myAttr3)
+    doAssert forceGetCustomPragmaVal(s, myAttr3) == "test"
+
+  check(a)
+  check(b)
+
+block: # https://forum.nim-lang.org/t/12522, backticks
+  template `mypragma`() {.pragma.}
+  # Error: invalid pragma: `mypragma`
+  type Test = object
+    field {.`mypragma`.}: int
+  doAssert Test().field.hasCustomPragma(mypragma)
diff --git a/tests/pragmas/tdeprecated.nim b/tests/pragmas/tdeprecated.nim
new file mode 100644
index 000000000..a5d07f727
--- /dev/null
+++ b/tests/pragmas/tdeprecated.nim
@@ -0,0 +1,10 @@
+# bug #6436
+proc foo(size: int, T: typedesc): seq[T]  {.deprecated.}=
+  result = newSeq[T](size)
+
+proc foo[T](size: int): seq[T]=
+  result = newSeq[T](size)
+
+let bar = foo[int](3) # Warning foo is deprecated
+
+doAssert bar == @[0, 0, 0]
diff --git a/tests/pragmas/thintprocessing.nim b/tests/pragmas/thintprocessing.nim
new file mode 100644
index 000000000..c608bc6e4
--- /dev/null
+++ b/tests/pragmas/thintprocessing.nim
@@ -0,0 +1,18 @@
+discard """
+  disabled: windows
+  matrix: "--hint:processing"
+  nimout: '''
+compile start
+..
+warn_module.nim(6, 6) Hint: 'test' is declared but not used [XDeclaredButNotUsed]
+compile end
+'''
+"""
+
+static:
+  echo "compile start"
+
+import warn_module
+
+static:
+  echo "compile end"
diff --git a/tests/pragmas/tinvalid_user_pragma.nim b/tests/pragmas/tinvalid_user_pragma.nim
new file mode 100644
index 000000000..3081db842
--- /dev/null
+++ b/tests/pragmas/tinvalid_user_pragma.nim
@@ -0,0 +1,9 @@
+discard """
+cmd: "nim check $file"
+"""
+
+{.pragma test: foo.} #[tt.Error
+^ invalid pragma:  {.pragma, test: foo.} ]#
+
+{.pragma: 1.} #[tt.Error
+^ invalid pragma:  {.pragma: 1.} ]#
diff --git a/tests/pragmas/tinvalidcustompragma.nim b/tests/pragmas/tinvalidcustompragma.nim
new file mode 100644
index 000000000..a31695809
--- /dev/null
+++ b/tests/pragmas/tinvalidcustompragma.nim
@@ -0,0 +1,23 @@
+discard """
+  cmd: "nim check $file"
+"""
+
+# issue #21652
+type Foo = object
+template foo() {.tags:[Foo].} = #[tt.Error
+                     ^ invalid pragma: tags: [Foo]]#
+  discard
+
+{.foobar.} #[tt.Error
+  ^ invalid pragma: foobar]#
+type A = enum a {.foobar.} #[tt.Error
+                  ^ invalid pragma: foobar]#
+for b {.foobar.} in [1]: discard #[tt.Error
+        ^ invalid pragma: foobar]#
+template foobar {.pragma.}
+{.foobar.} #[tt.Error
+  ^ cannot attach a custom pragma to 'tinvalidcustompragma'; custom pragmas are not supported for modules]#
+type A = enum a {.foobar.} #[tt.Error
+                  ^ cannot attach a custom pragma to 'a'; custom pragmas are not supported for enum fields]#
+for b {.foobar.} in [1]: discard #[tt.Error
+        ^ cannot attach a custom pragma to 'b'; custom pragmas are not supported for `for` loop variables]#
diff --git a/tests/pragmas/tlocks.nim b/tests/pragmas/tlocks.nim
new file mode 100644
index 000000000..5d6fcdd9c
--- /dev/null
+++ b/tests/pragmas/tlocks.nim
@@ -0,0 +1,12 @@
+type SomeBase* = ref object of RootObj
+type SomeDerived* = ref object of SomeBase
+  memberProc*: proc ()
+
+method testMethod(g: SomeBase) {.base, locks: "unknown".} = discard
+method testMethod(g: SomeDerived) =
+  if g.memberProc != nil:
+    g.memberProc()
+
+# ensure int literals still work
+proc plain*() {.locks: 0.} =
+  discard
diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim
new file mode 100644
index 000000000..6a58055fe
--- /dev/null
+++ b/tests/pragmas/tnoreturn.nim
@@ -0,0 +1,27 @@
+discard """
+matrix: "--mm:refc"
+ccodeCheck: "\\i @'__attribute__((noreturn))' .*"
+action: compile
+"""
+
+proc noret1*(i: int) {.noreturn.} =
+  echo i
+
+
+proc noret2*(i: int): void {.noreturn.} =
+  echo i
+
+if true: noret1(1)
+if true: noret2(2)
+
+var p {.used.}: proc(i: int): int
+doAssert(not compiles(
+  p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int
+))
+
+
+doAssert(not compiles(
+  block:
+    noret1(5)
+    echo 1 # statement after noreturn
+))
diff --git a/tests/pragmas/tonoff1.nim b/tests/pragmas/tonoff1.nim
new file mode 100644
index 000000000..20ba7def2
--- /dev/null
+++ b/tests/pragmas/tonoff1.nim
@@ -0,0 +1,8 @@
+# issue #23002
+
+import monoff1
+
+proc test() =
+  {.warning[ProveInit]: on.}
+
+test()
diff --git a/tests/pragmas/tonoff2.nim b/tests/pragmas/tonoff2.nim
new file mode 100644
index 000000000..9dff5ef11
--- /dev/null
+++ b/tests/pragmas/tonoff2.nim
@@ -0,0 +1,14 @@
+discard """
+    action: compile
+"""
+
+# issue #22841
+
+import unittest
+
+proc on() =
+    discard
+
+suite "some suite":
+    test "some test":
+        discard
diff --git a/tests/pragmas/tpragmas_misc.nim b/tests/pragmas/tpragmas_misc.nim
new file mode 100644
index 000000000..adb7e73c3
--- /dev/null
+++ b/tests/pragmas/tpragmas_misc.nim
@@ -0,0 +1,75 @@
+##[
+tests for misc pragmas that don't need a separate file
+]##
+
+block:
+  static: doAssert not defined(tpragmas_misc_def)
+  {.undef(tpragmas_misc_def).} # works even if not set
+  static: doAssert not defined(tpragmas_misc_def)
+  {.define(tpragmas_misc_def).}
+  static: doAssert defined(tpragmas_misc_def)
+  {.undef(tpragmas_misc_def).}
+  static: doAssert not defined(tpragmas_misc_def)
+
+block: # (partial fix) bug #15920
+  block: # var template pragmas don't work in templates
+    template foo(expr) =
+      expr
+    proc fun1()=
+      let a {.foo.} = 1
+    template fun2()=
+      let a {.foo.} = 1
+    fun1() # ok
+    fun2() # WAS bug
+
+  template foo2() = discard # distractor (template or other symbol kind)
+  block:
+    template foo2(expr) =
+      expr
+    proc fun1()=
+      let a {.foo2.} = 1
+    template fun2()=
+      let a {.foo2.} = 1
+    fun1() # ok
+    fun2() # bug: Error: invalid pragma: foo2
+
+  block: # template pragmas don't work for templates, #18212
+    # adapted from $nim/lib/std/private/since.nim
+    # case without overload
+    template since3(version: (int, int), body: untyped) {.dirty.} =
+      when (NimMajor, NimMinor) >= version:
+        body
+    when true: # bug
+      template fun3(): int {.since3: (1, 3).} = 12
+
+  block: # ditto, w
+    # case with overload
+    template since2(version: (int, int), body: untyped) {.dirty.} =
+      when (NimMajor, NimMinor) >= version:
+        body
+    template since2(version: (int, int, int), body: untyped) {.dirty.} =
+      when (NimMajor, NimMinor, NimPatch) >= version:
+        body
+    when true: # bug
+      template fun3(): int {.since2: (1, 3).} = 12
+
+when true: # D20210801T100514:here
+  from macros import genSym
+  block:
+    template fn() =
+      var ret {.gensym.}: int # must special case template pragmas so it doesn't get confused
+      discard ret
+    fn()
+    static: discard genSym()
+
+block: # issue #10994
+  macro foo(x): untyped = x
+  template bar {.pragma.}
+
+  proc a {.bar.} = discard # works
+  proc b {.bar, foo.} = discard # doesn't
+
+block: # issue #22525
+  macro catch(x: typed) = x
+  proc thing {.catch.} = discard
+  thing()
diff --git a/tests/pragmas/tpragmas_reorder.nim b/tests/pragmas/tpragmas_reorder.nim
new file mode 100644
index 000000000..c4b1a6b0a
--- /dev/null
+++ b/tests/pragmas/tpragmas_reorder.nim
@@ -0,0 +1,19 @@
+discard """
+  matrix: "--experimental:codeReordering"
+"""
+
+runnableExamples:
+  import strtabs
+  var t = newStringTable()
+  t["name"] = "John"
+  t["city"] = "Monaco"
+  doAssert t.len == 2
+  doAssert t.hasKey "name"
+  doAssert "name" in t
+
+include "system/inclrtl"
+
+{.pragma: rtlFunc, rtl.}
+
+proc hasKey*(): bool {.rtlFunc.} =
+  discard
\ No newline at end of file
diff --git a/tests/pragmas/tpush.nim b/tests/pragmas/tpush.nim
new file mode 100644
index 000000000..9c6b85c4e
--- /dev/null
+++ b/tests/pragmas/tpush.nim
@@ -0,0 +1,144 @@
+discard """
+  targets: "c js"
+"""
+
+# test the new pragmas
+
+{.push warnings: off, hints: off.}
+proc noWarning() =
+  var
+    x: int
+  echo(x)
+
+{.pop.}
+
+proc WarnMe() =
+  var
+    x: int
+  echo(x)
+
+# bug #11852
+proc foo(x: string, y: int, res: int) =
+  {.push checks: off}
+  var a: ptr char = unsafeAddr(x[y])
+  {.pop.}
+  if x.len > y:
+    doAssert ord(a[]) == 51
+  else:
+    doAssert x.len + 48 == res
+
+foo("", 0, 48)
+foo("abc", 40, 51)
+
+# bug #22362
+{.push staticBoundChecks: on.}
+proc main(): void =
+  {.pop.}
+  discard
+  {.push staticBoundChecks: on.}
+
+main()
+
+
+proc timnFoo[T](obj: T) {.noSideEffect.} = discard # BUG
+
+{.push exportc.}
+proc foo1() =
+  var s1 = "bar"
+  timnFoo(s1)
+  var s2 = @[1]
+  timnFoo(s2)
+{.pop.}
+
+
+block: # bug #22913
+  block:
+    type r = object
+
+    template std[T](x: T) =
+      let ttt {.used.} = x
+      result = $ttt
+
+    proc bar[T](x: T): string =
+      std(x)
+
+    {.push exportc: "$1".}
+    proc foo(): r =
+      let s = bar(123)
+    {.pop.}
+
+    discard foo()
+
+  block:
+    type r = object
+    {.push exportc: "$1".}
+    proc foo2(): r =
+      let s = $result
+    {.pop.}
+
+    discard foo2()
+
+block: # bug #23019
+  proc f(x: bool)
+
+  proc a(x: int) =
+    if false: f(true)
+
+  proc f(x: bool) =
+    if false: a(0)
+
+  proc k(r: int|int) {.inline.} =  # seems to require being generic and inline
+    if false: a(0)
+
+
+  # {.push tags: [].}
+  {.push raises: [].}
+
+  {.push warning[ObservableStores]:off.}  # can be any warning, off or on
+  let w = 0
+  k(w)
+  {.pop.}
+  {.pop.}
+
+{.push exportC.}
+
+block:
+  proc foo11() =
+    const factor = [1, 2, 3, 4]
+    doAssert factor[0] == 1
+  proc foo21() =
+    const factor = [1, 2, 3, 4]
+    doAssert factor[0] == 1
+
+  foo11()
+  foo21()
+
+template foo31() =
+  let factor = [1, 2, 3, 4]
+  doAssert factor[0] == 1
+template foo41() =
+  let factor = [1, 2, 3, 4]
+  doAssert factor[0] == 1
+
+foo31()
+foo41()
+
+{.pop.}
+
+import macros
+
+block:
+  {.push deprecated.}
+  template test() = discard
+  test()
+  {.pop.}
+  macro foo(): bool =
+    let ast = getImpl(bindSym"test")
+    var found = false
+    if ast[4].kind == nnkPragma:
+      for x in ast[4]:
+        if x.eqIdent"deprecated":
+          found = true
+          break
+    result = newLit(found)
+  doAssert foo()
diff --git a/tests/pragmas/tpushexperimental.nim b/tests/pragmas/tpushexperimental.nim
new file mode 100644
index 000000000..301419f60
--- /dev/null
+++ b/tests/pragmas/tpushexperimental.nim
@@ -0,0 +1,13 @@
+discard """
+  output: '''0 1
+1 2
+2 3
+0 1
+1 2
+2 3
+3 5'''
+"""
+
+import mpushexperimental
+
+main(12)
diff --git a/tests/pragmas/tpushnotes.nim b/tests/pragmas/tpushnotes.nim
new file mode 100644
index 000000000..27ba0bec4
--- /dev/null
+++ b/tests/pragmas/tpushnotes.nim
@@ -0,0 +1,13 @@
+discard """
+  matrix: "--warningAsError:HoleEnumConv"
+"""
+
+type
+  e = enum
+    a = 0
+    b = 2
+
+var i: int
+{.push warning[HoleEnumConv]:off.}
+discard i.e
+{.pop.}
diff --git a/tests/pragmas/tqualifiedmacro.nim b/tests/pragmas/tqualifiedmacro.nim
new file mode 100644
index 000000000..bc95ec1ea
--- /dev/null
+++ b/tests/pragmas/tqualifiedmacro.nim
@@ -0,0 +1,14 @@
+discard """
+  output: '''
+template t
+'''
+"""
+
+# issue #12696
+
+import mqualifiedmacro
+proc p() {. mqualifiedmacro.t .} = # errors with identifier expected but a.t found
+  echo "proc p"
+
+type Foo {. mqualifiedmacro.m("Bar") .} = object
+doAssert Bar is object
diff --git a/tests/pragmas/treorder.nim b/tests/pragmas/treorder.nim
new file mode 100644
index 000000000..09a98ef6a
--- /dev/null
+++ b/tests/pragmas/treorder.nim
@@ -0,0 +1,75 @@
+discard """
+output:'''0
+1
+2
+3'''
+"""
+
+import macros
+# {.reorder: on .}
+{.experimental: "codeReordering".}
+
+echo foo(-1)
+echo callWithFoo(0)
+echo(CA+CD)
+echo useTypes(TA(x:TB(x:1)), 2)
+second(0)
+
+template callWithFoo(arg: untyped): untyped =
+  foo(arg)
+
+proc first(i: int): void
+
+proc second(i: int): void =
+  make(first)
+  first(i)
+
+proc useTypes(a: TA, d: TD): int =
+  result = a.x.x+d
+
+type
+  TDoubleCyclic = ref object
+    x: TCyclicA
+    y: TCyclicB
+
+type
+  TCyclicA = ref object
+    x: TDoubleCyclic
+
+type
+  TCyclicB = ref object
+    x: TDoubleCyclic
+
+const
+  CA = 1
+  CB = CC
+
+type
+  TA = object
+    x: TB
+  TC = type(CC)
+  TD = type(CA)
+
+const
+  CC = 1
+  CD = CB
+
+type
+  TB = object
+    x: TC
+
+proc foo(x: int): int =
+  result = bar(x)
+
+proc bar(x: int): int =
+  result = x+1
+
+macro make(arg: untyped): untyped =
+  ss &= arg.repr
+  ss &= " "
+  discard
+
+proc first(i: int): void =
+  make(second)
+
+var ss {.compileTime.}: string = ""
diff --git a/tests/pragmas/tsym_as_pragma.nim b/tests/pragmas/tsym_as_pragma.nim
new file mode 100644
index 000000000..788311244
--- /dev/null
+++ b/tests/pragmas/tsym_as_pragma.nim
@@ -0,0 +1,8 @@
+
+# bug #3171
+
+template newDataWindow(): untyped =
+    let eventClosure = proc (closure: pointer): bool {.closure, cdecl.} =
+        discard
+
+newDataWindow()
diff --git a/tests/pragmas/ttypedef_macro.nim b/tests/pragmas/ttypedef_macro.nim
new file mode 100644
index 000000000..dd4c87757
--- /dev/null
+++ b/tests/pragmas/ttypedef_macro.nim
@@ -0,0 +1,66 @@
+import macros
+
+macro makeref(s): untyped =
+  expectKind s, nnkTypeDef
+  result = newTree(nnkTypeDef, s[0], s[1], newTree(nnkRefTy, s[2]))
+
+type
+  Obj {.makeref.} = object
+    a: int
+
+doAssert Obj is ref
+doAssert Obj(a: 3)[].a == 3
+
+macro multiply(amount: static int, s): untyped =
+  let name = $s[0].basename
+  result = newNimNode(nnkTypeSection)
+  for i in 1 .. amount:
+    result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
+
+type
+  Foo = object
+  Bar {.multiply: 2.} = object
+    x, y, z: int
+  Baz = object
+
+let bar1 = Bar1(x: 1, y: 2, z: 3)
+let bar2 = Bar2(x: bar1.x, y: bar1.y, z: bar1.z)
+doAssert Bar1 isnot Bar2
+doAssert not declared(Bar)
+doAssert not declared(Bar3)
+
+# https://github.com/nim-lang/RFCs/issues/219
+
+macro inferKind(td): untyped =
+  let name = $td[0].basename
+  var rhs = td[2]
+  while rhs.kind in {nnkPtrTy, nnkRefTy}: rhs = rhs[0]
+  if rhs.kind != nnkObjectTy:
+    result = td
+  else:
+    for n in rhs[^1]:
+      if n.kind == nnkRecCase and n[0][^2].eqIdent"_":
+        let kindTypeName = ident(name & "Kind")
+        let en = newTree(nnkEnumTy, newEmptyNode())
+        for i in 1 ..< n.len:
+          let branch = n[i]
+          if branch.kind == nnkOfBranch:
+            for j in 0 ..< branch.len - 1:
+              en.add(branch[j])
+        n[0][^2] = kindTypeName
+        return newTree(nnkTypeSection,
+          newTree(nnkTypeDef, kindTypeName, newEmptyNode(), en),
+          td)
+
+type Node {.inferKind.} = ref object
+  case kind: _
+  of opValue: value: int
+  of opAdd, opSub, opMul, opCall: kids: seq[Node]
+
+doAssert opValue is NodeKind
+let node = Node(kind: opMul, kids: @[
+  Node(kind: opValue, value: 3),
+  Node(kind: opValue, value: 5)
+])
+doAssert node.kind == opMul
+doAssert node.kids[0].value * node.kids[1].value == 15
diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim
new file mode 100644
index 000000000..d0c533f9a
--- /dev/null
+++ b/tests/pragmas/tused.nim
@@ -0,0 +1,43 @@
+discard """
+  nimout: '''
+compile start
+tused.nim(17, 8) Hint: 'echoSub' is declared but not used [XDeclaredButNotUsed]
+compile end'''
+  output: "8\n8"
+  joinable: false
+"""
+
+# not joinable because paths in nimout differ when imported
+static:
+  echo "compile start"
+
+template implementArithOpsOld(T) =
+  proc echoAdd(a, b: T) =
+    echo a + b
+  proc echoSub(a, b: T) =
+    echo a - b
+
+template implementArithOpsNew(T) =
+  proc echoAdd(a, b: T) {.used.} =
+    echo a + b
+  proc echoSub(a, b: T) {.used.} =
+    echo a - b
+
+block:
+  # should produce warning for the unused 'echoSub'
+  implementArithOpsOld(int)
+  echoAdd 3, 5
+
+block:
+  # no warning produced for the unused 'echoSub'
+  implementArithOpsNew(int)
+  echoAdd 3, 5
+
+# issue #9896
+type
+  MyEnum {.used.} = enum
+    Val1, Val2, Val3
+
+
+static:
+  echo "compile end"
diff --git a/tests/pragmas/tuserpragma.nim b/tests/pragmas/tuserpragma.nim
new file mode 100644
index 000000000..784baa176
--- /dev/null
+++ b/tests/pragmas/tuserpragma.nim
@@ -0,0 +1,7 @@
+
+{.pragma: rtl, cdecl, exportc.}
+
+proc myproc(x, y: int): int {.rtl} =
+  nil
+
+
diff --git a/tests/pragmas/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim
new file mode 100644
index 000000000..c3f31cd5e
--- /dev/null
+++ b/tests/pragmas/tuserpragma2.nim
@@ -0,0 +1,12 @@
+discard """
+  errormsg: "can raise an unlisted exception: ref Exception"
+  file: "tuserpragma2.nim"
+  line: 11
+"""
+{.push warningAsError[Effect]: on.}
+# bug #7216
+{.pragma: my_pragma, raises: [].}
+
+proc test1 {.my_pragma.} =
+  raise newException(Exception, "msg")
+{.pop.}
diff --git a/tests/pragmas/tuserpragmaargs.nim b/tests/pragmas/tuserpragmaargs.nim
new file mode 100644
index 000000000..791d703ac
--- /dev/null
+++ b/tests/pragmas/tuserpragmaargs.nim
@@ -0,0 +1,5 @@
+var foo {.exportc: "abc".} = 123
+{.pragma: importc2, importc.}
+var bar {.importc2: "abc".}: int #[tt.Error
+                  ^ user pragma cannot have arguments]#
+echo bar
diff --git a/tests/pragmas/tvar_macro.nim b/tests/pragmas/tvar_macro.nim
new file mode 100644
index 000000000..3fb6e3e53
--- /dev/null
+++ b/tests/pragmas/tvar_macro.nim
@@ -0,0 +1,128 @@
+import macros
+
+block: # test usage
+  macro modify(sec) =
+    result = copy sec
+    result[0][0] = ident(repr(result[0][0]) & "Modified")
+
+  block:
+    let foo {.modify.} = 3
+    doAssert fooModified == 3
+
+  block: # in section 
+    let
+      a = 1
+      b {.modify.} = 2
+      c = 3
+    doAssert (a, bModified, c) == (1, 2, 3)
+
+block: # with single argument
+  macro appendToName(name: static string, sec) =
+    result = sec
+    result[0][0] = ident(repr(result[0][0]) & name)
+
+  block:
+    let foo {.appendToName: "Bar".} = 3
+    doAssert fooBar == 3
+
+  block:
+    let
+      a = 1
+      b {.appendToName("").} = 2
+      c = 3
+    doAssert (a, b, c) == (1, 2, 3)
+
+macro appendToNameAndAdd(name: static string, incr: static int, sec) =
+  result = sec
+  result[0][0] = ident(repr(result[0][0]) & name)
+  result[0][2] = infix(result[0][2], "+", newLit(incr))
+
+block: # with multiple arguments
+  block:
+    let foo {.appendToNameAndAdd("Bar", 5).} = 3
+    doAssert fooBar == 8
+
+  block:
+    let
+      a = 1
+      b {.appendToNameAndAdd("", 15).} = 2
+      c = 3
+    doAssert (a, b, c) == (1, 17, 3)
+
+block: # in other kinds of sections
+  block:
+    const
+      a = 1
+      b {.appendToNameAndAdd("", 15).} = 2
+      c = 3
+    doAssert (a, b, c) == (1, 17, 3)
+    doAssert static(b) == b
+
+  block:
+    var
+      a = 1
+      b {.appendToNameAndAdd("", 15).} = 2
+      c = 3
+    doAssert (a, b, c) == (1, 17, 3)
+    b += a
+    c += b
+    doAssert (a, b, c) == (1, 18, 21)
+
+block: # with other pragmas
+  macro appendToNameAndAdd(name: static string, incr, sec) =
+    result = sec
+    result[0][0][0] = ident(repr(result[0][0][0]) & name)
+    result[0][0][1].add(ident"deprecated")
+    result[0][2] = infix(result[0][2], "+", incr)
+
+  var
+    a = 1
+    foo {.exportc: "exportedFooBar", appendToNameAndAdd("Bar", {'0'..'9'}), used.} = {'a'..'z', 'A'..'Z'}
+    b = 2
+  
+  doAssert (a, b) == (1, 2)
+
+  let importedFooBar {.importc: "exportedFooBar", nodecl.}: set[char]
+
+  doAssert importedFooBar == fooBar #[tt.Warning
+                             ^ fooBar is deprecated
+  ]#
+  
+
+block: # with stropping
+  macro `cast`(def) =
+    let def = def[0]
+    let
+      lhs = def[0]
+      typ = def[1]
+      ex = def[2]
+      addrTyp = if typ.kind == nnkEmpty: typ else: newTree(nnkPtrTy, typ)
+    result = quote do:
+      let tmp: `addrTyp` = unsafeAddr(`ex`)
+      template `lhs`: untyped = tmp[]
+  
+  macro assign(def) =
+    result = getAst(`cast`(def))
+
+  block:
+    let s = @["foo", "bar"]
+    let a {.`assign`.} = s[0]
+    doAssert a == "foo"
+    doAssert a[0].addr == s[0][0].addr
+
+  block:
+    let
+      s = @["foo", "bar"]
+      a {.`cast`.} = s[0]
+    doAssert a == "foo"
+    doAssert a[0].addr == s[0][0].addr
+
+block: # bug #15920
+  macro foo(def) =
+    result = def
+  proc fun1()=
+    let a {.foo.} = 1
+  template fun2()=
+    let a {.foo.} = 1
+  fun1() # ok
+  fun2() # BUG
diff --git a/tests/pragmas/twarning_off.nim b/tests/pragmas/twarning_off.nim
new file mode 100644
index 000000000..ccf07b9c4
--- /dev/null
+++ b/tests/pragmas/twarning_off.nim
@@ -0,0 +1,15 @@
+discard """
+  nimout: '''
+compile start
+warn_module.nim(6, 6) Hint: 'test' is declared but not used [XDeclaredButNotUsed]
+compile end
+'''
+"""
+
+static:
+  echo "compile start"
+
+import warn_module
+
+static:
+  echo "compile end"
diff --git a/tests/pragmas/warn_module.nim b/tests/pragmas/warn_module.nim
new file mode 100644
index 000000000..0d1e5f419
--- /dev/null
+++ b/tests/pragmas/warn_module.nim
@@ -0,0 +1,7 @@
+
+{.warning[UnusedImport]: off.}
+
+import hashes
+
+proc test(a: float): float =
+  a