Main Content

AUTOSAR C++14 Rule A4-5-1

Expressions with type enum or enum class shall not be used as operands to built-in and overloaded operators other than the subscript operator [], the assignment operator =, the equality operators == and !=, the unary & operator, and the relational operators <, <=, >, >=

Since R2020a

Description

Rule Definition

Expressions with type enum or enum class shall not be used as operands to built-in and overloaded operators other than the subscript operator [], the assignment operator =, the equality operators == and !=, the unary & operator, and the relational operators <, <=, >, >=.

Rationale

In C++, enumerations such as enum or enum class have implementations defined behavior. For instance, their underlying type can be any integral type, including short or char. If you use enumerations as operands to arithmetic operators such as + or -, they are converted to their underlying type. Because the underlying type of an enumeration is implementation dependent, outcome of arithmetic operations using enumerations as operands is unpredictable. To avoid unpredictable and non-portable code, use enumerations as operands to only these operators:

  • Subscript operator []

  • Assignment operator =

  • Equality operators == and !=

  • The Unary & operator

  • The relational operators <, <=,>,>=

You can use enumerations as operands to the built in or overloaded instances of only the above operators. Note that Bitmask type enumerations are an exception to this rule. That is, you can use Bitmask type enumerations as operands to any operators.

Polyspace Implementation

Enumerations are valid operands to only the operators listed above. Polyspace® flags enumerations when they are used as operands to any other operators. Note that Polyspace makes no exception for BitmaskType enumerations.

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 <cstdint>
enum Color : std::uint8_t {  Red,  Green,  Blue,  ColorsCount};
enum class Car : std::uint8_t { Model1, Model2, Model3, ModelsCount};
enum BMT {Exec = 0x1,Write  = 0x2,Read = 0x4};
Car operator+(Car lhs, Car rhs)
{
	return Car::Model3;
}
Color operator|=(Color lhs, Color rhs)
{
	return rhs;
};
void F1() 
{
	Car car = Car::Model1;
	Color color = Red;
	if (color == Green) {                   // Compliant
	}

	if (color == (Red + Blue)) {            // Noncompliant 
	}

	if (color < ColorsCount) {              //Compliant
	}
	if (car == (Car::Model1 + Car::Model2)) // Noncompliant 
	{
	}
	Color value;
	value = (Color)(Red | 3);               // Noncompliant
	value |= Blue;                          // Noncompliant 
	value = (Color)0;                       // Compliant
	if (value & Blue) {};                   // Noncompliant 
	value = (Color)(Blue * value       );   // Noncompliant 
	value = (Color)(Red << 3);              // Noncompliant
	value = (Color)(Red >> 12);             // Noncompliant
	BMT bitmask1 = (BMT)(Exec + Write);     // Noncompliant 
	BMT bitmask2 = (BMT)(Exec | Write);     // Noncompliant 
}

The line BMT bitmask1 = (BMT)(Exec + Write); adds two enumerators and assigns the result to the enum object bitmask1. The addition operation implicitly converts the enumerators into their underlying type. Because the underlying type of enumerators are implementation dependent, the outcome of this code can be unpredictable. Polyspace flags the enumerators that are operands to the built in + operator.

Polyspace treats both built in and overloaded operators similarly. For example, Polyspace flags the operands in the operation Car::Model1 + Car::Model2, even though the + operator is overloaded for the enum class Car.

Check Information

Group: Standard conversions
Category: Required, Automated

Version History

Introduced in R2020a