aboutsummaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r--libcpp/macro.c284
1 files changed, 223 insertions, 61 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c
index 0874028..cdb1821 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,8 +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 parse_params (cpp_reader *, unsigned *, bool *);
static void check_trad_stringification (cpp_reader *, const cpp_macro *,
const cpp_string *);
@@ -351,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;
@@ -586,7 +584,7 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
(c) we are not in strictly conforming mode, then it has the
value 0. (b) and (c) are already checked in cpp_init_builtins. */
case BT_STDC:
- if (cpp_in_system_header (pfile))
+ if (_cpp_in_system_header (pfile))
number = 0;
else
number = 1;
@@ -604,29 +602,21 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
at init time, because time() and localtime() are very
slow on some systems. */
time_t tt;
- struct tm *tb = NULL;
-
- /* Set a reproducible timestamp for __DATE__ and __TIME__ macro
- if SOURCE_DATE_EPOCH is defined. */
- if (pfile->source_date_epoch == (time_t) -2
- && pfile->cb.get_source_date_epoch != NULL)
- pfile->source_date_epoch = pfile->cb.get_source_date_epoch (pfile);
+ auto kind = cpp_get_date (pfile, &tt);
- if (pfile->source_date_epoch >= (time_t) 0)
- tb = gmtime (&pfile->source_date_epoch);
- else
+ if (kind == CPP_time_kind::UNKNOWN)
{
- /* (time_t) -1 is a legitimate value for "number of seconds
- since the Epoch", so we have to do a little dance to
- distinguish that from a genuine error. */
- errno = 0;
- tt = time (NULL);
- if (tt != (time_t)-1 || errno == 0)
- tb = localtime (&tt);
+ cpp_errno (pfile, CPP_DL_WARNING,
+ "could not determine date and time");
+
+ pfile->date = UC"\"??? ?? ????\"";
+ pfile->time = UC"\"??:??:??\"";
}
-
- if (tb)
+ else
{
+ struct tm *tb = (kind == CPP_time_kind::FIXED
+ ? gmtime : localtime) (&tt);
+
pfile->date = _cpp_unaligned_alloc (pfile,
sizeof ("\"Oct 11 1347\""));
sprintf ((char *) pfile->date, "\"%s %2d %4d\"",
@@ -638,14 +628,6 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
sprintf ((char *) pfile->time, "\"%02d:%02d:%02d\"",
tb->tm_hour, tb->tm_min, tb->tm_sec);
}
- else
- {
- cpp_errno (pfile, CPP_DL_WARNING,
- "could not determine date and time");
-
- pfile->date = UC"\"??? ?? ????\"";
- pfile->time = UC"\"??:??:??\"";
- }
}
if (node->value.builtin == BT_DATE)
@@ -662,7 +644,11 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
break;
case BT_HAS_ATTRIBUTE:
- number = pfile->cb.has_attribute (pfile);
+ number = pfile->cb.has_attribute (pfile, false);
+ break;
+
+ case BT_HAS_STD_ATTRIBUTE:
+ number = pfile->cb.has_attribute (pfile, true);
break;
case BT_HAS_BUILTIN:
@@ -686,6 +672,51 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
return result;
}
+/* Get an idempotent date. Either the cached value, the value from
+ source epoch, or failing that, the value from time(2). Use this
+ during compilation so that every time stamp is the same. */
+CPP_time_kind
+cpp_get_date (cpp_reader *pfile, time_t *result)
+{
+ if (!pfile->time_stamp_kind)
+ {
+ int kind = 0;
+ if (pfile->cb.get_source_date_epoch)
+ {
+ /* Try reading the fixed epoch. */
+ pfile->time_stamp = pfile->cb.get_source_date_epoch (pfile);
+ if (pfile->time_stamp != time_t (-1))
+ kind = int (CPP_time_kind::FIXED);
+ }
+
+ if (!kind)
+ {
+ /* Pedantically time_t (-1) is a legitimate value for
+ "number of seconds since the Epoch". It is a silly
+ time. */
+ errno = 0;
+ pfile->time_stamp = time (nullptr);
+ /* Annoyingly a library could legally set errno and return a
+ valid time! Bad library! */
+ if (pfile->time_stamp == time_t (-1) && errno)
+ kind = errno;
+ else
+ kind = int (CPP_time_kind::DYNAMIC);
+ }
+
+ pfile->time_stamp_kind = kind;
+ }
+
+ *result = pfile->time_stamp;
+ if (pfile->time_stamp_kind >= 0)
+ {
+ errno = pfile->time_stamp_kind;
+ return CPP_time_kind::UNKNOWN;
+ }
+
+ return CPP_time_kind (pfile->time_stamp_kind);
+}
+
/* Convert builtin macros like __FILE__ to a token and push it on the
context stack. Also handles _Pragma, for which a new token may not
be created. Returns 1 if it generates a new token context, 0 to
@@ -1433,7 +1464,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
/* Laziness can only affect the expansion tokens of the macro,
not its fun-likeness or parameters. */
- _cpp_maybe_notify_macro_use (pfile, node);
+ _cpp_maybe_notify_macro_use (pfile, node, location);
if (pfile->cb.used)
pfile->cb.used (pfile, location, node);
@@ -2182,7 +2213,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
= (const cpp_token **) tokens_buff_last_token_ptr (buff);
}
else if (CPP_PEDANTIC (pfile) && ! CPP_OPTION (pfile, c99)
- && ! macro->syshdr && ! cpp_in_system_header (pfile))
+ && ! macro->syshdr && ! _cpp_in_system_header (pfile))
{
if (CPP_OPTION (pfile, cplusplus))
cpp_pedwarning (pfile, CPP_W_PEDANTIC,
@@ -2201,7 +2232,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
}
else if (CPP_OPTION (pfile, cpp_warn_c90_c99_compat) > 0
&& ! CPP_OPTION (pfile, cplusplus)
- && ! macro->syshdr && ! cpp_in_system_header (pfile))
+ && ! macro->syshdr && ! _cpp_in_system_header (pfile))
cpp_warning (pfile, CPP_W_C90_C99_COMPAT,
"invoking macro %s argument %d: "
"empty macro arguments are undefined"
@@ -2843,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;
@@ -2928,6 +2965,85 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location)
}
pfile->about_to_expand_macro_p = saved_about_to_expand_macro;
+
+ if (pfile->state.directive_file_token
+ && !pfile->state.parsing_args
+ && !(result->type == CPP_PADDING || result->type == CPP_COMMENT)
+ && !(15 & --pfile->state.directive_file_token))
+ {
+ /* Do header-name frobbery. Concatenate < ... > as approprate.
+ Do header search if needed, and finally drop the outer <> or
+ "". */
+ pfile->state.angled_headers = false;
+
+ /* Do angle-header reconstitution. Then do include searching.
+ We'll always end up with a ""-quoted header-name in that
+ case. If searching finds nothing, we emit a diagnostic and
+ an empty string. */
+ size_t len = 0;
+ char *fname = NULL;
+
+ cpp_token *tmp = _cpp_temp_token (pfile);
+ *tmp = *result;
+
+ tmp->type = CPP_HEADER_NAME;
+ bool need_search = !pfile->state.directive_file_token;
+ pfile->state.directive_file_token = 0;
+
+ bool angle = result->type != CPP_STRING;
+ if (result->type == CPP_HEADER_NAME
+ || (result->type == CPP_STRING && result->val.str.text[0] != 'R'))
+ {
+ len = result->val.str.len - 2;
+ fname = XNEWVEC (char, len + 1);
+ memcpy (fname, result->val.str.text + 1, len);
+ fname[len] = 0;
+ }
+ else if (result->type == CPP_LESS)
+ fname = _cpp_bracket_include (pfile);
+
+ if (fname)
+ {
+ /* We have a header-name. Look it up. This will emit an
+ unfound diagnostic. Canonicalize the found name. */
+ const char *found = fname;
+
+ if (need_search)
+ {
+ found = cpp_find_header_unit (pfile, fname, angle, tmp->src_loc);
+ if (!found)
+ found = "";
+ len = strlen (found);
+ }
+ /* Force a leading './' if it's not absolute. */
+ bool dotme = (found[0] == '.' ? !IS_DIR_SEPARATOR (found[1])
+ : found[0] && !IS_ABSOLUTE_PATH (found));
+
+ if (BUFF_ROOM (pfile->u_buff) < len + 1 + dotme * 2)
+ _cpp_extend_buff (pfile, &pfile->u_buff, len + 1 + dotme * 2);
+ unsigned char *buf = BUFF_FRONT (pfile->u_buff);
+ size_t pos = 0;
+
+ if (dotme)
+ {
+ buf[pos++] = '.';
+ /* Apparently '/' is unconditional. */
+ buf[pos++] = '/';
+ }
+ memcpy (&buf[pos], found, len);
+ pos += len;
+ buf[pos] = 0;
+
+ tmp->val.str.len = pos;
+ tmp->val.str.text = buf;
+
+ tmp->type = CPP_HEADER_NAME;
+ XDELETEVEC (fname);
+
+ result = tmp;
+ }
+ }
+
return result;
}
@@ -3102,15 +3218,16 @@ 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;
- }
+ 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. */
+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). */
@@ -3579,6 +3696,10 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement)
{
cpp_macro *macro = (cpp_macro *) placement;
+ /* Zero init all the fields. This'll tell the compiler know all the
+ following inits are writing a virgin object. */
+ memset (macro, 0, offsetof (cpp_macro, exp));
+
macro->line = pfile->directive_line;
macro->parm.params = 0;
macro->lazy = 0;
@@ -3587,6 +3708,7 @@ _cpp_new_macro (cpp_reader *pfile, cpp_macro_kind kind, void *placement)
macro->used = !CPP_OPTION (pfile, warn_unused_macros);
macro->count = 0;
macro->fun_like = 0;
+ macro->imported_p = false;
macro->extra_tokens = 0;
/* To suppress some diagnostics. */
macro->syshdr = pfile->buffer && pfile->buffer->sysp != 0;
@@ -3664,39 +3786,72 @@ 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)
+{
+ gcc_checking_assert (node->type == NT_USER_MACRO);
+
+ 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);
+ gcc_checking_assert (!macro || !macro->lazy);
+ }
+ else 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. */
+ or testing its existance). Also applies any lazy definition.
+ Return FALSE if the macro isn't really there. */
-extern void
-_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node)
+extern bool
+_cpp_notify_macro_use (cpp_reader *pfile, cpp_hashnode *node,
+ location_t loc)
{
node->flags |= NODE_USED;
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:
if (pfile->cb.used_define)
- pfile->cb.used_define (pfile, pfile->directive_line, node);
+ pfile->cb.used_define (pfile, loc, node);
break;
case NT_VOID:
if (pfile->cb.used_undef)
- pfile->cb.used_undef (pfile, pfile->directive_line, node);
+ pfile->cb.used_undef (pfile, loc, node);
break;
default:
abort ();
}
+
+ return true;
}
/* Warn if a token in STRING matches one of a function-like MACRO's
@@ -3749,12 +3904,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. */