Main Content

MISRA C++:2023 Rule 10.2.3

The numeric value of an unscoped enumeration with no fixed underlying type shall not be used

Since R2024b

Description

Rule Definition

The numeric value of an unscoped enumeration with no fixed underlying type shall not be used.

Rationale

By default, the underlying type of an enumeration is implementation-defined. This can cause unexpected results if any implicit conversion occurs. Code that relies on the size or properties of the underlying type might not work consistently across different systems. When overloading functions, the compiler's choice of the underlying type can affect which overload is selected, potentially leading to surprising results if the function has overloads for different integer types.

Polyspace Implementation

The rule checker reports a violation when the code uses an unscoped enumeration with no fixed underlying type and you perform an operation on the enum that depends on the underlying type. For example, when the enumeration is the operand to a bitwise operator. This can also happen when the enumeration is the condition of a switch statement where the case constants are not from the same enumeration. For example:

enum A { x, y };
enum B { z };

int main() {

	switch (x)	//Noncompliant
	{
	case y: 
		//...
		return;
	case z: 
		//...
		return;
	}

	return 0;
}

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include <iostream>

enum ErrorCode {
    SUCCESS = 0,
    NETWORK_ERROR,
    DISK_ERROR,
    UNKNOWN_ERROR
};

void logError(int errorCode) {
    std::cout << "Error code: " << errorCode << std::endl;
}

int main() {
    ErrorCode error = NETWORK_ERROR;
    logError(error);
    int nextError = error + 1;			//Noncompliant

    return 0;
}

In this example, ErrorCode is an unscoped enumeration with no fixed underlying type. The violation occurs when the code performs arithmetic on error to calculate nextError, which uses the numeric value of the enumeration.

To avoid this violation in this example, define the enum with a fixed underlying type. You can use a static_cast when the target type is an unscoped enumeration and the enumeration type has a fixed underlying type.

#include <iostream>

enum class ErrorCode : int {
    SUCCESS = 0,
    NETWORK_ERROR,
    DISK_ERROR  ,
    UNKNOWN_ERROR
};

void logError(int errorCode) {
    std::cout << "Error code: " << errorCode << std::endl;
}

int toInt(ErrorCode errorCode) {    
    return static_cast<int>(errorCode);      //Compliant
}

int main() {
    ErrorCode error = ErrorCode::NETWORK_ERROR;

    logError(toInt(error));

    return 0;
}

Check Information

Group: Declarations
Category: Required

Version History

Introduced in R2024b