diff options
author | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
---|---|---|
committer | alk3pInjection <webmaster@raspii.tech> | 2024-02-04 16:16:35 +0800 |
commit | abdaadbcae30fe0c9a66c7516798279fdfd97750 (patch) | |
tree | 00a54a6e25601e43876d03c1a4a12a749d4a914c /share/doc/cppinternals/Guard-Macros.html |
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
Change-Id: I7303388733328cd98ab9aa3c30236db67f2e9e9c
Diffstat (limited to 'share/doc/cppinternals/Guard-Macros.html')
-rw-r--r-- | share/doc/cppinternals/Guard-Macros.html | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/share/doc/cppinternals/Guard-Macros.html b/share/doc/cppinternals/Guard-Macros.html new file mode 100644 index 0000000..72bd485 --- /dev/null +++ b/share/doc/cppinternals/Guard-Macros.html @@ -0,0 +1,188 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<!-- Created by GNU Texinfo 5.1, 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="previous" 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="previous">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> [<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 +… +#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’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 +‘<samp>#</samp>’ 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—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’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 ‘<samp>!</samp>’, ‘<samp>defined-expression</samp>’ and +‘<samp>end-of-directive</samp>’ 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="previous">Line Numbering</a>, Up: <a href="index.html#Top" accesskey="u" rel="up">Top</a> [<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> |