summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-05-02 09:04:41 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-10-05 03:29:19 +0200
commit5afb6e9ffe1687cee5648b11d59d05edeb063033 (patch)
tree2249e7cc4738ead7b3102e2c19f1219331bafd80
parent1a889a2e2efa56c3966add10a4db2aa08dbc8129 (diff)
downloadsparse-5afb6e9ffe1687cee5648b11d59d05edeb063033.tar.gz
enum: add testcase for base & enumerator type
Add various testcases for checking enum's base & enumerator type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--validation/enum-base-type.c30
-rw-r--r--validation/enum-bitwise.c19
-rw-r--r--validation/enum-bounds.c25
-rw-r--r--validation/enum-init-constness.c9
-rw-r--r--validation/enum-invalid.c11
-rw-r--r--validation/enum-min-size.c30
-rw-r--r--validation/enum-sign-gcc.c64
-rw-r--r--validation/enum-typecheck.c39
8 files changed, 227 insertions, 0 deletions
diff --git a/validation/enum-base-type.c b/validation/enum-base-type.c
new file mode 100644
index 00000000..e430290b
--- /dev/null
+++ b/validation/enum-base-type.c
@@ -0,0 +1,30 @@
+enum n {
+ NA,
+ NB = 1L,
+ NC = 1UL,
+ ND = 1LL,
+ NE = 1ULL,
+ NF = -1,
+ NG = -1L,
+ NH = -1LL,
+};
+_Static_assert(sizeof(enum n) == sizeof(int), "+-1");
+
+enum m {
+ MA = 0L,
+ MB = 1L,
+ MG = -1L,
+};
+_Static_assert(sizeof(enum m) == sizeof(int), "+-1L");
+
+enum p {
+ PA = 0UL,
+ PB = 1UL,
+};
+_Static_assert(sizeof(enum p) == sizeof(int), "UL");
+
+/*
+ * check-name: enum-base-type
+ * check-command: sparse -m64 $file
+ * check-known-to-fail
+ */
diff --git a/validation/enum-bitwise.c b/validation/enum-bitwise.c
new file mode 100644
index 00000000..fcdb8d7a
--- /dev/null
+++ b/validation/enum-bitwise.c
@@ -0,0 +1,19 @@
+#define __bitwise __attribute__((bitwise))
+#define __force __attribute__((force))
+
+typedef long long __bitwise bits;
+
+enum r {
+ RZ = (__force bits) 0,
+ RO = (__force bits) 1,
+ RM = (__force bits) -1,
+};
+
+_Static_assert([typeof(RZ)] == [bits], "RZ");
+_Static_assert([typeof(RO)] == [bits], "RO");
+_Static_assert([typeof(RM)] == [bits], "RM");
+_Static_assert(sizeof(enum r) == sizeof(bits), "bits");
+
+/*
+ * check-name: enum-bitwise
+ */
diff --git a/validation/enum-bounds.c b/validation/enum-bounds.c
new file mode 100644
index 00000000..604e0f33
--- /dev/null
+++ b/validation/enum-bounds.c
@@ -0,0 +1,25 @@
+enum bound_int_max {
+ IMAX = __INT_MAX__,
+};
+_Static_assert([typeof(IMAX)] == [int], "");
+
+enum bound_int_maxp1 {
+ IMP1 = __INT_MAX__ + 1L,
+};
+_Static_assert([typeof(IMP1)] == [unsigned int], "");
+
+enum bound_int_maxm1 {
+ IMM1 = -__INT_MAX__ - 1L,
+};
+_Static_assert([typeof(IMM1)] == [int], "");
+
+enum bound_int_maxm2 {
+ IMM2 = -__INT_MAX__ - 2L,
+};
+_Static_assert([typeof(IMM2)] == [long], "");
+
+/*
+ * check-name: enum-bounds
+ * check-command: sparse -m64 $file
+ * check-known-to-fail
+ */
diff --git a/validation/enum-init-constness.c b/validation/enum-init-constness.c
new file mode 100644
index 00000000..5b95bc06
--- /dev/null
+++ b/validation/enum-init-constness.c
@@ -0,0 +1,9 @@
+extern int invalid;
+
+enum e {
+ E = 1 ? 1 : invalid
+};
+
+/*
+ * check-name: enum-init-constness
+ */
diff --git a/validation/enum-invalid.c b/validation/enum-invalid.c
new file mode 100644
index 00000000..08846442
--- /dev/null
+++ b/validation/enum-invalid.c
@@ -0,0 +1,11 @@
+enum e { };
+enum f { F = 0.1 };
+
+/*
+ * check-name: enum-invalid
+ *
+ * check-error-start
+enum-invalid.c:1:10: error: bad enum definition
+enum-invalid.c:2:14: error: bad constant expression
+ * check-error-end
+ */
diff --git a/validation/enum-min-size.c b/validation/enum-min-size.c
new file mode 100644
index 00000000..264a3154
--- /dev/null
+++ b/validation/enum-min-size.c
@@ -0,0 +1,30 @@
+enum i { I = 1 };
+_Static_assert(sizeof(enum i) == sizeof(int), "int");
+enum u { U = 1U };
+_Static_assert(sizeof(enum u) == sizeof(int), "uint");
+
+enum l { L = 1L };
+_Static_assert(sizeof(enum l) == sizeof(int), "long");
+enum m { M = 1UL };
+_Static_assert(sizeof(enum m) == sizeof(int), "ulong");
+
+enum n { N = 1LL };
+_Static_assert(sizeof(enum n) == sizeof(int), "llong");
+enum o { O = 1ULL };
+_Static_assert(sizeof(enum o) == sizeof(int), "ullong");
+
+
+enum mi { MI = -1 };
+_Static_assert(sizeof(enum i) == sizeof(int), "int");
+
+enum ml { ML = -1L };
+_Static_assert(sizeof(enum l) == sizeof(int), "long");
+
+enum mn { MN = -1LL };
+_Static_assert(sizeof(enum n) == sizeof(int), "llong");
+
+
+/*
+ * check-name: enum-min-size
+ * check-known-to-fail
+ */
diff --git a/validation/enum-sign-gcc.c b/validation/enum-sign-gcc.c
new file mode 100644
index 00000000..a442bf0b
--- /dev/null
+++ b/validation/enum-sign-gcc.c
@@ -0,0 +1,64 @@
+// For enum's underlying/compatible type:
+// std C: unspecified
+// GCC: 'unsigned int' if no negative values,
+// otherwise 'int' (see GCC manul 4.9).
+// But also accept ulong, long
+// For the type of the enumerators:
+// std C: 'int'
+// GCC: 'int' if the value fit in a 'int'
+// otherwise same as the enum underlying type?
+//
+// The following tests match GCC's choices
+
+#define is_unsigned(X) ((typeof(X))-1 > 0)
+
+enum u {
+ U = 1U, // fit in 'int'
+ // no negatives
+};
+_Static_assert(sizeof(enum u) == sizeof(int), "size");
+_Static_assert(is_unsigned(enum u), "enum u");
+_Static_assert(is_unsigned(U) == 0, "value U"); // fail
+
+enum v {
+ V = __INT_MAX__ + 1U, // doesn't fit in 'int'
+ // no negatives
+};
+_Static_assert(sizeof(enum v) == sizeof(int), "size");
+_Static_assert(is_unsigned(enum v), "enum v");
+_Static_assert(is_unsigned(V) == 1, "value V");
+
+enum w {
+ W = __LONG_MAX__ + 1UL, // doesn't fit in 'long'
+};
+_Static_assert(sizeof(enum w) == sizeof(long), "size");
+_Static_assert(is_unsigned(enum w), "enum w");
+_Static_assert(is_unsigned(W) == 1, "value W");
+
+enum x {
+ A = 1, // fit in 'int'
+ B = 0x100000000UL, // doesn't fit in int
+};
+_Static_assert(sizeof(enum x) == sizeof(long), "size");
+_Static_assert(is_unsigned(enum x), "enum x");
+_Static_assert(sizeof(A) == sizeof(int), "size A"); // fail
+_Static_assert(is_unsigned(A) == 0, "enum A"); // fail
+_Static_assert(sizeof(B) == sizeof(long), "size B");
+_Static_assert(is_unsigned(B) == 1, "enum B");
+
+enum y {
+ C = 1, // fit in 'int'
+ D = 0x100000000L, // doesn't fit in int
+};
+_Static_assert(sizeof(enum y) == sizeof(long), "size");
+_Static_assert(is_unsigned(enum y), "enum y");
+_Static_assert(sizeof(C) == sizeof(int), "size C"); // fail
+_Static_assert(is_unsigned(C) == 0, "enum C"); // fail
+_Static_assert(sizeof(D) == sizeof(long), "size D");
+_Static_assert(is_unsigned(D) == 1, "enum D");
+
+/*
+ * check-name: enum-sign-gcc
+ * check-command: sparse -m64 $file
+ * check-known-to-fail
+ */
diff --git a/validation/enum-typecheck.c b/validation/enum-typecheck.c
new file mode 100644
index 00000000..77b77b47
--- /dev/null
+++ b/validation/enum-typecheck.c
@@ -0,0 +1,39 @@
+enum good { G, };
+enum bad { B, };
+enum good g;
+
+enum good compat_int(void) { return 1; }
+
+void parg(enum good);
+void parg(enum bad);
+
+void farg(enum good a);
+void farg(enum bad a) { }
+
+enum good pret(void);
+enum bad pret(void);
+
+enum good fret(void);
+enum bad fret(void) { return 0; }
+
+
+enum good *ptr;
+enum bad *ptr;
+
+enum good *gptr = &g;
+enum bad *bptr = &g;
+
+/*
+ * check-name: enum-typecheck
+ * check-command: sparse -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-error-start
+enum-typecheck.c:8:6: error: symbol 'parg' redeclared with different type
+enum-typecheck.c:11:6: error: symbol 'farg' redeclared with different type
+enum-typecheck.c:14:11: error: symbol 'pret' redeclared with different type
+enum-typecheck.c:17:11: error: symbol 'fret' redeclared with different type
+enum-typecheck.c:21:12: error: symbol 'ptr' redeclared with different type
+enum-typecheck.c:24:20: warning: incorrect type in initializer (different type sizes)
+ * check-error-end
+ */