aboutsummaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2020-11-24 08:23:55 -0800
committerNathan Sidwell <nathan@acm.org>2020-11-24 08:31:03 -0800
commit13f93cf5336ec0085277b9a5ef88c02359527170 (patch)
tree21dd731e4de98eaab84f2e61d5bc54debf9c9851 /libcpp/macro.c
parent489be3119e6cd092bf7f30880a5d641f0bf0672f (diff)
downloadgcc-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.c95
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. */