diff options
author | Nathan Sidwell <nathan@acm.org> | 2020-11-24 08:23:55 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2020-11-24 08:31:03 -0800 |
commit | 13f93cf5336ec0085277b9a5ef88c02359527170 (patch) | |
tree | 21dd731e4de98eaab84f2e61d5bc54debf9c9851 /libcpp/macro.c | |
parent | 489be3119e6cd092bf7f30880a5d641f0bf0672f (diff) | |
download | gcc-13f93cf5336ec0085277b9a5ef88c02359527170.zip gcc-13f93cf5336ec0085277b9a5ef88c02359527170.tar.gz gcc-13f93cf5336ec0085277b9a5ef88c02359527170.tar.bz2 |
preprocessor: Add deferred macros
Deferred macros are needed for C++ modules. Header units may export
macro definitions and undefinitions. These are resolved lazily at the
point of (potential) use. (The language specifies that, it's not just
a useful optimization.) Thus, identifier nodes grow a 'deferred'
field, which fortunately doesn't expand the structure on 64-bit
systems as there was padding there. This is non-zero on NT_MACRO
nodes, if the macro is deferred. When such an identifier is lexed, it
is resolved via a callback that I added recently. That will either
provide the macro definition, or discover it there was an overriding
undef. Either way the identifier is no longer a deferred macro.
Notice it is now possible for NT_MACRO nodes to have a NULL macro
expansion.
libcpp/
* include/cpplib.h (struct cpp_hashnode): Add deferred field.
(cpp_set_deferred_macro): Define.
(cpp_get_deferred_macro): Declare.
(cpp_macro_definition): Reformat, add overload.
(cpp_macro_definition_location): Deal with deferred macro.
(cpp_alloc_token_string, cpp_compare_macro): Declare.
* internal.h (_cpp_notify_macro_use): Return bool
(_cpp_maybe_notify_macro_use): Likewise.
* directives.c (do_undef): Check macro is not undef before
warning.
(do_ifdef, do_ifndef): Deal with deferred macro.
* expr.c (parse_defined): Likewise.
* lex.c (cpp_allocate_token_string): Break out of ...
(create_literal): ... here. Call it.
(cpp_maybe_module_directive): Deal with deferred macro.
* macro.c (cpp_get_token_1): Deal with deferred macro.
(warn_of_redefinition): Deal with deferred macro.
(compare_macros): Rename to ...
(cpp_compare_macro): ... here. Make extern.
(cpp_get_deferred_macro): New.
(_cpp_notify_macro_use): Deal with deferred macro, return bool
indicating definedness.
(cpp_macro_definition): Deal with deferred macro.
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r-- | libcpp/macro.c | 95 |
1 files changed, 64 insertions, 31 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c index 35a5e70..0575585 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -268,6 +268,8 @@ class vaopt_state { /* Macro expansion. */ +static cpp_macro *get_deferred_or_lazy_macro (cpp_reader *, cpp_hashnode *, + location_t); static int enter_macro_context (cpp_reader *, cpp_hashnode *, const cpp_token *, location_t); static int builtin_macro (cpp_reader *, cpp_hashnode *, @@ -338,10 +340,6 @@ static cpp_macro *create_iso_definition (cpp_reader *); /* #define directive parsing and handling. */ static cpp_macro *lex_expansion_token (cpp_reader *, cpp_macro *); -static bool warn_of_redefinition (cpp_reader *, cpp_hashnode *, - const cpp_macro *); -static bool compare_macros (const cpp_macro *, const cpp_macro *); - static bool parse_params (cpp_reader *, unsigned *, bool *); static void check_trad_stringification (cpp_reader *, const cpp_macro *, const cpp_string *); @@ -353,8 +351,6 @@ static const cpp_token* cpp_get_token_1 (cpp_reader *, location_t *); static cpp_hashnode* macro_of_context (cpp_context *context); -static bool in_macro_expansion_p (cpp_reader *pfile); - /* Statistical counter tracking the number of macros that got expanded. */ unsigned num_expanded_macros_counter = 0; @@ -2878,6 +2874,12 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location) if (node->type == NT_VOID || (result->flags & NO_EXPAND)) break; + if (!(node->flags & NODE_USED) + && node->type == NT_USER_MACRO + && !node->value.macro + && !cpp_get_deferred_macro (pfile, node, result->src_loc)) + break; + if (!(node->flags & NODE_DISABLED)) { int ret = 0; @@ -3216,22 +3218,15 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode *node, if (node->flags & NODE_CONDITIONAL) return false; - cpp_macro *macro1 = node->value.macro; - if (macro1->lazy) - { - /* We don't want to mark MACRO as used, but do need to finalize - its laziness. */ - pfile->cb.user_lazy_macro (pfile, macro1, macro1->lazy - 1); - macro1->lazy = 0; - } - - return compare_macros (macro1, macro2); + if (cpp_macro *macro1 = get_deferred_or_lazy_macro (pfile, node, macro2->line)) + return cpp_compare_macros (macro1, macro2); + return false; } /* Return TRUE if MACRO1 and MACRO2 differ. */ -static bool -compare_macros (const cpp_macro *macro1, const cpp_macro *macro2) +bool +cpp_compare_macros (const cpp_macro *macro1, const cpp_macro *macro2) { /* Redefinition of a macro is allowed if and only if the old and new definitions are the same. (6.10.3 paragraph 2). */ @@ -3790,11 +3785,46 @@ cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num) macro->lazy = num + 1; } +/* NODE is a deferred macro, resolve it, returning the definition + (which may be NULL). */ +cpp_macro * +cpp_get_deferred_macro (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) +{ + node->value.macro = pfile->cb.user_deferred_macro (pfile, loc, node); + + if (!node->value.macro) + node->type = NT_VOID; + + return node->value.macro; +} + +static cpp_macro * +get_deferred_or_lazy_macro (cpp_reader *pfile, cpp_hashnode *node, + location_t loc) +{ + cpp_macro *macro = node->value.macro; + if (!macro) + { + macro = cpp_get_deferred_macro (pfile, node, loc); + if (!macro) + return NULL; + } + + if (macro->lazy) + { + pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); + macro->lazy = 0; + } + + return macro; +} + /* Notify the use of NODE in a macro-aware context (i.e. expanding it, or testing its existance). Also applies any lazy definition. Return FALSE if the macro isn't really there. */ -extern void +extern bool _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, location_t loc) { @@ -3802,14 +3832,8 @@ _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, switch (node->type) { case NT_USER_MACRO: - { - cpp_macro *macro = node->value.macro; - if (macro->lazy) - { - pfile->cb.user_lazy_macro (pfile, macro, macro->lazy - 1); - macro->lazy = 0; - } - } + if (!get_deferred_or_lazy_macro (pfile, node, loc)) + return false; /* FALLTHROUGH. */ case NT_BUILTIN_MACRO: @@ -3825,6 +3849,8 @@ _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node, default: abort (); } + + return true; } /* Warn if a token in STRING matches one of a function-like MACRO's @@ -3877,12 +3903,19 @@ check_trad_stringification (cpp_reader *pfile, const cpp_macro *macro, const unsigned char * cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node) { - unsigned int i, len; - unsigned char *buffer; - gcc_checking_assert (cpp_user_macro_p (node)); - const cpp_macro *macro = node->value.macro; + if (const cpp_macro *macro = get_deferred_or_lazy_macro (pfile, node, 0)) + return cpp_macro_definition (pfile, node, macro); + return NULL; +} + +const unsigned char * +cpp_macro_definition (cpp_reader *pfile, cpp_hashnode *node, + const cpp_macro *macro) +{ + unsigned int i, len; + unsigned char *buffer; /* Calculate length. */ len = NODE_LEN (node) * 10 + 2; /* ' ' and NUL. */ |