For the following code, I hope there is a warning because a
is type enum A
, but the case B1
and B2
are type enum B
; but I couldn’t find a way to make gcc/clang warn about it.
Any suggestion on how to detect the potential bugs like this?
Thanks
enum A { A1, A2 };
enum B { B1, B2 };
int foo(enum A a) {
switch(a) {
case B1:
return 1;
case B2:
return 2;
default:
return 3;
}
}
$ clang -Wall -Wextra -Wpedantic -Werror -c enum3.c; echo $?
0
$ gcc -Wall -Wextra -Wpedantic -Werror -c enum3.c; echo $?
0
$ clang --version
Ubuntu clang version 14.0.0-1ubuntu1.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ gcc --version
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
Copyright (C) 2021 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.
2
Answers
You can’t, at least not in standard C.
enum
s are a very weak abstraction in C; they’re a way to introduce named integer constants and not much more.enum
s don’t create their own namespaces, there aren’t any constraints against assigning a value of oneenum
type to a variable of anotherenum
type, etc. Enumeration constants belong to the "all other identifiers" namespace, so two different enumeration types can’t use the same enumeration constants.Do not expect C enumeration types to have the same type safety as enumeration types in Java or C#.
As others have noted, there does not appear to be any
warning built in to GCC or Clang to do this. There is also no
clang-tidy
check for it.
However, it is possible to write a check condition for this using
clang-query
.The following check will report any
switch
whose condition expressionhas enumeration type, and it has a
case
that has a case constant thathas a different enumeration type:
When run on this input:
it produces this output:
For more details on what the elements of the query do, see the Clang
AST Matcher Reference.
It’s pretty terse though, so trial and error is required to make use of
it.
FWIW, I ran this over a couple large-ish C++ translation units I had
at hand and it didn’t report anything. So while I haven’t really done
any "tuning" of the query it appears to not explode with noise.
Of course, adding a custom
clang-query
command to your build is muchmore work than just adding a compiler warning option, but it’s perhaps
something to experiment with at least.