aboutsummaryrefslogtreecommitdiff
path: root/libcpp/macro.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r--libcpp/macro.c147
1 files changed, 107 insertions, 40 deletions
diff --git a/libcpp/macro.c b/libcpp/macro.c
index cdb1821..f214548 100644
--- a/libcpp/macro.c
+++ b/libcpp/macro.c
@@ -1,5 +1,5 @@
/* Part of CPP library. (Macro and #define handling.)
- Copyright (C) 1986-2020 Free Software Foundation, Inc.
+ Copyright (C) 1986-2021 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -118,6 +118,7 @@ class vaopt_state {
m_arg (arg),
m_variadic (is_variadic),
m_last_was_paste (false),
+ m_stringify (false),
m_state (0),
m_paste_location (0),
m_location (0),
@@ -145,6 +146,7 @@ class vaopt_state {
}
++m_state;
m_location = token->src_loc;
+ m_stringify = (token->flags & STRINGIFY_ARG) != 0;
return BEGIN;
}
else if (m_state == 1)
@@ -234,6 +236,12 @@ class vaopt_state {
return m_state == 0;
}
+ /* Return true for # __VA_OPT__. */
+ bool stringify () const
+ {
+ return m_stringify;
+ }
+
private:
/* The cpp_reader. */
@@ -247,6 +255,8 @@ class vaopt_state {
/* If true, the previous token was ##. This is used to detect when
a paste occurs at the end of the sequence. */
bool m_last_was_paste;
+ /* True for #__VA_OPT__. */
+ bool m_stringify;
/* The state variable:
0 means not parsing
@@ -284,7 +294,8 @@ static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
static cpp_context *next_context (cpp_reader *);
static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
static const cpp_token *new_string_token (cpp_reader *, uchar *, unsigned int);
-static const cpp_token *stringify_arg (cpp_reader *, macro_arg *);
+static const cpp_token *stringify_arg (cpp_reader *, const cpp_token **,
+ unsigned int, bool);
static void paste_all_tokens (cpp_reader *, const cpp_token *);
static bool paste_tokens (cpp_reader *, location_t,
const cpp_token **, const cpp_token *);
@@ -531,15 +542,21 @@ _cpp_builtin_macro_text (cpp_reader *pfile, cpp_hashnode *node,
}
break;
case BT_FILE:
+ case BT_FILE_NAME:
case BT_BASE_FILE:
{
unsigned int len;
const char *name;
uchar *buf;
-
- if (node->value.builtin == BT_FILE)
- name = linemap_get_expansion_filename (pfile->line_table,
- pfile->line_table->highest_line);
+
+ if (node->value.builtin == BT_FILE
+ || node->value.builtin == BT_FILE_NAME)
+ {
+ name = linemap_get_expansion_filename (pfile->line_table,
+ pfile->line_table->highest_line);
+ if ((node->value.builtin == BT_FILE_NAME) && name)
+ name = lbasename (name);
+ }
else
{
name = _cpp_get_file_name (pfile->main_file);
@@ -812,10 +829,11 @@ cpp_quote_string (uchar *dest, const uchar *src, unsigned int len)
return dest;
}
-/* Convert a token sequence ARG to a single string token according to
- the rules of the ISO C #-operator. */
+/* Convert a token sequence FIRST to FIRST+COUNT-1 to a single string token
+ according to the rules of the ISO C #-operator. */
static const cpp_token *
-stringify_arg (cpp_reader *pfile, macro_arg *arg)
+stringify_arg (cpp_reader *pfile, const cpp_token **first, unsigned int count,
+ bool va_opt)
{
unsigned char *dest;
unsigned int i, escape_it, backslash_count = 0;
@@ -828,9 +846,27 @@ stringify_arg (cpp_reader *pfile, macro_arg *arg)
*dest++ = '"';
/* Loop, reading in the argument's tokens. */
- for (i = 0; i < arg->count; i++)
+ for (i = 0; i < count; i++)
{
- const cpp_token *token = arg->first[i];
+ const cpp_token *token = first[i];
+
+ if (va_opt && (token->flags & PASTE_LEFT))
+ {
+ location_t virt_loc = pfile->invocation_location;
+ const cpp_token *rhs;
+ do
+ {
+ if (i == count)
+ abort ();
+ rhs = first[++i];
+ if (!paste_tokens (pfile, virt_loc, &token, rhs))
+ {
+ --i;
+ break;
+ }
+ }
+ while (rhs->flags & PASTE_LEFT);
+ }
if (token->type == CPP_PADDING)
{
@@ -917,7 +953,7 @@ paste_tokens (cpp_reader *pfile, location_t location,
cpp_token *lhs;
unsigned int len;
- len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 1;
+ len = cpp_token_len (*plhs) + cpp_token_len (rhs) + 2;
buf = (unsigned char *) alloca (len);
end = lhsend = cpp_spell_token (pfile, *plhs, buf, true);
@@ -943,8 +979,10 @@ paste_tokens (cpp_reader *pfile, location_t location,
location_t saved_loc = lhs->src_loc;
_cpp_pop_buffer (pfile);
- _cpp_backup_tokens (pfile, 1);
- *lhsend = '\0';
+
+ unsigned char *rhsstart = lhsend;
+ if ((*plhs)->type == CPP_DIV && rhs->type != CPP_EQ)
+ rhsstart++;
/* We have to remove the PASTE_LEFT flag from the old lhs, but
we want to keep the new location. */
@@ -956,8 +994,10 @@ paste_tokens (cpp_reader *pfile, location_t location,
/* Mandatory error for all apart from assembler. */
if (CPP_OPTION (pfile, lang) != CLK_ASM)
cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
- "pasting \"%s\" and \"%s\" does not give a valid preprocessing token",
- buf, cpp_token_as_text (pfile, rhs));
+ "pasting \"%.*s\" and \"%.*s\" does not give "
+ "a valid preprocessing token",
+ (int) (lhsend - buf), buf,
+ (int) (end - rhsstart), rhsstart);
return false;
}
@@ -1033,7 +1073,10 @@ paste_all_tokens (cpp_reader *pfile, const cpp_token *lhs)
abort ();
}
if (!paste_tokens (pfile, virt_loc, &lhs, rhs))
- break;
+ {
+ _cpp_backup_tokens (pfile, 1);
+ break;
+ }
}
while (rhs->flags & PASTE_LEFT);
@@ -1900,7 +1943,8 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
if (src->flags & STRINGIFY_ARG)
{
if (!arg->stringified)
- arg->stringified = stringify_arg (pfile, arg);
+ arg->stringified = stringify_arg (pfile, arg->first, arg->count,
+ false);
}
else if ((src->flags & PASTE_LEFT)
|| (src != macro->exp.tokens && (src[-1].flags & PASTE_LEFT)))
@@ -1991,7 +2035,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
/* __VA_OPT__ handling. */
vaopt_state::update_type vostate = vaopt_tracker.update (src);
- if (vostate != vaopt_state::INCLUDE)
+ if (__builtin_expect (vostate != vaopt_state::INCLUDE, false))
{
if (vostate == vaopt_state::BEGIN)
{
@@ -2014,17 +2058,35 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
const cpp_token **start = vaopt_start;
vaopt_start = NULL;
- /* Remove any tail padding from inside the __VA_OPT__. */
paste_flag = tokens_buff_last_token_ptr (buff);
- while (paste_flag && paste_flag != start
- && (*paste_flag)->type == CPP_PADDING)
+
+ if (vaopt_tracker.stringify ())
{
- tokens_buff_remove_last_token (buff);
- paste_flag = tokens_buff_last_token_ptr (buff);
+ unsigned int count
+ = start ? paste_flag - start : tokens_buff_count (buff);
+ const cpp_token *t
+ = stringify_arg (pfile,
+ start ? start + 1
+ : (const cpp_token **) (buff->base),
+ count, true);
+ while (count--)
+ tokens_buff_remove_last_token (buff);
+ if (src->flags & PASTE_LEFT)
+ copy_paste_flag (pfile, &t, src);
+ tokens_buff_add_token (buff, virt_locs,
+ t, t->src_loc, t->src_loc,
+ NULL, 0);
}
-
- if (src->flags & PASTE_LEFT)
+ else if (src->flags & PASTE_LEFT)
{
+ /* Don't avoid paste after all. */
+ while (paste_flag && paste_flag != start
+ && *paste_flag == &pfile->avoid_paste)
+ {
+ tokens_buff_remove_last_token (buff);
+ paste_flag = tokens_buff_last_token_ptr (buff);
+ }
+
/* With a non-empty __VA_OPT__ on the LHS of ##, the last
token should be flagged PASTE_LEFT. */
if (paste_flag && (*paste_flag)->type != CPP_PADDING)
@@ -2120,11 +2182,8 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
else
paste_flag = tmp_token_ptr;
}
- /* Remove the paste flag if the RHS is a placemarker, unless the
- previous emitted token is at the beginning of __VA_OPT__;
- placemarkers within __VA_OPT__ are ignored in that case. */
- else if (arg_tokens_count == 0
- && tmp_token_ptr != vaopt_start)
+ /* Remove the paste flag if the RHS is a placemarker. */
+ else if (arg_tokens_count == 0)
paste_flag = tmp_token_ptr;
}
}
@@ -2154,7 +2213,8 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
/* Padding on the left of an argument (unless RHS of ##). */
if ((!pfile->state.in_directive || pfile->state.directive_wants_padding)
- && src != macro->exp.tokens && !(src[-1].flags & PASTE_LEFT)
+ && src != macro->exp.tokens
+ && !(src[-1].flags & PASTE_LEFT)
&& !last_token_is (buff, vaopt_start))
{
const cpp_token *t = padding_token (pfile, src);
@@ -2199,8 +2259,8 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
token_index += j;
index = expanded_token_index (pfile, macro, src, token_index);
- tokens_buff_add_token (buff, virt_locs,
- macro_arg_token_iter_get_token (&from),
+ const cpp_token *tok = macro_arg_token_iter_get_token (&from);
+ tokens_buff_add_token (buff, virt_locs, tok,
macro_arg_token_iter_get_location (&from),
src->src_loc, map, index);
macro_arg_token_iter_forward (&from);
@@ -2240,8 +2300,7 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro,
NODE_NAME (node), src->val.macro_arg.arg_no);
/* Avoid paste on RHS (even case count == 0). */
- if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT)
- && !last_token_is (buff, vaopt_start))
+ if (!pfile->state.in_directive && !(src->flags & PASTE_LEFT))
{
const cpp_token *t = &pfile->avoid_paste;
tokens_buff_add_token (buff, virt_locs,
@@ -3010,7 +3069,7 @@ cpp_get_token_1 (cpp_reader *pfile, location_t *location)
if (need_search)
{
- found = cpp_find_header_unit (pfile, fname, angle, tmp->src_loc);
+ found = _cpp_find_header_unit (pfile, fname, angle, tmp->src_loc);
if (!found)
found = "";
len = strlen (found);
@@ -3110,7 +3169,8 @@ cpp_get_token_with_location (cpp_reader *pfile, location_t *loc)
/* Returns true if we're expanding an object-like macro that was
defined in a system header. Just checks the macro at the top of
- the stack. Used for diagnostic suppression. */
+ the stack. Used for diagnostic suppression.
+ Also return true for builtin macros. */
int
cpp_sys_macro_p (cpp_reader *pfile)
{
@@ -3121,7 +3181,11 @@ cpp_sys_macro_p (cpp_reader *pfile)
else
node = pfile->context->c.macro;
- return node && node->value.macro && node->value.macro->syshdr;
+ if (!node)
+ return false;
+ if (cpp_builtin_macro_p (node))
+ return true;
+ return node->value.macro && node->value.macro->syshdr;
}
/* Read each token in, until end of the current file. Directives are
@@ -3574,7 +3638,10 @@ create_iso_definition (cpp_reader *pfile)
function-like macros when lexing the subsequent token. */
if (macro->count > 1 && token[-1].type == CPP_HASH && macro->fun_like)
{
- if (token->type == CPP_MACRO_ARG)
+ if (token->type == CPP_MACRO_ARG
+ || (macro->variadic
+ && token->type == CPP_NAME
+ && token->val.node.node == pfile->spec_nodes.n__VA_OPT__))
{
if (token->flags & PREV_WHITE)
token->flags |= SP_PREV_WHITE;