diff options
Diffstat (limited to 'libcpp/lex.c')
-rw-r--r-- | libcpp/lex.c | 42 |
1 files changed, 37 insertions, 5 deletions
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) |