#onceC Document number: N2742
Date: 2021-10-17
Author: Miguel Ojeda <ojeda@ojeda.dev>
Project: ISO/IEC JTC1/SC22/WG14: Programming Language C
This proposal adds a standard version of the #pragma once feature implemented in major compilers.
The #pragma once feature is provided by compilers as a more ergonomic include guard, i.e. instead of writing a header like:
/*
* Some header.
*/
#ifndef SOME_HEADER_H
#define SOME_HEADER_H
// File contents
#endif // SOME_HEADER_H
Users may write it like:
/*
* Some header.
*/
#pragma once
// File contents
The feature is supported in all major compilers:
However, the semantics of “having seen a file” can be unclear (e.g. is it based on the path? On the inode? On the contents?) and unreliable (e.g. filesystem aliasing), thus some projects like the Linux kernel prefer to avoid using #pragma once, though they may use such a feature if it allows to provide an identifier [1].
This proposal adds a new preprocessing directive, #once, as a standard and shorter version of #pragma once, in two variants.
The first variant has implementation-defined semantics and the intention is that translators that already provide #pragma once give it the same semantics (and document them):
/*
* Some header.
*/
#once
// File contents
The benefits of this variant with respect to #pragma once is that it is standard and shorter.
The second variant, which takes an identifier, is a replacement for an explicit include guard for projects that do not wish to rely on the interpretation of “having seen a file” that their compilers may do:
/*
* Some header.
*/
#once SOME_HEADER_H
// File contents
The benefits of this variant with respect to an explicit include guard is that it is standard, shorter and avoids duplicating the identifier (twice if the project uses the fairly common convention of writing it also in the #endif directive as a comment).
Both variants are required to come before any other preprocessor directive, but may come after text lines (typically, comments such as a top-level description of the header or a SPDX [2] line). Only a single #once directive is allowed per source file (though more may appear in the preprocessing translation unit).
The proposed wording is with respect to the N2596 C23 Working Draft.
In “4. Conformance”, after paragraph 4 add a new one:
The implementation shall not successfully translate a source file containing more than one
#oncepreprocessing directive or containing one if it is not the first preprocessing directive in the source file.
In “6.10 Preprocessing directives”, modify paragraph 1 to add the #once directive after #error and before #pragma:
…
control-line:
…
#errorpp-tokensopt new-line
#oncenew-line
#onceidentifier new-line
#pragmapp-tokensopt new-line…
After “6.10.5 Error directive”, add a new section:
6.10.6 Once directive
Semantics
A preprocessing directive of the form
#oncenew-linecauses the implementation to behave in an implementation-defined manner.
A preprocessing directive of the form
#onceidentifier new-linecauses the implementation to behave as if the source file was prefixed with
#ifndefidentifier
#defineidentifierand suffixed with
#endifIf more than one
#oncedirective appears in the source file, or if a preprocessing directive appears before it, then this causes the implementation to produce a diagnostic message.