Click to see the query in the CodeQL repository
Some header files, such as those which define structures or classes, cannot be included more than once within a translation unit, as doing so would cause a redefinition error. Such headers must be guarded to prevent ill-effects from multiple inclusion. Similarly, if header files include other header files, and this inclusion graph contains a cycle, then at least one file within the cycle must contain header guards in order to break the cycle. Because of cases like these, all headers should be guarded as a matter of good practice, even if they do not strictly need to be.
Furthermore, most modern compilers contain optimizations which are triggered by header guards. If the header guard strictly conforms to the pattern that compilers expect, then inclusions of that header other than the first have absolutely no effect: the file isn’t re-read from disk, nor is it re-tokenised or re-preprocessed. This can result in a noticeable, albeit minor, improvement to compilation time.
Add one of the following forms of header guard to the file (where HEADER_NAME is a unique identifier derived from the name of the file):
#ifndef HEADER_NAME followed by #define HEADER_NAME at the very start of the header, and a matching #endif at the very end.
#if !defined(HEADER_NAME) followed by #define HEADER_NAME at the very start of the header, and a matching #endif at the very end.
#pragma once anywhere within the header. Note that if you are updating code to match the Joint Strike Fighter Air Vehicle coding standard, then the first option is the only appropriate form.
The author of the following header tried to use header guards, but made a typo:
In scenarios like this, MY_HAEDER_H should be replaced by MY_HEADER_H (note the transposed A and E):
The following header would seem to be guarded, but doesn’t strictly abide to the rules:
Although the preprocessor directives in the preceding header will prevent errors from repeated inclusion, not all compilers are intelligent enough to recognise it as being guarded. Consequently compiler optimization will be limited. To ensure that the guard is recognized by compilers, change the header so that the guard is the outermost directive:
The following header evolved over time, with different authors adding function declarations in different places:
Unfortunately, the result is that some declarations are before the initial #ifndef, some are between the #ifndef and the #define, and some are after the final #endif. All three of these things must be addressed to turn the file into a correctly guarded header:
AV Rules 27 and 35, Joint Strike Fighter Air Vehicle C++ Coding Standards. Lockheed Martin Corporation, 2005.