Main Content

AUTOSAR C++14 Rule A6-5-3

Do statements should not be used

Since R2020b

Description

Rule Definition

Do statements should not be used.

Rationale

A do statement can introduce bugs in your code because its termination condition is checked after executing the code block. Consider this code where an array is accessed by using a pointer in a do-while loop.

int* array;
//...
do {
cout<<*array;
--array;
} while (array != nullptr); 
Because the termination condition is checked after executing the block of code, this code might dereference an invalid or null pointer, which can unexpectedly terminate code execution during run time. The code is also hard to read because the condition for executing the block is at the end of the block where it can be easily missed.

Avoid do statements in your code. You can use do statements to write function-like macros.

Polyspace Implementation

Polyspace® flags all do statements, except those located in macros.

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

This example shows how Polyspace flags do statements outside of a macro. This code uses a pointer within a do-while loop. The terminating condition is that the pointer is not a null pointer.

#include<cstdint>
struct P
{
	int val;
	struct P* next;
};

void psKO(P*p)
{
	do              // Noncompliant
	{
		p = p->next;
	} while(p!=nullptr);
}

This code can dereference a null pointer because the terminating condition is checked after executing the do block. The code is also difficult to read because the terminating condition is placed at the end of the block. Polyspace flags the do statement.

This example shows how Polyspace treats do statements in a macro. Consider this code where two macros, SWAP and SWAP2 are implemented. SWAP uses a do statement while SWAP2 does not.

#include <cstdint>
//Compliant by exception 
#define SWAP(a, b) \
        do                         \
        {                          \
            decltype(a) tmp = (a); \
           (a) = (b);             \
           (b) = tmp;             \
       } while (0)

#define SWAP2(a, b)        \
       decltype(a) tmp = (a); \
       (a) = (b);             \
       (b) = tmp;

int main(void)
{
  uint8_t a = 24;
  uint8_t b = 12;

  if (a > 12)
//  SWAP2(a, b);  // Compilation Error
  SWAP(a, b);
return 0;
}

The two macros are intended to be invoked like functions. You cannot use SWAP2 as a function-like macro in the if block because after expansion, only the first expression statement of SWAP2 remains within the if block. This breakup of the macro changes its meaning, and in this case, causes a compilation error. A solution to this issue is to enclose the macro in a do-while block and put the terminating condition as false. Such enclosed macros cannot be broken up and can be invoked as functions. Polyspace does not flag do statements in macros.

Check Information

Group: Statements
Category: Advisory, Automated

Version History

Introduced in R2020b