diff options
Diffstat (limited to 'tests/pragmas')
28 files changed, 842 insertions, 58 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/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/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/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/t8741.nim b/tests/pragmas/t8741.nim index 61a449c01..bf97b0e29 100644 --- a/tests/pragmas/t8741.nim +++ b/tests/pragmas/t8741.nim @@ -1,7 +1,7 @@ discard """ - cmd: "nim check --hint[processing]:off $file" + cmd: "nim check --hint:processing:off $file" errormsg: "3 is not two" - nimout: '''t8741.nim(13, 9) Error: cannot attach a custom pragma to 'a' + 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 ''' diff --git a/tests/pragmas/tbitsize.nim b/tests/pragmas/tbitsize.nim index 7a44944d2..39aee445f 100644 --- a/tests/pragmas/tbitsize.nim +++ b/tests/pragmas/tbitsize.nim @@ -10,13 +10,13 @@ type var b: bits -assert b.flag == 0 +doAssert b.flag == 0 b.flag = 1 -assert b.flag == 1 +doAssert b.flag == 1 b.flag = 2 -assert b.flag == 0 +doAssert b.flag == 0 b.opts = 7 -assert b.opts == 7 +doAssert b.opts == 7 b.opts = 9 -assert b.opts == -7 +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 index b306045e0..11a6df813 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -8,7 +8,7 @@ block: proc myProc():int {.myAttr.} = 2 const hasMyAttr = myProc.hasCustomPragma(myAttr) static: - assert(hasMyAttr) + doAssert(hasMyAttr) block: template myAttr(a: string) {.pragma.} @@ -17,10 +17,26 @@ block: MyObj = object myField1, myField2 {.myAttr: "hi".}: int + MyGenericObj[T] = object + myField1, myField2 {.myAttr: "hi".}: int + + MyOtherObj = MyObj + + var o: MyObj static: - assert o.myField2.hasCustomPragma(myAttr) - assert(not o.myField1.hasCustomPragma(myAttr)) + 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 @@ -42,31 +58,31 @@ block: # A bit more advanced case var s: MySerializable const aDefVal = s.a.getCustomPragmaVal(defaultValue) - static: assert(aDefVal == 5) + static: doAssert(aDefVal == 5) const aSerKey = s.a.getCustomPragmaVal(serializationKey) - static: assert(aSerKey == "asdf") + static: doAssert(aSerKey == "asdf") const cSerKey = getCustomPragmaVal(s.field.c, serializationKey) - static: assert(cSerKey == "cc") + static: doAssert(cSerKey == "cc") const procSerKey = getCustomPragmaVal(myproc, serializationKey) - static: assert(procSerKey == "myprocSS") + static: doAssert(procSerKey == "myprocSS") - static: assert(hasCustomPragma(myproc, alternativeKey)) + static: doAssert(hasCustomPragma(myproc, alternativeKey)) const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue) - static: assert(hasFieldCustomPragma == false) + static: doAssert(hasFieldCustomPragma == false) # pragma on an object static: - assert Subfield.hasCustomPragma(defaultValue) - assert(Subfield.getCustomPragmaVal(defaultValue) == "catman") + doAssert Subfield.hasCustomPragma(defaultValue) + doAssert(Subfield.getCustomPragmaVal(defaultValue) == "catman") - assert hasCustomPragma(type(s.field), defaultValue) + doAssert hasCustomPragma(type(s.field), defaultValue) proc foo(s: var MySerializable) = - static: assert(s.a.getCustomPragmaVal(defaultValue) == 5) + static: doAssert(s.a.getCustomPragmaVal(defaultValue) == 5) foo(s) @@ -91,8 +107,8 @@ block: # ref types leftSerKey = getCustomPragmaVal(s.left, serializationKey) rightSerKey = getCustomPragmaVal(s.right, serializationKey) static: - assert leftSerKey == "l" - assert rightSerKey == "r" + doAssert leftSerKey == "l" + doAssert rightSerKey == "r" var specS = SpecialNodeRef() @@ -100,25 +116,25 @@ block: # ref types dataDefVal = hasCustomPragma(specS.data, defaultValue) specLeftSerKey = hasCustomPragma(specS.left, serializationKey) static: - assert dataDefVal == true - assert specLeftSerKey == true + doAssert dataDefVal == true + doAssert specLeftSerKey == true var ptrS = NodePtr(nil) const ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey) static: - assert ptrRightSerKey == "r" + doAssert ptrRightSerKey == "r" var f = MyFile() const fileDefVal = f.getCustomPragmaVal(defaultValue) filePathDefVal = f.path.getCustomPragmaVal(defaultValue) static: - assert fileDefVal == "closed" - assert filePathDefVal == "invalid" + doAssert fileDefVal == "closed" + doAssert filePathDefVal == "invalid" static: - assert TypeWithoutPragma.hasCustomPragma(defaultValue) == false + doAssert TypeWithoutPragma.hasCustomPragma(defaultValue) == false block: type @@ -144,9 +160,9 @@ block: nestedItemDefVal = vari.nestedItem.getCustomPragmaVal(defaultValue) static: - assert hasIntSerKey - assert strSerKey == "string" - assert nestedItemDefVal == "Nimmers of the world, unite!" + doAssert hasIntSerKey + doAssert strSerKey == "string" + doAssert nestedItemDefVal == "Nimmers of the world, unite!" block: template simpleAttr {.pragma.} @@ -154,15 +170,25 @@ block: type Annotated {.simpleAttr.} = object proc generic_proc[T]() = - assert Annotated.hasCustomPragma(simpleAttr) - + doAssert Annotated.hasCustomPragma(simpleAttr) #-------------------------------------------------------------------------- # Pragma on proc type -let a: proc(x: int) {.defaultValue(5).} = nil +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.type, defaultValue) + 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.} @@ -252,7 +278,11 @@ block: block: macro expectedAst(expectedRepr: static[string], input: untyped): untyped = - assert input.treeRepr & "\n" == expectedRepr + doAssert input.treeRepr & "\n" == expectedRepr + return input + + macro expectedAstRepr(expectedRepr: static[string], input: untyped): untyped = + doAssert input.repr == expectedRepr return input const procTypeAst = """ @@ -270,25 +300,15 @@ ProcTy type Foo = proc (x: int) {.expectedAst(procTypeAst), async.} - static: assert Foo is proc(x: int): Future[void] + static: doAssert Foo is proc(x: int): Future[void] const asyncProcTypeAst = """ -ProcTy - FormalParams - BracketExpr - Ident "Future" - Ident "void" - IdentDefs - Ident "s" - Ident "string" - Empty - Pragma -""" - +proc (s: string): Future[void] {..}""" + # using expectedAst would show `OpenSymChoice` for Future[void], which is fragile. type - Bar = proc (s: string) {.async, expectedAst(asyncProcTypeAst).} + Bar = proc (s: string) {.async, expectedAstRepr(asyncProcTypeAst).} - static: assert Bar is proc(x: string): Future[void] + static: doAssert Bar is proc(x: string): Future[void] const typeAst = """ TypeDef @@ -310,7 +330,7 @@ TypeDef Baz {.expectedAst(typeAst).} = object x: string - static: assert Baz.x is string + static: doAssert Baz.x is string const procAst = """ ProcDef @@ -333,10 +353,10 @@ ProcDef proc bar(s: string): string {.expectedAst(procAst).} = return s - static: assert bar("x") == "x" + static: doAssert bar("x") == "x" #------------------------------------------------------ -# issue #13909 +# bug #13909 template dependency*(id: string, weight = 0.0) {.pragma.} @@ -345,4 +365,176 @@ type provider*: proc(obj: string): pointer {.dependency("Data/" & obj, 16.1), noSideEffect.} proc myproc(obj: string): string {.dependency("Data/" & obj, 16.1).} = - result = obj \ No newline at end of file + 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/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 index ba66a2dca..5d6fcdd9c 100644 --- a/tests/pragmas/tlocks.nim +++ b/tests/pragmas/tlocks.nim @@ -1,4 +1,3 @@ - type SomeBase* = ref object of RootObj type SomeDerived* = ref object of SomeBase memberProc*: proc () diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim index 6d0466df3..6a58055fe 100644 --- a/tests/pragmas/tnoreturn.nim +++ b/tests/pragmas/tnoreturn.nim @@ -1,4 +1,5 @@ discard """ +matrix: "--mm:refc" ccodeCheck: "\\i @'__attribute__((noreturn))' .*" action: compile """ 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 index 247fa471e..adb7e73c3 100644 --- a/tests/pragmas/tpragmas_misc.nim +++ b/tests/pragmas/tpragmas_misc.nim @@ -10,3 +10,66 @@ block: 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 index 5ecfe9704..9c6b85c4e 100644 --- a/tests/pragmas/tpush.nim +++ b/tests/pragmas/tpush.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + # test the new pragmas {.push warnings: off, hints: off.} @@ -13,3 +17,128 @@ proc WarnMe() = 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/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/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/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim index ce16c4649..c3f31cd5e 100644 --- a/tests/pragmas/tuserpragma2.nim +++ b/tests/pragmas/tuserpragma2.nim @@ -3,9 +3,10 @@ discard """ 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 index d5d31d4c2..ccf07b9c4 100644 --- a/tests/pragmas/twarning_off.nim +++ b/tests/pragmas/twarning_off.nim @@ -1,7 +1,6 @@ discard """ nimout: ''' compile start -.. warn_module.nim(6, 6) Hint: 'test' is declared but not used [XDeclaredButNotUsed] compile end ''' |