blob: 5d5f7ad3ebe6940985e763749b24a9b00b8931d5 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!-- Created by GNU Texinfo 5.2, http://www.gnu.org/software/texinfo/ -->
<head>
<title>The GNU C Preprocessor Internals: Guard Macros</title>
<meta name="description" content="The GNU C Preprocessor Internals: Guard Macros">
<meta name="keywords" content="The GNU C Preprocessor Internals: Guard Macros">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content="makeinfo">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="index.html#Top" rel="start" title="Top">
<link href="Concept-Index.html#Concept-Index" rel="index" title="Concept Index">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="index.html#Top" rel="up" title="Top">
<link href="Files.html#Files" rel="next" title="Files">
<link href="Line-Numbering.html#Line-Numbering" rel="prev" title="Line Numbering">
<style type="text/css">
<!--
a.summary-letter {text-decoration: none}
blockquote.smallquotation {font-size: smaller}
div.display {margin-left: 3.2em}
div.example {margin-left: 3.2em}
div.indentedblock {margin-left: 3.2em}
div.lisp {margin-left: 3.2em}
div.smalldisplay {margin-left: 3.2em}
div.smallexample {margin-left: 3.2em}
div.smallindentedblock {margin-left: 3.2em; font-size: smaller}
div.smalllisp {margin-left: 3.2em}
kbd {font-style:oblique}
pre.display {font-family: inherit}
pre.format {font-family: inherit}
pre.menu-comment {font-family: serif}
pre.menu-preformatted {font-family: serif}
pre.smalldisplay {font-family: inherit; font-size: smaller}
pre.smallexample {font-size: smaller}
pre.smallformat {font-family: inherit; font-size: smaller}
pre.smalllisp {font-size: smaller}
span.nocodebreak {white-space:nowrap}
span.nolinebreak {white-space:nowrap}
span.roman {font-family:serif; font-weight:normal}
span.sansserif {font-family:sans-serif; font-weight:normal}
ul.no-bullet {list-style: none}
-->
</style>
</head>
<body lang="en" bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" alink="#FF0000">
<a name="Guard-Macros"></a>
<div class="header">
<p>
Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="prev">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
</div>
<hr>
<a name="The-Multiple_002dInclude-Optimization"></a>
<h2 class="unnumbered">The Multiple-Include Optimization</h2>
<a name="index-guard-macros"></a>
<a name="index-controlling-macros"></a>
<a name="index-multiple_002dinclude-optimization"></a>
<p>Header files are often of the form
</p>
<div class="smallexample">
<pre class="smallexample">#ifndef FOO
#define FOO
&hellip;
#endif
</pre></div>
<p>to prevent the compiler from processing them more than once. The
preprocessor notices such header files, so that if the header file
appears in a subsequent <code>#include</code> directive and <code>FOO</code> is
defined, then it is ignored and it doesn&rsquo;t preprocess or even re-open
the file a second time. This is referred to as the <em>multiple
include optimization</em>.
</p>
<p>Under what circumstances is such an optimization valid? If the file
were included a second time, it can only be optimized away if that
inclusion would result in no tokens to return, and no relevant
directives to process. Therefore the current implementation imposes
requirements and makes some allowances as follows:
</p>
<ol>
<li> There must be no tokens outside the controlling <code>#if</code>-<code>#endif</code>
pair, but whitespace and comments are permitted.
</li><li> There must be no directives outside the controlling directive pair, but
the <em>null directive</em> (a line containing nothing other than a single
&lsquo;<samp>#</samp>&rsquo; and possibly whitespace) is permitted.
</li><li> The opening directive must be of the form
<div class="smallexample">
<pre class="smallexample">#ifndef FOO
</pre></div>
<p>or
</p>
<div class="smallexample">
<pre class="smallexample">#if !defined FOO [equivalently, #if !defined(FOO)]
</pre></div>
</li><li> In the second form above, the tokens forming the <code>#if</code> expression
must have come directly from the source file&mdash;no macro expansion must
have been involved. This is because macro definitions can change, and
tracking whether or not a relevant change has been made is not worth the
implementation cost.
</li><li> There can be no <code>#else</code> or <code>#elif</code> directives at the outer
conditional block level, because they would probably contain something
of interest to a subsequent pass.
</li></ol>
<p>First, when pushing a new file on the buffer stack,
<code>_stack_include_file</code> sets the controlling macro <code>mi_cmacro</code> to
<code>NULL</code>, and sets <code>mi_valid</code> to <code>true</code>. This indicates
that the preprocessor has not yet encountered anything that would
invalidate the multiple-include optimization. As described in the next
few paragraphs, these two variables having these values effectively
indicates top-of-file.
</p>
<p>When about to return a token that is not part of a directive,
<code>_cpp_lex_token</code> sets <code>mi_valid</code> to <code>false</code>. This
enforces the constraint that tokens outside the controlling conditional
block invalidate the optimization.
</p>
<p>The <code>do_if</code>, when appropriate, and <code>do_ifndef</code> directive
handlers pass the controlling macro to the function
<code>push_conditional</code>. cpplib maintains a stack of nested conditional
blocks, and after processing every opening conditional this function
pushes an <code>if_stack</code> structure onto the stack. In this structure
it records the controlling macro for the block, provided there is one
and we&rsquo;re at top-of-file (as described above). If an <code>#elif</code> or
<code>#else</code> directive is encountered, the controlling macro for that
block is cleared to <code>NULL</code>. Otherwise, it survives until the
<code>#endif</code> closing the block, upon which <code>do_endif</code> sets
<code>mi_valid</code> to true and stores the controlling macro in
<code>mi_cmacro</code>.
</p>
<p><code>_cpp_handle_directive</code> clears <code>mi_valid</code> when processing any
directive other than an opening conditional and the null directive.
With this, and requiring top-of-file to record a controlling macro, and
no <code>#else</code> or <code>#elif</code> for it to survive and be copied to
<code>mi_cmacro</code> by <code>do_endif</code>, we have enforced the absence of
directives outside the main conditional block for the optimization to be
on.
</p>
<p>Note that whilst we are inside the conditional block, <code>mi_valid</code> is
likely to be reset to <code>false</code>, but this does not matter since
the closing <code>#endif</code> restores it to <code>true</code> if appropriate.
</p>
<p>Finally, since <code>_cpp_lex_direct</code> pops the file off the buffer stack
at <code>EOF</code> without returning a token, if the <code>#endif</code> directive
was not followed by any tokens, <code>mi_valid</code> is <code>true</code> and
<code>_cpp_pop_file_buffer</code> remembers the controlling macro associated
with the file. Subsequent calls to <code>stack_include_file</code> result in
no buffer being pushed if the controlling macro is defined, effecting
the optimization.
</p>
<p>A quick word on how we handle the
</p>
<div class="smallexample">
<pre class="smallexample">#if !defined FOO
</pre></div>
<p>case. <code>_cpp_parse_expr</code> and <code>parse_defined</code> take steps to see
whether the three stages &lsquo;<samp>!</samp>&rsquo;, &lsquo;<samp>defined-expression</samp>&rsquo; and
&lsquo;<samp>end-of-directive</samp>&rsquo; occur in order in a <code>#if</code> expression. If
so, they return the guard macro to <code>do_if</code> in the variable
<code>mi_ind_cmacro</code>, and otherwise set it to <code>NULL</code>.
<code>enter_macro_context</code> sets <code>mi_valid</code> to false, so if a macro
was expanded whilst parsing any part of the expression, then the
top-of-file test in <code>push_conditional</code> fails and the optimization
is turned off.
</p>
<hr>
<div class="header">
<p>
Next: <a href="Files.html#Files" accesskey="n" rel="next">Files</a>, Previous: <a href="Line-Numbering.html#Line-Numbering" accesskey="p" rel="prev">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html#Concept-Index" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>