diff options
Diffstat (limited to 'libcpp/macro.c')
-rw-r--r-- | libcpp/macro.c | 147 |
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; |