pfile->directive_line, 0,
"undefining \"%s\"", NODE_NAME (node));
- if (CPP_OPTION (pfile, warn_unused_macros))
+ if (node->value.macro
+ && CPP_OPTION (pfile, warn_unused_macros))
_cpp_warn_if_unused_macro (pfile, node, NULL);
_cpp_free_definition (node);
if (node)
{
skip = !_cpp_defined_macro_p (node);
+ if (!_cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line))
+ /* It wasn't a macro after all. */
+ skip = true;
_cpp_mark_macro_used (node);
- _cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line);
if (pfile->cb.used)
pfile->cb.used (pfile, pfile->directive_line, node);
check_eol (pfile, false);
if (node)
{
skip = _cpp_defined_macro_p (node);
+ if (!_cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line))
+ /* It wasn't a macro after all. */
+ skip = false;
_cpp_mark_macro_used (node);
- _cpp_maybe_notify_macro_use (pfile, node, pfile->directive_line);
if (pfile->cb.used)
pfile->cb.used (pfile, pfile->directive_line, node);
check_eol (pfile, false);
}
}
+ bool is_defined = false;
if (node)
{
if ((pfile->context != initial_context
&& CPP_OPTION (pfile, warn_expansion_to_defined))
cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED,
"this use of \"defined\" may not be portable");
-
+ is_defined = _cpp_defined_macro_p (node);
+ if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc))
+ /* It wasn't a macro after all. */
+ is_defined = false;
_cpp_mark_macro_used (node);
- _cpp_maybe_notify_macro_use (pfile, node, token->src_loc);
/* A possible controlling macro of the form #if !defined ().
_cpp_parse_expr checks there was no other junk on the line. */
result.unsignedp = false;
result.high = 0;
result.overflow = false;
- result.low = node && _cpp_defined_macro_p (node);
+ result.low = is_defined;
return result;
}
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;
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;
};
{
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)
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
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
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 *);
}
/* In macro.c */
-extern void _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node,
- location_t loc);
-inline void _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node,
+extern bool _cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node,
+ location_t);
+inline bool _cpp_maybe_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node,
location_t loc)
{
if (!(node->flags & NODE_USED))
- _cpp_notify_macro_use (pfile, node, loc);
+ return _cpp_notify_macro_use (pfile, node, loc);
+ return true;
}
extern cpp_macro *_cpp_new_macro (cpp_reader *, cpp_macro_kind, void *);
extern void _cpp_free_definition (cpp_hashnode *);
create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base,
unsigned int len, enum cpp_ttype type)
{
- uchar *dest = _cpp_unaligned_alloc (pfile, len + 1);
-
- memcpy (dest, base, len);
- dest[len] = '\0';
token->type = type;
token->val.str.len = len;
- token->val.str.text = dest;
+ token->val.str.text = cpp_alloc_token_string (pfile, base, len);
+}
+
+const uchar *
+cpp_alloc_token_string (cpp_reader *pfile,
+ const unsigned char *ptr, unsigned len)
+{
+ uchar *dest = _cpp_unaligned_alloc (pfile, len + 1);
+
+ dest[len] = 0;
+ memcpy (dest, ptr, len);
+ return dest;
}
/* A pair of raw buffer pointers. The currently open one is [1], the
/* Don't attempt to expand the token. */
tok->flags |= NO_EXPAND;
if (_cpp_defined_macro_p (node)
+ && _cpp_maybe_notify_macro_use (pfile, node, tok->src_loc)
&& !cpp_fun_like_macro_p (node))
cpp_error_with_line (pfile, CPP_DL_ERROR, tok->src_loc, 0,
"module control-line \"%s\" cannot be"
/* 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 *,
/* #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 *);
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;
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;
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). */
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)
{
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:
default:
abort ();
}
+
+ return true;
}
/* Warn if a token in STRING matches one of a function-like MACRO's
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. */