summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2020-04-23 02:24:09 -0700
committerGitHub <noreply@github.com>2020-04-23 11:24:09 +0200
commit66db9de714be7c2f4cf1f2fb0a0a99145baf6acb (patch)
tree8675842299fe22ad237b06bb923a880789c9faa4 /tests
parent5c534b2943145106db99212fb9bb75fde289b6f5 (diff)
downloadNim-66db9de714be7c2f4cf1f2fb0a0a99145baf6acb.tar.gz
CT sizeof(+friends) for {.importc, completeStruct.} types, enable ABI static checks (#13926)
* -d:checkabi obsolete (ABI check now enforced); add `addTypeHeader` helper
* cleanups
* import sizeof at CT for {.completeType.}
* address comments; revert default enabling of -d:checkAbi for now
* mimportc_size_check.nim => msizeof5.nim; merge mabi_check.nim into msizeof5.nim; refactor
* all pragmas in errmsgs should be written: '.importc' (un-ambiguous and less verbose than {.importc.})
Diffstat (limited to 'tests')
-rw-r--r--tests/misc/msizeof5.nim131
-rw-r--r--tests/misc/tsizeof2.nim2
-rw-r--r--tests/trunner.nim42
3 files changed, 161 insertions, 14 deletions
diff --git a/tests/misc/msizeof5.nim b/tests/misc/msizeof5.nim
new file mode 100644
index 000000000..c833d1e43
--- /dev/null
+++ b/tests/misc/msizeof5.nim
@@ -0,0 +1,131 @@
+## tests for -d:checkAbi used by addAbiCheck via NIM_STATIC_ASSERT
+
+{.emit:"""/*TYPESECTION*/
+struct Foo1{
+  int a;
+};
+struct Foo2{
+  int a;
+};
+enum Foo3{k1, k2};
+typedef enum Foo3 Foo3b;
+typedef enum Foo4{k3, k4} Foo4;
+
+typedef int Foo5[3];
+
+typedef struct Foo6{
+  int a1;
+  bool a2;
+  double a3;
+  struct Foo6* a4;
+} Foo6;
+""".}
+
+template ensureCgen(T: typedesc) =
+  ## ensures cgen
+  var a {.volatile.}: T
+
+block:
+  type Foo1Alias{.importc: "struct Foo1", size: sizeof(cint).} = object
+    a: cint
+  ensureCgen Foo1Alias
+
+block:
+  type Foo3Alias{.importc: "enum Foo3", size: sizeof(cint).} = enum
+    k1, k2
+  ensureCgen Foo3Alias
+
+block:
+  type Foo3bAlias{.importc: "Foo3b", size: sizeof(cint).} = enum
+    k1, k2
+  ensureCgen Foo3bAlias
+
+block:
+  type Foo3b{.importc, size: sizeof(cint).} = enum
+    k1, k2
+  ensureCgen Foo3b
+  static:
+    doAssert Foo3b.sizeof == cint.sizeof
+
+block:
+  type Foo4{.importc, size: sizeof(cint).} = enum
+    k3, k4
+  # adding entries should not yield duplicate ABI checks, as enforced by
+  # `typeABICache`.
+  # Currently the test doesn't check for this but you can inspect the cgen'd file
+  ensureCgen Foo4
+  ensureCgen Foo4
+  ensureCgen Foo4
+
+block:
+  type Foo5{.importc.} = array[3, cint]
+  ensureCgen Foo5
+
+block:
+  type Foo5{.importc.} = array[3, cint]
+  ensureCgen Foo5
+
+block: # CT sizeof
+  type Foo6GT = object # grountruth
+    a1: cint
+    a2: bool
+    a3: cfloat
+    a4: ptr Foo6GT
+
+  type Foo6{.importc, completeStruct.} = object
+    a1: cint
+    a2: bool
+    a3: cfloat
+    a4: ptr Foo6
+
+  static: doAssert compiles(static(Foo6.sizeof))
+  static: doAssert Foo6.sizeof == Foo6GT.sizeof
+  static: doAssert (Foo6, int, array[2, Foo6]).sizeof ==
+    (Foo6GT, int, array[2, Foo6GT]).sizeof
+
+block:
+  type GoodImportcType {.importc: "signed char", nodecl.} = char
+    # "good" in sense the sizeof will match
+  ensureCgen GoodImportcType
+
+block:
+  type Foo6{.importc.} = object
+    a1: cint
+  doAssert compiles(Foo6.sizeof)
+  static: doAssert not compiles(static(Foo6.sizeof))
+
+when defined caseBad:
+  # Each case below should give a static cgen assert fail message
+
+  block:
+    type BadImportcType {.importc: "unsigned char", nodecl.} = uint64
+      # "sizeof" check will fail
+    ensureCgen BadImportcType
+
+  block:
+    type Foo2AliasBad{.importc: "struct Foo2", size: 1.} = object
+      a: cint
+    ensureCgen Foo2AliasBad
+
+  block:
+    type Foo5{.importc.} = array[4, cint]
+    ensureCgen Foo5
+
+  block:
+    type Foo5{.importc.} = array[3, bool]
+    ensureCgen Foo5
+
+  block:
+    type Foo6{.importc, completeStruct.} = object
+      a1: cint
+      # a2: bool # missing this should trigger assert fail
+      a3: cfloat
+      a4: ptr Foo6
+    ensureCgen Foo6
+
+  when false:
+    block:
+      # pre-existing BUG: this should give a CT error in semcheck because `size`
+      # disagrees with `array[3, cint]`
+      type Foo5{.importc, size: 1.} = array[3, cint]
+      ensureCgen Foo5
diff --git a/tests/misc/tsizeof2.nim b/tests/misc/tsizeof2.nim
index a193cf7c3..da28de508 100644
--- a/tests/misc/tsizeof2.nim
+++ b/tests/misc/tsizeof2.nim
@@ -1,5 +1,5 @@
 discard """
-errormsg: "cannot evaluate 'sizeof' because its type is not defined completely"
+errormsg: "'sizeof' requires '.importc' types to be '.completeStruct'"
 line: 9
 """
 
diff --git a/tests/trunner.nim b/tests/trunner.nim
index 7e1468e84..263184571 100644
--- a/tests/trunner.nim
+++ b/tests/trunner.nim
@@ -19,14 +19,10 @@ proc runCmd(file, options = ""): auto =
     echo result[0]
     echo result[1]
 
-proc testCodegenStaticAssert() =
-  let (output, exitCode) = runCmd("ccgbugs/mstatic_assert.nim")
-  doAssert "sizeof(bool) == 2" in output
-  doAssert exitCode != 0
-
-proc testCTFFI() =
-  let (output, exitCode) = runCmd("vm/mevalffi.nim", "--experimental:compiletimeFFI")
-  let expected = """
+when defined(nimHasLibFFIEnabled):
+  block: # mevalffi
+    let (output, exitCode) = runCmd("vm/mevalffi.nim", "--experimental:compiletimeFFI")
+    let expected = """
 hello world stderr
 hi stderr
 foo
@@ -37,10 +33,30 @@ foo:102:103:104
 foo:0.03:asdf:103:105
 ret={s1:foobar s2:foobar age:25 pi:3.14}
 """
-  doAssert output == expected, output
-  doAssert exitCode == 0
+    doAssert output == expected, output
+    doAssert exitCode == 0
 
-when defined(nimHasLibFFIEnabled):
-  testCTFFI()
 else: # don't run twice the same test
-  testCodegenStaticAssert()
+  template check(msg) = doAssert msg in output, output
+
+  block: # mstatic_assert
+    let (output, exitCode) = runCmd("ccgbugs/mstatic_assert.nim", "-d:caseBad")
+    check "sizeof(bool) == 2"
+    doAssert exitCode != 0
+
+  block: # ABI checks
+    let file = "misc/msizeof5.nim"
+    block:
+      let (output, exitCode) = runCmd(file, "-d:checkAbi")
+      doAssert exitCode == 0, output
+    block:
+      let (output, exitCode) = runCmd(file, "-d:checkAbi -d:caseBad")
+      # on platforms that support _StaticAssert natively, errors will show full context, eg:
+      # error: static_assert failed due to requirement 'sizeof(unsigned char) == 8'
+      # "backend & Nim disagree on size for: BadImportcType{int64} [declared in mabi_check.nim(1, 6)]"
+      check "sizeof(unsigned char) == 8"
+      check "sizeof(struct Foo2) == 1"
+      check "sizeof(Foo5) == 16"
+      check "sizeof(Foo5) == 3"
+      check "sizeof(struct Foo6) == "
+      doAssert exitCode != 0