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/include | |
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/include')
-rw-r--r-- | libcpp/include/cpplib.h | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 91226cf..2becd2e 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -901,7 +901,7 @@ enum cpp_builtin_type union GTY(()) _cpp_hashnode_value { /* Assert (maybe NULL) */ cpp_macro * GTY((tag ("NT_VOID"))) answers; - /* Macro (never NULL) */ + /* Macro (maybe NULL) */ cpp_macro * GTY((tag ("NT_USER_MACRO"))) macro; /* Code for a builtin macro. */ enum cpp_builtin_type GTY ((tag ("NT_BUILTIN_MACRO"))) builtin; @@ -919,7 +919,11 @@ struct GTY(()) cpp_hashnode { unsigned int flags : 9; /* CPP flags. */ ENUM_BITFIELD(node_type) type : 2; /* CPP node type. */ - /* 5 bits spare (plus another 32 on 64-bit hosts). */ + /* 5 bits spare. */ + + /* On a 64-bit system there would be 32-bits of padding to the value + field. So placing the deferred index here is not costly. */ + unsigned deferred; /* Deferred index, (unless zero). */ union _cpp_hashnode_value GTY ((desc ("%1.type"))) value; }; @@ -1061,6 +1065,18 @@ inline bool cpp_macro_p (const cpp_hashnode *node) { return node->type & NT_MACRO_MASK; } +inline cpp_macro *cpp_set_deferred_macro (cpp_hashnode *node, + cpp_macro *forced = NULL) +{ + cpp_macro *old = node->value.macro; + + node->value.macro = forced; + node->type = NT_USER_MACRO; + node->flags &= ~NODE_USED; + + return old; +} +cpp_macro *cpp_get_deferred_macro (cpp_reader *, cpp_hashnode *, location_t); /* Returns true if NODE is a function-like user macro. */ inline bool cpp_fun_like_macro_p (cpp_hashnode *node) @@ -1068,11 +1084,13 @@ inline bool cpp_fun_like_macro_p (cpp_hashnode *node) return cpp_user_macro_p (node) && node->value.macro->fun_like; } -extern const unsigned char *cpp_macro_definition (cpp_reader *, - cpp_hashnode *); +extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *); +extern const unsigned char *cpp_macro_definition (cpp_reader *, cpp_hashnode *, + const cpp_macro *); inline location_t cpp_macro_definition_location (cpp_hashnode *node) { - return node->value.macro->line; + const cpp_macro *macro = node->value.macro; + return macro ? macro->line : 0; } /* Return an idempotent time stamp (possibly from SOURCE_DATE_EPOCH). */ enum class CPP_time_kind @@ -1266,6 +1284,8 @@ extern int cpp_ideq (const cpp_token *, const char *); extern void cpp_output_line (cpp_reader *, FILE *); extern unsigned char *cpp_output_line_to_string (cpp_reader *, const unsigned char *); +extern const unsigned char *cpp_alloc_token_string + (cpp_reader *, const unsigned char *, unsigned); extern void cpp_output_token (const cpp_token *, FILE *); extern const char *cpp_type2name (enum cpp_ttype, unsigned char flags); /* Returns the value of an escape sequence, truncated to the correct @@ -1321,6 +1341,8 @@ extern void cpp_scan_nooutput (cpp_reader *); extern int cpp_sys_macro_p (cpp_reader *); extern unsigned char *cpp_quote_string (unsigned char *, const unsigned char *, unsigned int); +extern bool cpp_compare_macros (const cpp_macro *macro1, + const cpp_macro *macro2); /* In files.c */ extern bool cpp_included (cpp_reader *, const char *); |