C[++]: Normalizing include syntax ("" vs <>)

Kaganski Mike mikekaganski at hotmail.com
Fri Oct 6 09:26:25 UTC 2017


Lately, I've pushed some commits ([1], [2], [3]) that change syntax used 
for some includes. I wanted to share my rationale behind that, along 
with some notes about past discussion on this topic.

The topic is using one of two syntaxes described for #include directive 
in standard (section [cpp.include]): in angular brackets <> vs in quotes 
"". The standard reads:

 > 2 A preprocessing directive of the form
 > # include < h-char-sequence > new-line
 > searches a sequence of implementation-defined places for a header 
identified uniquely by the specified sequence
 > between the < and > delimiters, and causes the replacement of that 
directive by the entire contents of the
 > header. How the places are specified or the header identified is 
 > 3 A preprocessing directive of the form
 > # include " q-char-sequence " new-line
 > causes the replacement of that directive by the entire contents of 
the source file identified by the specified
 > sequence between the " delimiters. The named source file is searched 
for in an implementation-defined
 > manner. If this search is not supported, or if the search fails, the 
directive is reprocessed as if it read
 > # include < h-char-sequence > new-line
 > with the identical contained sequence (including > characters, if 
any) from the original directive.
 > ...
 > [ Note: Although an implementation may provide a mechanism for making 
arbitrary source files available to
 > the < > search, in general programmers should use the < > form for 
headers provided with the implementation,
 > and the " " form for sources outside the control of the implementation.

The discussion that took place at [4] raised some concerns on possible 
problems due to inconsistent treatment of the quoted syntax in MS 
compiler vs gcc. Namely, [5] states, that
 > The preprocessor searches for include files in this order:
 > 1) In the same directory as the file that contains the #include 
 > 2) In the directories of the currently opened include files, in the 
reverse order in which they were opened. The search begins in the 
directory of the parent include file and continues upward through the 
directories of any grandparent include files.
 > 3) Along the path that's specified by each /I compiler option.
 > 4) Along the paths that are specified by the INCLUDE environment 

while [6] reads about quoted syntax:
 > This variant is used for header files of your own program. It 
searches for a file named file first in the directory containing the 
current file, then in the quote directories and then the same 
directories used for <file>. You can prepend directories to the list of 
quote directories with the -iquote option.

So, it is speculated that these differences might result in very hard to 
trace bugs. Thus, it was suggested to use <> syntax uniformly, to avoid 
that possibility.

However, doing so creates some problems, at least with IDE integration 
with VisualStudio. The generated project, naturally, doesn't add 
file-specific include paths to each file, to include the files' 
directories. This makes the includes of headers sitting in the same 
directory as the source file, referenced using <> syntax, to fail in the 
editor's parser, and errors (failed includes + unknown identifiers) 
being highlighted (underlined with red) in editor window. This impairs 
the ease of use of the IDE aids (e.g., Intellisense, and error 
highlighting that gets masked by false errors throughout the code).

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).

As all implementations search current source's directory first for 
includes referred using "" syntax, as a side effect, these rules will 
(1) speed up searching for same-directory implementation headers (which 
is intended when "" is used) - the results will be immediately 
available; and (2) somewhat speed up searching for interface includes 
that will be converted from current "" syntax to <>, because their 
search path will not be prepended with current source's directory.

Please share your opinions and concerns on this matter. I hope to 
continue implementing this policy in my future commits, to improve my 
coding experience using VS IDE.

I was asked to put the policy into README.md. Please advise, which 
README.md is suitable for such information (I assume, the one in /, but 
probably it's worth creating one in /include ?).

Thank you for consideration.

[4] https://bugs.documentfoundation.org/show_bug.cgi?id=65108
[5] https://msdn.microsoft.com/en-us/library/36k2cdd4
[6] https://gcc.gnu.org/onlinedocs/cpp/Include-Syntax.html

Best regards,
Mike Kaganski

More information about the LibreOffice mailing list