diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-11-20 16:02:55 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@linaro.org> | 2017-11-20 16:02:55 +0000 |
commit | d58952aefb03632bbb5b441d5c0bd330711f0af1 (patch) | |
tree | d046e56bfbd6a40106ae6ab96fafc954f1dfc955 /libcpp | |
parent | 648f8fc59b2cc39abd24f4c22388b346cdebcc31 (diff) | |
parent | 50221fae802a10fafe95e61d40504a58da33e98f (diff) | |
download | gcc-linaro-dev/sve.tar.gz |
Merge trunk into svelinaro-dev/sve
Diffstat (limited to 'libcpp')
-rw-r--r-- | libcpp/ChangeLog | 38 | ||||
-rw-r--r-- | libcpp/identifiers.c | 2 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 3 | ||||
-rw-r--r-- | libcpp/include/line-map.h | 46 | ||||
-rw-r--r-- | libcpp/init.c | 44 | ||||
-rw-r--r-- | libcpp/internal.h | 3 | ||||
-rw-r--r-- | libcpp/lex.c | 42 | ||||
-rw-r--r-- | libcpp/macro.c | 170 | ||||
-rw-r--r-- | libcpp/pch.c | 1 |
9 files changed, 297 insertions, 52 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 39e12bda927..70c834c61d0 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -1,3 +1,41 @@ +2017-11-13 Tom Tromey <tom@tromey.com> + + * pch.c (cpp_read_state): Set n__VA_OPT__. + * macro.c (vaopt_state): New class. + (_cpp_arguments_ok): Check va_opt flag. + (replace_args, create_iso_definition): Use vaopt_state. + * lex.c (lex_identifier_intern): Possibly issue errors for + __VA_OPT__. + (lex_identifier): Likewise. + (maybe_va_opt_error): New function. + * internal.h (struct lexer_state) <va_args_ok>: Update comment. + (struct spec_nodes) <n__VA_OPT__>: New field. + * init.c (struct lang_flags) <va_opt>: New field. + (lang_defaults): Add entries for C++2A. Update all entries for + va_opt. + (cpp_set_lang): Initialize va_opt. + * include/cpplib.h (struct cpp_options) <va_opt>: New field. + * identifiers.c (_cpp_init_hashtable): Initialize n__VA_OPT__. + +2017-11-13 David Malcolm <dmalcolm@redhat.com> + + * include/line-map.h (linenum_type): Move this typedef and the + comment describing column numbering to near the top of the file. + +2017-11-06 Mukesh Kapoor <mukesh.kapoor@oracle.com> + + PR c++/80955 + * lex.c (lex_string): When checking for a valid macro for the + warning related to -Wliteral-suffix (CPP_W_LITERAL_SUFFIX), + check that the macro name does not start with an underscore + before calling is_macro(). + +2017-11-05 Tom de Vries <tom@codesourcery.com> + + PR other/82784 + * lex.c (BUF_APPEND): Remove semicolon after + "do {} while (0)". + 2017-10-31 David Malcolm <dmalcolm@redhat.com> * directives.c (_cpp_handle_directive): Update for renaming of diff --git a/libcpp/identifiers.c b/libcpp/identifiers.c index 220f9b97f0d..e456fd3a4fc 100644 --- a/libcpp/identifiers.c +++ b/libcpp/identifiers.c @@ -70,6 +70,8 @@ _cpp_init_hashtable (cpp_reader *pfile, cpp_hash_table *table) s->n_false = cpp_lookup (pfile, DSC("false")); s->n__VA_ARGS__ = cpp_lookup (pfile, DSC("__VA_ARGS__")); s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC; + s->n__VA_OPT__ = cpp_lookup (pfile, DSC("__VA_OPT__")); + s->n__VA_OPT__->flags |= NODE_DIAGNOSTIC; s->n__has_include__ = cpp_lookup (pfile, DSC("__has_include__")); s->n__has_include_next__ = cpp_lookup (pfile, DSC("__has_include_next__")); } diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index 5a14858c44f..101b33aef48 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -478,6 +478,9 @@ struct cpp_options /* Nonzero for C++ 2014 Standard digit separators. */ unsigned char digit_separators; + /* Nonzero for C++2a __VA_OPT__ feature. */ + unsigned char va_opt; + /* Holds the name of the target (execution) character set. */ const char *narrow_charset; diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index e6960410c00..8b7e5dcd0ae 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -26,6 +26,29 @@ along with this program; see the file COPYING3. If not see #define GTY(x) /* nothing */ #endif +/* Both gcc and emacs number source *lines* starting at 1, but + they have differing conventions for *columns*. + + GCC uses a 1-based convention for source columns, + whereas Emacs's M-x column-number-mode uses a 0-based convention. + + For example, an error in the initial, left-hand + column of source line 3 is reported by GCC as: + + some-file.c:3:1: error: ...etc... + + On navigating to the location of that error in Emacs + (e.g. via "next-error"), + the locus is reported in the Mode Line + (assuming M-x column-number-mode) as: + + some-file.c 10% (3, 0) + + i.e. "3:1:" in GCC corresponds to "(3, 0)" in Emacs. */ + +/* The type of line numbers. */ +typedef unsigned int linenum_type; + /* Reason for creating a new line map with linemap_add. LC_ENTER is when including a new file, e.g. a #include directive in C. LC_LEAVE is when reaching a file's end. LC_RENAME is when a file @@ -43,9 +66,6 @@ enum lc_reason /* FIXME: add support for stringize and paste. */ }; -/* The type of line numbers. */ -typedef unsigned int linenum_type; - /* The typedef "source_location" is a key within the location database, identifying a source location or macro expansion, along with range information, and (optionally) a pointer for use by gcc. @@ -1251,26 +1271,6 @@ typedef struct bool sysp; } expanded_location; -/* Both gcc and emacs number source *lines* starting at 1, but - they have differing conventions for *columns*. - - GCC uses a 1-based convention for source columns, - whereas Emacs's M-x column-number-mode uses a 0-based convention. - - For example, an error in the initial, left-hand - column of source line 3 is reported by GCC as: - - some-file.c:3:1: error: ...etc... - - On navigating to the location of that error in Emacs - (e.g. via "next-error"), - the locus is reported in the Mode Line - (assuming M-x column-number-mode) as: - - some-file.c 10% (3, 0) - - i.e. "3:1:" in GCC corresponds to "(3, 0)" in Emacs. */ - /* A location within a rich_location: a caret&range, with the caret potentially flagged for display. */ diff --git a/libcpp/init.c b/libcpp/init.c index ecc81e3138a..8423656ad10 100644 --- a/libcpp/init.c +++ b/libcpp/init.c @@ -91,30 +91,31 @@ struct lang_flags char digit_separators; char trigraphs; char utf8_char_literals; + char va_opt; }; static const struct lang_flags lang_defaults[] = -{ /* c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit */ - /* GNUC89 */ { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, - /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, - /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, - /* GNUC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0 }, - /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 }, - /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 }, - /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 }, - /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }, - /* STDC17 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }, - /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, - /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0 }, - /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 }, - /* CXX11 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0 }, - /* GNUCXX14 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 }, - /* CXX14 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, - /* GNUCXX17 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, - /* CXX17 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 }, - /* GNUCXX2A */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, - /* CXX2A */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1 }, - /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +{ /* c99 c++ xnum xid c11 std digr ulit rlit udlit bincst digsep trig u8chlit vaopt */ + /* GNUC89 */ { 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + /* GNUC99 */ { 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, + /* GNUC11 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, + /* GNUC17 */ { 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1 }, + /* STDC89 */ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + /* STDC94 */ { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, + /* STDC99 */ { 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, + /* STDC11 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0 }, + /* STDC17 */ { 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0 }, + /* GNUCXX */ { 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, + /* CXX98 */ { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0 }, + /* GNUCXX11 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1 }, + /* CXX11 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0 }, + /* GNUCXX14 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1 }, + /* CXX14 */ { 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0 }, + /* GNUCXX17 */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + /* CXX17 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0 }, + /* GNUCXX2A */ { 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + /* CXX2A */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + /* ASM */ { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; /* Sets internal flags correctly for a given language. */ @@ -139,6 +140,7 @@ cpp_set_lang (cpp_reader *pfile, enum c_lang lang) CPP_OPTION (pfile, digit_separators) = l->digit_separators; CPP_OPTION (pfile, trigraphs) = l->trigraphs; CPP_OPTION (pfile, utf8_char_literals) = l->utf8_char_literals; + CPP_OPTION (pfile, va_opt) = l->va_opt; } /* Initialize library global state. */ diff --git a/libcpp/internal.h b/libcpp/internal.h index f24e85cfb11..0a33abafd43 100644 --- a/libcpp/internal.h +++ b/libcpp/internal.h @@ -246,7 +246,7 @@ struct lexer_state all directives apart from #define. */ unsigned char save_comments; - /* Nonzero if lexing __VA_ARGS__ is valid. */ + /* Nonzero if lexing __VA_ARGS__ and __VA_OPT__ are valid. */ unsigned char va_args_ok; /* Nonzero if lexing poisoned identifiers is valid. */ @@ -282,6 +282,7 @@ struct spec_nodes cpp_hashnode *n_true; /* C++ keyword true */ cpp_hashnode *n_false; /* C++ keyword false */ cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */ + cpp_hashnode *n__VA_OPT__; /* C++ vararg macros */ cpp_hashnode *n__has_include__; /* __has_include__ operator */ cpp_hashnode *n__has_include_next__; /* __has_include_next__ operator */ }; diff --git a/libcpp/lex.c b/libcpp/lex.c index 40ff801e8e3..a8dc3bae5e4 100644 --- a/libcpp/lex.c +++ b/libcpp/lex.c @@ -1352,6 +1352,28 @@ forms_identifier_p (cpp_reader *pfile, int first, return false; } +/* Helper function to issue error about improper __VA_OPT__ use. */ +static void +maybe_va_opt_error (cpp_reader *pfile) +{ + if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, va_opt)) + { + /* __VA_OPT__ should not be accepted at all, but allow it in + system headers. */ + if (!cpp_in_system_header (pfile)) + cpp_error (pfile, CPP_DL_PEDWARN, + "__VA_OPT__ is not available until C++2a"); + } + else if (!pfile->state.va_args_ok) + { + /* __VA_OPT__ should only appear in the replacement list of a + variadic macro. */ + cpp_error (pfile, CPP_DL_PEDWARN, + "__VA_OPT__ can only appear in the expansion" + " of a C++2a variadic macro"); + } +} + /* Helper function to get the cpp_hashnode of the identifier BASE. */ static cpp_hashnode * lex_identifier_intern (cpp_reader *pfile, const uchar *base) @@ -1396,6 +1418,9 @@ lex_identifier_intern (cpp_reader *pfile, const uchar *base) " of a C99 variadic macro"); } + if (result == pfile->spec_nodes.n__VA_OPT__) + maybe_va_opt_error (pfile); + /* For -Wc++-compat, warn about use of C++ named operators. */ if (result->flags & NODE_WARN_OPERATOR) cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES, @@ -1485,6 +1510,11 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, " of a C99 variadic macro"); } + /* __VA_OPT__ should only appear in the replacement list of a + variadic macro. */ + if (result == pfile->spec_nodes.n__VA_OPT__) + maybe_va_opt_error (pfile); + /* For -Wc++-compat, warn about use of C++ named operators. */ if (result->flags & NODE_WARN_OPERATOR) cpp_warning (pfile, CPP_W_CXX_OPERATOR_NAMES, @@ -1647,7 +1677,7 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, (const uchar *)(STR), (LEN)); \ temp_buffer_len += (LEN); \ } \ - } while (0); + } while (0) orig_base = base; ++cur; @@ -1871,8 +1901,9 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, /* If a string format macro, say from inttypes.h, is placed touching a string literal it could be parsed as a C++11 user-defined string literal thus breaking the program. - Try to identify macros with is_macro. A warning is issued. */ - if (is_macro (pfile, cur)) + Try to identify macros with is_macro. A warning is issued. + The macro name should not start with '_' for this warning. */ + if ((*cur != '_') && is_macro (pfile, cur)) { /* Raise a warning, but do not consume subsequent tokens. */ if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping) @@ -2001,8 +2032,9 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) /* If a string format macro, say from inttypes.h, is placed touching a string literal it could be parsed as a C++11 user-defined string literal thus breaking the program. - Try to identify macros with is_macro. A warning is issued. */ - if (is_macro (pfile, cur)) + Try to identify macros with is_macro. A warning is issued. + The macro name should not start with '_' for this warning. */ + if ((*cur != '_') && is_macro (pfile, cur)) { /* Raise a warning, but do not consume subsequent tokens. */ if (CPP_OPTION (pfile, warn_literal_suffix) && !pfile->state.skipping) diff --git a/libcpp/macro.c b/libcpp/macro.c index fab1cb051dc..bf473eae358 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -89,6 +89,155 @@ struct macro_arg_saved_data { union _cpp_hashnode_value value; }; +static const char *vaopt_paste_error = + N_("'##' cannot appear at either end of __VA_OPT__"); + +/* A class for tracking __VA_OPT__ state while iterating over a + sequence of tokens. This is used during both macro definition and + expansion. */ +class vaopt_state { + + public: + + /* Initialize the state tracker. ANY_ARGS is true if variable + arguments were provided to the macro invocation. */ + vaopt_state (cpp_reader *pfile, bool is_variadic, bool any_args) + : m_pfile (pfile), + m_allowed (any_args), + m_variadic (is_variadic), + m_state (0), + m_last_was_paste (false), + m_paste_location (0), + m_location (0) + { + } + + enum update_type + { + ERROR, + DROP, + INCLUDE + }; + + /* Given a token, update the state of this tracker and return a + boolean indicating whether the token should be be included in the + expansion. */ + update_type update (const cpp_token *token) + { + /* If the macro isn't variadic, just don't bother. */ + if (!m_variadic) + return INCLUDE; + + if (token->type == CPP_NAME + && token->val.node.node == m_pfile->spec_nodes.n__VA_OPT__) + { + if (m_state > 0) + { + cpp_error_at (m_pfile, CPP_DL_ERROR, token->src_loc, + "__VA_OPT__ may not appear in a __VA_OPT__"); + return ERROR; + } + ++m_state; + m_location = token->src_loc; + return DROP; + } + else if (m_state == 1) + { + if (token->type != CPP_OPEN_PAREN) + { + cpp_error_at (m_pfile, CPP_DL_ERROR, m_location, + "__VA_OPT__ must be followed by an " + "open parenthesis"); + return ERROR; + } + ++m_state; + return DROP; + } + else if (m_state >= 2) + { + if (m_state == 2 && token->type == CPP_PASTE) + { + cpp_error_at (m_pfile, CPP_DL_ERROR, token->src_loc, + vaopt_paste_error); + return ERROR; + } + /* Advance states before further considering this token, in + case we see a close paren immediately after the open + paren. */ + if (m_state == 2) + ++m_state; + + bool was_paste = m_last_was_paste; + m_last_was_paste = false; + if (token->type == CPP_PASTE) + { + m_last_was_paste = true; + m_paste_location = token->src_loc; + } + else if (token->type == CPP_OPEN_PAREN) + ++m_state; + else if (token->type == CPP_CLOSE_PAREN) + { + --m_state; + if (m_state == 2) + { + /* Saw the final paren. */ + m_state = 0; + + if (was_paste) + { + cpp_error_at (m_pfile, CPP_DL_ERROR, token->src_loc, + vaopt_paste_error); + return ERROR; + } + + return DROP; + } + } + return m_allowed ? INCLUDE : DROP; + } + + /* Nothing to do with __VA_OPT__. */ + return INCLUDE; + } + + /* Ensure that any __VA_OPT__ was completed. If ok, return true. + Otherwise, issue an error and return false. */ + bool completed () + { + if (m_variadic && m_state != 0) + cpp_error_at (m_pfile, CPP_DL_ERROR, m_location, + "unterminated __VA_OPT__"); + return m_state == 0; + } + + private: + + /* The cpp_reader. */ + cpp_reader *m_pfile; + + /* True if there were varargs. */ + bool m_allowed; + /* True if the macro is variadic. */ + bool m_variadic; + + /* The state variable: + 0 means not parsing + 1 means __VA_OPT__ seen, looking for "(" + 2 means "(" seen (so the next token can't be "##") + >= 3 means looking for ")", the number encodes the paren depth. */ + int m_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; + /* The location of the paste token. */ + source_location m_paste_location; + + /* Location of the __VA_OPT__ token. */ + source_location m_location; +}; + /* Macro expansion. */ static int enter_macro_context (cpp_reader *, cpp_hashnode *, @@ -776,7 +925,8 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node if (argc < macro->paramc) { - /* As an extension, variadic arguments are allowed to not appear in + /* In C++2a (here the va_opt flag is used), and also as a GNU + extension, variadic arguments are allowed to not appear in the invocation at all. e.g. #define debug(format, args...) something debug("string"); @@ -786,7 +936,8 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node if (argc + 1 == macro->paramc && macro->variadic) { - if (CPP_PEDANTIC (pfile) && ! macro->syshdr) + if (CPP_PEDANTIC (pfile) && ! macro->syshdr + && ! CPP_OPTION (pfile, va_opt)) { if (CPP_OPTION (pfile, cplusplus)) cpp_error (pfile, CPP_DL_PEDWARN, @@ -1678,6 +1829,8 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, num_macro_tokens); } i = 0; + vaopt_state vaopt_tracker (pfile, macro->variadic, + args[macro->paramc - 1].count > 0); for (src = macro->exp.tokens; src < limit; src++) { unsigned int arg_tokens_count; @@ -1685,6 +1838,10 @@ replace_args (cpp_reader *pfile, cpp_hashnode *node, cpp_macro *macro, const cpp_token **paste_flag = NULL; const cpp_token **tmp_token_ptr; + /* __VA_OPT__ handling. */ + if (vaopt_tracker.update (src) != vaopt_state::INCLUDE) + continue; + if (src->type != CPP_MACRO_ARG) { /* Allocate a virtual location for token SRC, and add that @@ -3076,6 +3233,9 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) *token = *ctoken; } + /* The argument doesn't matter here. */ + vaopt_state vaopt_tracker (pfile, macro->variadic, true); + for (;;) { /* Check the stringifying # constraint 6.10.3.2.1 of @@ -3144,10 +3304,16 @@ create_iso_definition (cpp_reader *pfile, cpp_macro *macro) } } + if (vaopt_tracker.update (token) == vaopt_state::ERROR) + return false; + following_paste_op = (token->type == CPP_PASTE); token = lex_expansion_token (pfile, macro); } + if (!vaopt_tracker.completed ()) + return false; + macro->exp.tokens = (cpp_token *) BUFF_FRONT (pfile->a_buff); macro->traditional = 0; diff --git a/libcpp/pch.c b/libcpp/pch.c index cad4b872cda..b685a38a854 100644 --- a/libcpp/pch.c +++ b/libcpp/pch.c @@ -835,6 +835,7 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f, s->n_true = cpp_lookup (r, DSC("true")); s->n_false = cpp_lookup (r, DSC("false")); s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__")); + s->n__VA_OPT__ = cpp_lookup (r, DSC("__VA_OPT__")); s->n__has_include__ = cpp_lookup (r, DSC("__has_include__")); s->n__has_include_next__ = cpp_lookup (r, DSC("__has_include_next__")); } |