root/usr/src/tools/smatch/src/validation/enum-sign-gcc.c
// 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
 */