Rule A6-5-3 (advisory, implementation, automated)
Do statements should not be used.
Rationale
Do-statements are bug-prone, as the termination condition is checked at the end and can be overlooked.
Exception
A do-statement may be used in a function-like macro to ensure that its invocation behaves like an expression statement consisting of a function call (see http://cfaq.com/cpp/multistmt.html). Note: Rule A16-0-1 forbids function-like macros. This exception is kept in case rule A16-0-1 is disabled in a project.
Example
// $Id: A6-5-3.cpp 291350 2017-10-17 14:31:34Z jan.babst $
#include <cstdint>
// Compliant by exception
#define SWAP(a, b) \
do \
{ \
decltype(a) tmp = (a); \
(a) = (b); \
(b) = tmp; \
} while (0)
// Non-compliant
#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)
SWAP(a, b);
// if (a > 12)
//SWAP2(a, b);
// Does not compile, because only the first line is used in the body of the
// if-statement. In other cases this may even cause a run-time error.
// The expansion contain two semicolons in a row, which may be flagged by
// compiler warnings.
// Expands to:
// if (a > 12)
//decltype(a) tmp = (a);
// (a) = (b);
// (b) = tmp;;
return 0;
}
See also
C++ Core Guidelines [11]: ES.75: Avoid do-statements.