The analyzer has detected a suspicious 'switch' operator. The choice of an option is made through an enum-variable. While doing so, however, not all the possible cases are considered.
Take a look at the following example:
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
case A: Y(11); break;
case B: Y(22); break;
case C: Y(33); break;
case D: Y(44); break;
case E: Y(55); break;
}
The TEnum enumeration contains 6 named constants. But inside the 'switch' operator, only 5 of them are used. It's highly probable that this is an error.
This error often occurs as a result of careless refactoring. The programmer added the 'F' constant into 'TEnum' and fixed some of the 'switch' but forgot about the others. It resulted in the 'F' value being processed incorrectly.
The analyzer will warn about the non-used 'F' constant. Then the programmer can fix the mistake:
switch (x)
{
case A: Y(11); break;
case B: Y(22); break;
case C: Y(33); break;
case D: Y(44); break;
case E: Y(55); break;
case F: Y(66); break;
}
It's far not always that the analyzer generates the warning for cases when some of the constants of an enum are not used in 'switch'. Otherwise, there would be too many false positives. There are a number of empirical exceptions to the rule. Here are the basic ones:
The user can explicitly define a list of names for the last item in an enum. In this case, the analyzer will only use these user-defined names instead of the list of default names such as "num" or "count". The comment to control the behavior of the V719 diagnostic is as follows:
//-V719_COUNT_NAME=ABCD,FOO
You can add this comment into one of the files included into all the other ones - for example StdAfx.h.
Introduced exceptions is a deliberate decision, use-proven in practice. The only thing we should discuss in more detail is the case when warnings are not generated when there is a 'default' branch. This exception is not always good.
On the one hand, the analyzer must not go mad about non-used constants when a 'default' is present in the code. There would be too many false positives otherwise and users would simply turn off this diagnostic. On the other hand, it's quite a typical situation when you need to consider all the options in 'switch' while the 'default' branch is used to catch alert conditions. For example:
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
case A: Y(11); break;
case B: Y(22); break;
case C: Y(33); break;
case D: Y(44); break;
case E: Y(55); break;
default:
throw MyException("Ouch! One of the cases is missing!");
}
The error can be detected only at runtime. Sure, one would like this issue to be diagnosed by the analyzer as well. In the most crucial code fragments, you may do the following:
enum TEnum { A, B, C, D, E, F };
....
TEnum x = foo();
switch (x)
{
case A: Y(11); break;
case B: Y(22); break;
case C: Y(33); break;
case D: Y(44); break;
case E: Y(55); break;
#ifndef PVS_STUDIO
default:
throw MyException("Ouch! One of the cases is missing!");
#endif
}
What is used here is a predefined PVS-Studio macro. This macro is absent during compilation, so when compiling the exe file, the 'default' branch remains where it is and an exception is thrown if an error occurs.
When checking the code with PVS-Studio, the PVS_STUDIO macro is predefined and this prevents the analyzer from noticing the default-branch. Therefore, it will check 'switch', detect the non-used 'F' constant, and generate the warning.
The fixed code:
switch (x)
{
case A: Y(11); break;
case B: Y(22); break;
case C: Y(33); break;
case D: Y(44); break;
case E: Y(55); break;
case F: Y(66); break;
#ifndef PVS_STUDIO
default:
throw MyException("Ouch! One of the cases is missing!");
#endif
}
The approach described above doesn't look neat. But if you worry about some of the 'switch' and want to make sure you have protected it, this method is quite applicable.
This diagnostic is classified as:
|
You can look at examples of errors detected by the V719 diagnostic. |