Rule A16-0-1 (required, implementation, automated)

The pre-processor shall only be used for unconditional and conditional file inclusion and include guards, and using the following directives: (1) #ifndef, #ifdef, (3) #if, (4) #if defined, (5) #elif, (6) #else, (7) #define, (8) #endif, (9) #include.

Rationale

C++ provides safer, more readable and easier to maintain ways of achieving what is often done using the pre-processor. The pre-processor does not obey the linkage, lookup and function call semantics. Instead, constant objects, constexprs, inline functions and templates are to be used.

Example

// $Id: A16-0-1.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#pragma once // Non-compliant - implementation-defined feature

#ifndef HEADER_FILE_NAME // Compliant - include guard
#define HEADER_FILE_NAME // Compliant - include guard

#include <cstdint> // Compliant - unconditional file inclusion

#ifdef WIN32
#include <windows.h> // Compliant - conditional file inclusion
#endif

#ifdef WIN32
std::int32_t fn1(
std::int16_t x,
std::int16_t y) noexcept; // Non-compliant - not a file inclusion
#endif

#if defined VERSION && VERSION > 2011L // Compliant
#include <array>
// Compliant - conditional file inclusion
#elif VERSION > 1998L // Compliant
// Compliant
- conditional file inclusion
22 #include <vector>
// Compliant
23 #endif

#define MAX_ARRAY_SIZE 1024U // Non-compliant
#ifndef MAX_ARRAY_SIZE
// Non-compliant
#error "MAX_ARRAY_SIZE has not been defined" // Non-compliant
#endif
// Non-compliant
#undef MAX_ARRAY_SIZE // Non-compliant

#define MIN(a, b) (((a) < (b)) ? (a) : (b)) // Non-compliant

#define PLUS2(X) ((X) + 2) // Non-compliant - function should be used instead
#define PI 3.14159F// Non-compliant - constexpr should be used instead
#define std ::int32_t long // Non-compliant - ’using’ should be used instead
#define STARTIF if( // Non-compliant - language redefinition
#define HEADER "filename.h" // Non-compliant - string literal

void Fn2() noexcept
{
#ifdef __linux__ // Non-compliant - ifdef not used for file inclusion

// ...

#elif WIN32 // Non-compliant - elif not used for file inclusion

// ...

#elif __APPLE__ // Non-compliant - elif not used for file inclusion

// ...

#else // Non-compliant - else not used for file inclusion

// ...

#endif // Non-compliant - endif not used for file inclusion or include guards
}

#endif // Compliant - include guard

See also

MISRA C++ 2008 [7]: Rule 16-2-1 The pre-processor shall only be used for file inclusion and include guards. MISRA C++ 2008 [7]: Rule 16-2-2 C++ macros shall only be used for: include guards, type qualifiers, or storage class specifiers. JSF December 2005 [8]: AV Rule 26 Only the following pre-processor directives shall be used: 1. #ifndef 2. #define 3. #endif 4. #include. JSF December 2005 [8]: AV Rule 27 #ifndef, #define and #endif will be used to prevent multiple inclusions of the same header file. Other techniques to prevent the multiple inclusions of header files will not be used. JSF December 2005 [8]: AV Rule 28 The #ifndef and #endif pre-processor directives will only be used as defined in AV Rule 27 to prevent multiple inclusions of the same header file. JSF December 2005 [8]: AV Rule 29 The #define pre-processor directive shall not be used to create inline macros. Inline functions shall be used instead.

JSF December 2005 [8]: AV Rule 30 The #define pre-processor directive shall not be used to define constant values. Instead, the const qualifier shall be applied to variable declarations to specify constant values. JSF December 2005 [8]: AV Rule 31 The #define pre-processor directive will only be used as part of the technique to prevent multiple inclusions of the same header file. JSF December 2005 [8]: AV Rule 32 The #include pre-processor directive will only be used to include header (*.h) files. HIC++ v4.0 [9]: 16.1.1 Use the preprocessor only for implementing include guards, and including header files with include guards.