Pour obtenir une clé
d'essai remplissez le formulaire ci-dessous
Demandez des tariffs
Nouvelle licence
Renouvellement de licence
--Sélectionnez la devise--
USD
EUR
RUB
* En cliquant sur ce bouton, vous acceptez notre politique de confidentialité

Free PVS-Studio license for Microsoft MVP specialists
To get the licence for your open-source project, please fill out this form
** En cliquant sur ce bouton, vous acceptez notre politique de confidentialité.

I am interested to try it on the platforms:
** En cliquant sur ce bouton, vous acceptez notre politique de confidentialité.

Votre message a été envoyé.

Nous vous répondrons à


Si vous n'avez toujours pas reçu de réponse, vérifiez votre dossier
Spam/Junk et cliquez sur le bouton "Not Spam".
De cette façon, vous ne manquerez la réponse de notre équipe.

>
>
>
V1016. The value is out of range of enu…
Analyzer diagnostics
General Analysis (C++)
General Analysis (C#)
General Analysis (Java)
Diagnosis of micro-optimizations (C++)
Diagnosis of 64-bit errors (Viva64, C++)
Customer specific requests (C++)
MISRA errors
AUTOSAR errors
OWASP errors (C#)
Problems related to code analyzer
Additional information
Contents

V1016. The value is out of range of enum values. This causes unspecified or undefined behavior.

20 Jan 2021

The analyzer detected a dangerous cast from a numeric type to an enumeration. The specified number may not be in the range of 'enum' values.

Note 1: This rule is only relevant for the C++ language. The underlying 'enum' type is always 'int' in the C language.

Note 2: This rule is only relevant for C++ compilers that calculate the actual size of 'enum' according to the standard. For example, such compilers are GCC and Clang. MSVC compiler doen't fall into this category, since it calculates the 'enum' size for backward compatibility purposes according to the rules of the C language. It always uses the 'int' type as the underlying type, unless a different type is specified.

The result of casting a number whose value is not in the range of 'enum' elements is unspecified behavior up to C++17 and undefined behavior starting from C++17.

If an underlying type is specified for 'enum', then all values that can fit into this type can be cast to this 'enum' type.

Example 1:

enum class byte : unsigned char {}; // Range: [0; 255]
byte b1 = static_cast<byte>(255);   // ok

The number 256 no longer fits in the 'char' type, so this code is incorrect:

byte b2 = static_cast<byte>(256);   // UB

If an underlying type is not specified, then, according to the standard, the compiler tries to fit the values depending on the initializer into the following types:

int -> unsigned int -> long -> unsigned long ->
  long long -> unsigned long long

Within the selected type, the compiler uses the minimum required number of bits (n) that can fit the maximum number in the enumeration. In such an 'enum', you can fit the range of values [- (2^n) / 2; 2^n / 2 - 1] for 'enum' with a signed underlying type and [0; 2^n - 1] for 'enum' with an unsigned underlying type. Bounds violation of this range is unspecified behavior (before C++17) or undefined behavior (since C++17).

Example 2:

enum foo { a = 0, b = UINT_MAX }; // Range: [0; UINT_MAX]
foo x = foo(-1);                  // UB

At first glance, this code is correct, but in fact it can result in troubles. The underlying 'enum' type is set to 'unsigned int'. The number '-1' does not fall within the range of this type, so such an assignment may lead to unspecified or undefined behavior.

Example 3.

enum EN { low = 2, high = 4 }; // Uses 3 bits, range: [0; 7]
EN a1 = static_cast<EN>(7);    // ok

According to the standard, the underlying type for this enum is 'int'. Inside this type, the compiler uses the minimum width of the bit field that can fit all the values of enum constants.

In this case, you will need at least 3 bits to fit all the values (2 = 0b010 and 4 = 0b100), so an EN variable can fit numbers from 0 (0b000) to 7 (0b111) inclusively. The number 8 already occupies four bits (0b1000), so it no longer fits in the EN type:

EN a2 = static_cast<EN>(8);    // UB

UndefinedBehaviorSanitizer also finds an error in this example: https://godbolt.org/z/GGYo7z.

At the same time, if you specify the underlying type for EN, for example, 'unsigned char', then this will be the correct code version:

enum EN : unsigned char { low = 2, high = 4 }; // Range: [0; 255]
EN a2 = static_cast<EN>(8);                    // ok

This diagnostic is classified as:

Unicorn with delicious cookie
Nous utilisons des cookies pour améliorer votre expérience de navigation. En savoir plus
Accepter