C[++]: Normalizing include syntax ("" vs <>)
Stephan Bergmann
sbergman at redhat.com
Thu Nov 2 09:15:56 UTC 2017
On 10/06/2017 11:26 AM, Kaganski Mike wrote:
> Here I propose an updated rule to follow in the use of includes in the
> project's code:
>
> 1. Use *only* <> syntax for any include that resides in include paths
> explicitly defined in the module's mk file (gb_Library_set_include),
> global includes ($INCLUDE), e.g., /include, and system headers (<vector>
> or <Windows.h>) - these are interface headers.
> As all implementations agree to use both implementation include places
> and -I-defined places as search paths for <> syntax, this will likely
> not allow inconsistency problems (and is actually what is used now in
> most of the code).
>
> 2. Use *only* <> syntax for includes inside headers that reside in such
> places (e.g., no header in /include should include other headers using
> "" itself). This is aimed to prevent cases where some header placed in
> the current source's directory would conflict with an include referred
> from a global interface header.
>
> 3. *Always* use "" syntax *only* for includes that refer to headers
> placed next to the current source in the same directory (or
> subdirectories), i.e. that would be found using the "." entry of -I
> switch. These are implementation headers. This applies to both includes
> in c[xx] files as well as in h[xx] residing in directories like
> /sw/source/core/access (as opposed to those in /sw/inc).
What happened to get implemented now with the help of a rewriting
loplugin:includeform is slightly different:
Use the "..." form if and only if the included file is found next to
the including file. Otherwise, use the <...> form.
More technically: Use the "p" form if and only if the "perceived"
(i.e., as potentially modified through #line directives) absolute path
of the including file is p'/f (with f being just a file name, not a
multi-segment path), and the absolute path of an included file can be
written as p'/p (with p potentially being a multi-segment relative path).
This is independent of whether the including file is the translation
unit's main source file (".cxx") or itself an include file (".hxx").
And that is how the actual rules differ from rule (2) of the three
original rules quoted above. (Though in practice include files in the
include/ tree will still reference other include files with the <...>
form, even with the modified rules, due to the hierarchical structure of
the include/ tree and the way such includes are written with relative
paths, include/foo/bar.hxx using #include <foo/baz.hxx> notation, not
#include "baz.hxx".)
The original rule (2) rationale "to prevent cases where some header
placed in the current source's directory would conflict with an include
referred from a global interface header" should be a non-issue anyway:
For the "..." form, all compilers first search next to the including
file itself, so actually including a file that can be found that way is
safe from any clashes. MSVC then additionally searches next to each
file in the "include stack", so that sloppily written Windows-only code
could accidentally use "..." when it should actually use <...>, but
loplugin:includeform will then find that blunder (when at least I
occasionally run the Clang plugins on Windows).
(The reason to use the potentially #line-modified, "perceived" pathname
is more of an aesthetic than a technical nature; it would look odd to
reference include files next to a flex or bison source file with <...>
instead of "...", different from how those would be written for a
genuine C/C++ source file.)
The loplugin:includeform remains enabled (in a non-rewriting mode), so
Jenkins may occasionally block your Gerrit changes for a wrong choice of
"..." vs. <...> include form. However, as the now-redundant -I switches
that make the current translation unit's path be searched for the <...>
form are removed, chances that such wrong choices would not already be
found by a local (non-Clang-plugins) build should be low.
More information about the LibreOffice
mailing list