cgcc

gcc -Wsign-conversion does not check enum signedness


The following program[1] is buggy because a < 0 always returns false. Clang can warn on this case with -Wconversion[2] but GCC has no warning on it.

[1]

#include <stdio.h>
enum A { a1, a2 };

int foo() { return -1; }

int main() {
        enum A a = foo();
        if (a < 0)
                printf("neg\n");
        else
                printf("pos\n");
}

[2]

$ clang -Wconversion enum1.c
enum1.c:7:13: warning: implicit conversion changes signedness: 'int' to 'enum A' [-Wsign-conversion]
        enum A a = foo();
               ~   ^~~~~
1 warning generated.

[3]

$ gcc -Wconversion -Werror enum1.c; echo $?
0
$ gcc -Wall -Wextra -Wsign-conversion -Wenum-conversion -Werror enum1.c; echo $?
0
$ gcc --version
gcc (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Solution

  • Each C implementation must choose an underlying integer type for each enumerated type (or since C23, the program can specify). This underlying type can be char or any signed or unsigned integer type.

    Clang's diagnostic seems to indicate that Clang has chosen an unsigned type as the underlying type for enum A, though it was not required to do so. GCC's lack of any diagnostic suggests that it may have chosen a signed underlying type, but its lack of a diagnostic cannot safely be taken as proof, as most diagnostics are issued at implementation discretion.

    for the following program, it's buggy because a < 0 always return false.

    I guess that's a matter of expectation, and of whose bug it is, and what the nature of the bug is. I'd be inclined to say that the program is buggy in assigning the return value of foo() to a variable of type enum A, when the return value may not (does not) correspond to any of the enumeration constants associated with enum A. I consider that a semantic error, notwithstanding the fact that C allows such assignments, and the behavior is not undefined in this instance.

    However, if you're suggesting that GCC is not behaving as documented with respect to -Wconversion then I would be inclined to agree, and to consider that a (separate) bug in GCC. In fact, it appears to be 14-year-old bug 50486.

    On the third hand, the C language is consistent with the program printing either output, so if a person reading or writing that code expects a particular result based on the code alone, then that person's expectation is not justified.