]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/doc/cppinternals/scanning-the-replacement-list-for-macros-to-expand.rst
sphinx: add missing trailing newline
[thirdparty/gcc.git] / gcc / doc / cppinternals / scanning-the-replacement-list-for-macros-to-expand.rst
1 ..
2 Copyright 1988-2022 Free Software Foundation, Inc.
3 This is part of the GCC manual.
4 For copying conditions, see the copyright.rst file.
5
6 Scanning the replacement list for macros to expand
7 **************************************************
8
9 The C standard states that, after any parameters have been replaced
10 with their possibly-expanded arguments, the replacement list is
11 scanned for nested macros. Further, any identifiers in the
12 replacement list that are not expanded during this scan are never
13 again eligible for expansion in the future, if the reason they were
14 not expanded is that the macro in question was disabled.
15
16 Clearly this latter condition can only apply to tokens resulting from
17 argument pre-expansion. Other tokens never have an opportunity to be
18 re-tested for expansion. It is possible for identifiers that are
19 function-like macros to not expand initially but to expand during a
20 later scan. This occurs when the identifier is the last token of an
21 argument (and therefore originally followed by a comma or a closing
22 parenthesis in its macro's argument list), and when it replaces its
23 parameter in the macro's replacement list, the subsequent token
24 happens to be an opening parenthesis (itself possibly the first token
25 of an argument).
26
27 It is important to note that when cpplib reads the last token of a
28 given context, that context still remains on the stack. Only when
29 looking for the *next* token do we pop it off the stack and drop
30 to a lower context. This makes backing up by one token easy, but more
31 importantly ensures that the macro corresponding to the current
32 context is still disabled when we are considering the last token of
33 its replacement list for expansion (or indeed expanding it). As an
34 example, which illustrates many of the points above, consider
35
36 .. code-block:: c++
37
38 #define foo(x) bar x
39 foo(foo) (2)
40
41 which fully expands to :samp:`bar foo (2)`. During pre-expansion
42 of the argument, :samp:`foo` does not expand even though the macro is
43 enabled, since it has no following parenthesis [pre-expansion of an
44 argument only uses tokens from that argument; it cannot take tokens
45 from whatever follows the macro invocation]. This still leaves the
46 argument token :samp:`foo` eligible for future expansion. Then, when
47 re-scanning after argument replacement, the token :samp:`foo` is
48 rejected for expansion, and marked ineligible for future expansion,
49 since the macro is now disabled. It is disabled because the
50 replacement list :samp:`bar foo` of the macro is still on the context
51 stack.
52
53 If instead the algorithm looked for an opening parenthesis first and
54 then tested whether the macro were disabled it would be subtly wrong.
55 In the example above, the replacement list of :samp:`foo` would be
56 popped in the process of finding the parenthesis, re-enabling
57 :samp:`foo` and expanding it a second time.