// 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-assert: sizeof(long) == 8 */