diff mbox series

[05/12] enum: add testcase for base & enumerator type

Message ID 20180908000046.65842-6-luc.vanoostenryck@gmail.com (mailing list archive)
State Mainlined, archived
Headers show
Series fixes for enum's base type | expand

Commit Message

Luc Van Oostenryck Sept. 8, 2018, midnight UTC
Add various testcases for checking enum's base & enumerator type.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 validation/enum-base-type.c      | 29 +++++++++++++++
 validation/enum-bitwise.c        | 19 ++++++++++
 validation/enum-bounds.c         | 24 ++++++++++++
 validation/enum-init-constness.c |  9 +++++
 validation/enum-invalid.c        | 11 ++++++
 validation/enum-min-size.c       | 30 +++++++++++++++
 validation/enum-sign-gcc.c       | 63 ++++++++++++++++++++++++++++++++
 validation/enum-typecheck.c      | 39 ++++++++++++++++++++
 8 files changed, 224 insertions(+)
 create mode 100644 validation/enum-base-type.c
 create mode 100644 validation/enum-bitwise.c
 create mode 100644 validation/enum-bounds.c
 create mode 100644 validation/enum-init-constness.c
 create mode 100644 validation/enum-invalid.c
 create mode 100644 validation/enum-min-size.c
 create mode 100644 validation/enum-sign-gcc.c
 create mode 100644 validation/enum-typecheck.c
diff mbox series

Patch

diff --git a/validation/enum-base-type.c b/validation/enum-base-type.c
new file mode 100644
index 000000000..ecec59296
--- /dev/null
+++ b/validation/enum-base-type.c
@@ -0,0 +1,29 @@ 
+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-known-to-fail
+ */
diff --git a/validation/enum-bitwise.c b/validation/enum-bitwise.c
new file mode 100644
index 000000000..fcdb8d7a0
--- /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 000000000..d8993edb4
--- /dev/null
+++ b/validation/enum-bounds.c
@@ -0,0 +1,24 @@ 
+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-known-to-fail
+ */
diff --git a/validation/enum-init-constness.c b/validation/enum-init-constness.c
new file mode 100644
index 000000000..5b95bc06a
--- /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 000000000..08846442d
--- /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 000000000..264a31542
--- /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 000000000..c4779dbe6
--- /dev/null
+++ b/validation/enum-sign-gcc.c
@@ -0,0 +1,63 @@ 
+// 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-known-to-fail
+ */
diff --git a/validation/enum-typecheck.c b/validation/enum-typecheck.c
new file mode 100644
index 000000000..77b77b47b
--- /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
+ */