From a81ea6a8ada45f45ee2ee52e5b5d3d5a40adcc4e Mon Sep 17 00:00:00 2001 From: jwnhy Date: Fri, 2 Aug 2024 21:49:13 +0800 Subject: [PATCH 01/14] Add support_option_named_variadics --- include/boost/wave/language_support.hpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/boost/wave/language_support.hpp b/include/boost/wave/language_support.hpp index 6d011131f..2d869720e 100644 --- a/include/boost/wave/language_support.hpp +++ b/include/boost/wave/language_support.hpp @@ -61,7 +61,7 @@ enum language_support { #endif #endif - support_option_mask = 0xFFC0, + support_option_mask = 0x1FFC0, support_option_emit_contnewlines = 0x0040, support_option_insert_whitespace = 0x0080, support_option_preserve_comments = 0x0100, @@ -71,7 +71,8 @@ enum language_support { support_option_prefer_pp_numbers = 0x1000, support_option_emit_line_directives = 0x2000, support_option_include_guard_detection = 0x4000, - support_option_emit_pragma_directives = 0x8000 + support_option_emit_pragma_directives = 0x8000, + support_option_named_variadics = 0x10000, }; /////////////////////////////////////////////////////////////////////////////// @@ -240,6 +241,7 @@ BOOST_WAVE_OPTION(include_guard_detection) // support_option_include_guard_det #endif #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 BOOST_WAVE_OPTION(variadics) // support_option_variadics +BOOST_WAVE_OPTION(named_variadics) // support_option_named_variadic #endif #if BOOST_WAVE_SUPPORT_VA_OPT != 0 BOOST_WAVE_OPTION(va_opt) // support_option_va_opt From fc46553cb253c472795d1650a52cdbad0f4a4408 Mon Sep 17 00:00:00 2001 From: john Date: Sun, 8 Sep 2024 23:55:20 +0800 Subject: [PATCH 02/14] add gnu's named_variadics support --- include/boost/wave/grammars/cpp_grammar.hpp | 7 ++++-- include/boost/wave/language_support.hpp | 10 ++++++--- include/boost/wave/util/cpp_macromap.hpp | 8 +++++++ include/boost/wave/util/macro_definition.hpp | 23 +++++++++++++++++++- 4 files changed, 42 insertions(+), 6 deletions(-) diff --git a/include/boost/wave/grammars/cpp_grammar.hpp b/include/boost/wave/grammars/cpp_grammar.hpp index e310d43ac..3648f978d 100644 --- a/include/boost/wave/grammars/cpp_grammar.hpp +++ b/include/boost/wave/grammars/cpp_grammar.hpp @@ -354,16 +354,19 @@ struct cpp_grammar : = confix_p( no_node_d[ch_p(T_LEFTPAREN) >> *ppsp], !list_p( - ( ch_p(T_IDENTIFIER) - | pattern_p(KeywordTokenType, + ( pattern_p(KeywordTokenType, TokenTypeMask|PPTokenFlag) | pattern_p(OperatorTokenType|AltExtTokenType, ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | pattern_p(BoolLiteralTokenType, TokenTypeMask|PPTokenFlag) // true/false #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + | lexeme_d[ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)] +#endif | ch_p(T_ELLIPSIS) #endif + | ch_p(T_IDENTIFIER) // must be after the named variadic ), no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp] ), diff --git a/include/boost/wave/language_support.hpp b/include/boost/wave/language_support.hpp index 2d869720e..5e5dc7922 100644 --- a/include/boost/wave/language_support.hpp +++ b/include/boost/wave/language_support.hpp @@ -33,6 +33,9 @@ enum language_support { // support flags for C99 support_option_variadics = 0x04, support_c99 = support_option_variadics | support_option_long_long | 0x08, +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + support_option_named_variadics = 0x100000, +#endif #endif #if BOOST_WAVE_SUPPORT_CPP0X != 0 // support flags for C++11 @@ -61,7 +64,7 @@ enum language_support { #endif #endif - support_option_mask = 0x1FFC0, + support_option_mask = 0xFFC0, support_option_emit_contnewlines = 0x0040, support_option_insert_whitespace = 0x0080, support_option_preserve_comments = 0x0100, @@ -72,7 +75,6 @@ enum language_support { support_option_emit_line_directives = 0x2000, support_option_include_guard_detection = 0x4000, support_option_emit_pragma_directives = 0x8000, - support_option_named_variadics = 0x10000, }; /////////////////////////////////////////////////////////////////////////////// @@ -241,7 +243,9 @@ BOOST_WAVE_OPTION(include_guard_detection) // support_option_include_guard_det #endif #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 BOOST_WAVE_OPTION(variadics) // support_option_variadics -BOOST_WAVE_OPTION(named_variadics) // support_option_named_variadic +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 +BOOST_WAVE_OPTION(named_variadics) // support_option_named_variadics +#endif #endif #if BOOST_WAVE_SUPPORT_VA_OPT != 0 BOOST_WAVE_OPTION(va_opt) // support_option_va_opt diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index 5c49e1f21..93b1a54d5 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -1486,6 +1486,14 @@ macromap::expand_macro(ContainerT &expanded, macro_def.macroparameters.size(), seen_newline); std::size_t parm_count_required = macro_def.macroparameters.size(); +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + if (boost::wave::need_named_variadics(ctx.get_language())) { + if ((parm_count_required >= 2) && + T_ELLIPSIS == token_id(*(macro_def.macroparameters.end() - 1)) && + T_IDENTIFIER == token_id(*(macro_def.macroparameters.end() - 2))) + --parm_count_required; + } +#endif #if BOOST_WAVE_SUPPORT_CPP2A if (boost::wave::need_cpp2a(ctx.get_language())) { // Starting with C++20, variable arguments may be left out diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index 29ecdccdf..8e97eac36 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -81,6 +81,18 @@ struct macro_definition { if (!replaced_parameters) { typename definition_container_type::iterator end = macrodefinition.end(); typename definition_container_type::iterator it = macrodefinition.begin(); + typename ContextT::string_type va_args = "__VA_ARGS__"; +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS + if (need_named_variadics(ctx.get_language())) { + const_parameter_iterator_t cend = macroparameters.end(); + const_parameter_iterator_t cbegin = macroparameters.begin(); + if (macroparameters.size() >= 2 && + T_IDENTIFIER == token_id(*(cend-2)) && + T_ELLIPSIS == token_id(*(cend-1))) { + va_args = (*(cend-2)).get_value(); + } + } +#endif for (/**/; it != end; ++it) { token_id id = *it; @@ -96,6 +108,15 @@ struct macro_definition { for (typename parameter_container_type::size_type i = 0; cit != cend; ++cit, ++i) { +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS + if (need_named_variadics(ctx.get_language()) && + T_IDENTIFIER == token_id(*cit) && + cit == cend - 2 && + T_ELLIPSIS == token_id(*(cit+1))) { + --i; + continue; + } +#endif if ((*it).get_value() == (*cit).get_value()) { (*it).set_token_id(token_id(T_PARAMETERBASE+i)); break; @@ -103,7 +124,7 @@ struct macro_definition { #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 else if (need_variadics(ctx.get_language()) && T_ELLIPSIS == token_id(*cit) && - "__VA_ARGS__" == (*it).get_value()) + va_args == (*it).get_value()) { // __VA_ARGS__ requires special handling (*it).set_token_id(token_id(T_EXTPARAMETERBASE+i)); From 2d252d72c28d7b8a125cf0d67fc9bce8d4918afa Mon Sep 17 00:00:00 2001 From: john Date: Mon, 9 Sep 2024 00:05:05 +0800 Subject: [PATCH 03/14] add gnu's named_variadics support --- include/boost/wave/grammars/cpp_grammar.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/wave/grammars/cpp_grammar.hpp b/include/boost/wave/grammars/cpp_grammar.hpp index 3648f978d..878373555 100644 --- a/include/boost/wave/grammars/cpp_grammar.hpp +++ b/include/boost/wave/grammars/cpp_grammar.hpp @@ -363,6 +363,7 @@ struct cpp_grammar : #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 | lexeme_d[ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)] + | ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS) #endif | ch_p(T_ELLIPSIS) #endif From c6dc014f6fa0425d0832978496f66c13357be21d Mon Sep 17 00:00:00 2001 From: john Date: Mon, 9 Sep 2024 09:16:35 +0800 Subject: [PATCH 04/14] ensure all named variadics is guarded by normal variadics --- include/boost/wave/util/macro_definition.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index 8e97eac36..0e0a15ed6 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -82,7 +82,8 @@ struct macro_definition { typename definition_container_type::iterator end = macrodefinition.end(); typename definition_container_type::iterator it = macrodefinition.begin(); typename ContextT::string_type va_args = "__VA_ARGS__"; -#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS +#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (need_named_variadics(ctx.get_language())) { const_parameter_iterator_t cend = macroparameters.end(); const_parameter_iterator_t cbegin = macroparameters.begin(); @@ -92,6 +93,7 @@ struct macro_definition { va_args = (*(cend-2)).get_value(); } } +#endif #endif for (/**/; it != end; ++it) { @@ -108,6 +110,7 @@ struct macro_definition { for (typename parameter_container_type::size_type i = 0; cit != cend; ++cit, ++i) { +#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS if (need_named_variadics(ctx.get_language()) && T_IDENTIFIER == token_id(*cit) && @@ -116,6 +119,7 @@ struct macro_definition { --i; continue; } +#endif #endif if ((*it).get_value() == (*cit).get_value()) { (*it).set_token_id(token_id(T_PARAMETERBASE+i)); From 2c0ceb47123f9cbe74e0390d794042ba549b0854 Mon Sep 17 00:00:00 2001 From: john Date: Mon, 9 Sep 2024 09:31:51 +0800 Subject: [PATCH 05/14] ensure all named variadics is guarded by normal variadics & add warning for named variadics without variadics --- include/boost/wave/util/cpp_macromap.hpp | 2 ++ include/boost/wave/util/macro_definition.hpp | 2 +- include/boost/wave/wave_config.hpp | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index 93b1a54d5..d8dc38f24 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -1486,6 +1486,7 @@ macromap::expand_macro(ContainerT &expanded, macro_def.macroparameters.size(), seen_newline); std::size_t parm_count_required = macro_def.macroparameters.size(); +#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (boost::wave::need_named_variadics(ctx.get_language())) { if ((parm_count_required >= 2) && @@ -1494,6 +1495,7 @@ macromap::expand_macro(ContainerT &expanded, --parm_count_required; } #endif +#endif #if BOOST_WAVE_SUPPORT_CPP2A if (boost::wave::need_cpp2a(ctx.get_language())) { // Starting with C++20, variable arguments may be left out diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index 0e0a15ed6..9dd49eb4f 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -111,7 +111,7 @@ struct macro_definition { cit != cend; ++cit, ++i) { #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 -#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (need_named_variadics(ctx.get_language()) && T_IDENTIFIER == token_id(*cit) && cit == cend - 2 && diff --git a/include/boost/wave/wave_config.hpp b/include/boost/wave/wave_config.hpp index 04844cc88..4010c7f1b 100644 --- a/include/boost/wave/wave_config.hpp +++ b/include/boost/wave/wave_config.hpp @@ -158,6 +158,23 @@ #endif #endif +/////////////////////////////////////////////////////////////////////////////// +// Change the following, to enable the support for GNU named variadics: +// #define(x...) x +// By default this is disabled. +#if !defined(BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS) +#define BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS 0 +#endif + + +/////////////////////////////////////////////////////////////////////////////// +// Warn the user if GNU named variadics are enabled without variadics support +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 +#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS == 0 +#warning "Boost.Wave: The support for GNU named variadics requires variadics support." +#endif +#endif + /////////////////////////////////////////////////////////////////////////////// // Allow the message body of the #error and #warning directives to be // preprocessed before the diagnostic is issued. From 9faf9daef89ce307da74649aa3f12210b06fdf87 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 10:19:18 +0800 Subject: [PATCH 06/14] reduce the number of mandatory parameters --- include/boost/wave/util/cpp_macromap.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index d8dc38f24..0b051da7d 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -1489,13 +1489,15 @@ macromap::expand_macro(ContainerT &expanded, #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (boost::wave::need_named_variadics(ctx.get_language())) { + // named variadics can be completely left out if ((parm_count_required >= 2) && T_ELLIPSIS == token_id(*(macro_def.macroparameters.end() - 1)) && T_IDENTIFIER == token_id(*(macro_def.macroparameters.end() - 2))) - --parm_count_required; + parm_count_required -= 2; } #endif #endif + #if BOOST_WAVE_SUPPORT_CPP2A if (boost::wave::need_cpp2a(ctx.get_language())) { // Starting with C++20, variable arguments may be left out From 84da6e23297a9f1045f3441f25b432603c319e30 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 17:35:13 +0800 Subject: [PATCH 07/14] reworked --- include/boost/wave/cpp_exceptions.hpp | 5 ++++ include/boost/wave/grammars/cpp_grammar.hpp | 20 +++++++++++-- include/boost/wave/token_ids.hpp | 3 ++ include/boost/wave/util/cpp_iterator.hpp | 13 +++++++++ include/boost/wave/util/cpp_macromap.hpp | 11 ------- include/boost/wave/util/macro_definition.hpp | 30 +++++++++----------- src/token_ids.cpp | 2 ++ 7 files changed, 53 insertions(+), 31 deletions(-) diff --git a/include/boost/wave/cpp_exceptions.hpp b/include/boost/wave/cpp_exceptions.hpp index 1358479d9..37dc5a893 100644 --- a/include/boost/wave/cpp_exceptions.hpp +++ b/include/boost/wave/cpp_exceptions.hpp @@ -116,6 +116,7 @@ class BOOST_SYMBOL_VISIBLE preprocess_exception : ill_formed_operator, bad_define_statement, bad_define_statement_va_args, + bad_define_statement_named_va_args, bad_define_statement_va_opt, bad_define_statement_va_opt_parens, bad_define_statement_va_opt_recurse, @@ -209,6 +210,7 @@ class BOOST_SYMBOL_VISIBLE preprocess_exception : case preprocess_exception::unbalanced_if_endif: case preprocess_exception::bad_define_statement: case preprocess_exception::bad_define_statement_va_args: + case preprocess_exception::bad_define_statement_named_va_args: case preprocess_exception::bad_define_statement_va_opt: case preprocess_exception::bad_define_statement_va_opt_parens: case preprocess_exception::bad_define_statement_va_opt_recurse: @@ -265,6 +267,8 @@ class BOOST_SYMBOL_VISIBLE preprocess_exception : "ill formed #define directive", // bad_define_statement "__VA_ARGS__ can only appear in the " "expansion of a C99 variadic macro", // bad_define_statement_va_args + "named variadic like x... is disabled, " + "please enable_named_variadics() to enable", // bad_define_statement_named_va_args "__VA_OPT__ can only appear in the " "expansion of a C++20 variadic macro", // bad_define_statement_va_opt "__VA_OPT__ must be followed by a left " @@ -334,6 +338,7 @@ class BOOST_SYMBOL_VISIBLE preprocess_exception : util::severity_error, // ill_formed_operator util::severity_error, // bad_define_statement util::severity_error, // bad_define_statement_va_args + util::severity_error, // bad_define_statement_named_va_args util::severity_error, // bad_define_statement_va_opt util::severity_error, // bad_define_statement_va_opt_parens util::severity_error, // bad_define_statement_va_opt_recurse diff --git a/include/boost/wave/grammars/cpp_grammar.hpp b/include/boost/wave/grammars/cpp_grammar.hpp index 878373555..d3e35a606 100644 --- a/include/boost/wave/grammars/cpp_grammar.hpp +++ b/include/boost/wave/grammars/cpp_grammar.hpp @@ -347,7 +347,17 @@ struct cpp_grammar : ) ) ; - +#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + typedef typename ScannerT::iterator_t iterator_t; + typedef node_val_data node_t; + typedef typename node_t::iterator_t container_iterator_t; + const auto &named_variadics = [](tree_node& node, iterator_t begin, iterator_t end) { + container_iterator_t it = node.value.begin(); + it->set_token_id(T_GNU_NAMED_ELLIPSIS); + }; +#endif +#endif // parameter list // normal C++ mode macro_parameters @@ -362,8 +372,12 @@ struct cpp_grammar : TokenTypeMask|PPTokenFlag) // true/false #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - | lexeme_d[ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)] - | ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS) + | access_node_d[ + token_node_d[ + lexeme_d[ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)] + | (ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)) + ]][named_variadics] + #endif | ch_p(T_ELLIPSIS) #endif diff --git a/include/boost/wave/token_ids.hpp b/include/boost/wave/token_ids.hpp index 713a7d862..1e9521bf7 100644 --- a/include/boost/wave/token_ids.hpp +++ b/include/boost/wave/token_ids.hpp @@ -315,6 +315,9 @@ enum token_id : std::uint32_t { // C++20 operators T_SPACESHIP = TOKEN_FROM_ID(441, OperatorTokenType), +// GNU named variadics + T_GNU_NAMED_ELLIPSIS = TOKEN_FROM_ID(442, IdentifierTokenType), + T_LAST_TOKEN_ID, T_LAST_TOKEN = ID_FROM_TOKEN(T_LAST_TOKEN_ID & ~PPTokenFlag), diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index 9c0a2966a..fcfb2239b 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1731,6 +1731,19 @@ pp_iterator_functor::on_define (parse_node_type const &node) (*pit).get_position()); return; } +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + if (T_GNU_NAMED_ELLIPSIS == token_id(*pit)) { + if (boost::wave::need_named_variadics(ctx.get_language())) + seen_ellipses = true; + else { + // named variadics are not supported + BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, + bad_define_statement_named_va_args, macroname.get_value().c_str(), + (*pit).get_position()); + return; + } + } +#endif if (T_ELLIPSIS == token_id(*pit)) seen_ellipses = true; diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index 0b051da7d..cca2b18d7 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -1486,17 +1486,6 @@ macromap::expand_macro(ContainerT &expanded, macro_def.macroparameters.size(), seen_newline); std::size_t parm_count_required = macro_def.macroparameters.size(); -#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 -#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - if (boost::wave::need_named_variadics(ctx.get_language())) { - // named variadics can be completely left out - if ((parm_count_required >= 2) && - T_ELLIPSIS == token_id(*(macro_def.macroparameters.end() - 1)) && - T_IDENTIFIER == token_id(*(macro_def.macroparameters.end() - 2))) - parm_count_required -= 2; - } -#endif -#endif #if BOOST_WAVE_SUPPORT_CPP2A if (boost::wave::need_cpp2a(ctx.get_language())) { diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index 9dd49eb4f..5cad29554 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -85,12 +85,9 @@ struct macro_definition { #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (need_named_variadics(ctx.get_language())) { - const_parameter_iterator_t cend = macroparameters.end(); - const_parameter_iterator_t cbegin = macroparameters.begin(); - if (macroparameters.size() >= 2 && - T_IDENTIFIER == token_id(*(cend-2)) && - T_ELLIPSIS == token_id(*(cend-1))) { - va_args = (*(cend-2)).get_value(); + if (macroparameters.size() > 0 && + T_GNU_NAMED_ELLIPSIS == token_id(macroparameters.back())) { + va_args = macroparameters.back().get_value(); } } #endif @@ -110,17 +107,6 @@ struct macro_definition { for (typename parameter_container_type::size_type i = 0; cit != cend; ++cit, ++i) { -#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 -#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - if (need_named_variadics(ctx.get_language()) && - T_IDENTIFIER == token_id(*cit) && - cit == cend - 2 && - T_ELLIPSIS == token_id(*(cit+1))) { - --i; - continue; - } -#endif -#endif if ((*it).get_value() == (*cit).get_value()) { (*it).set_token_id(token_id(T_PARAMETERBASE+i)); break; @@ -134,6 +120,16 @@ struct macro_definition { (*it).set_token_id(token_id(T_EXTPARAMETERBASE+i)); break; } +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + else if (need_named_variadics(ctx.get_language()) && + T_GNU_NAMED_ELLIPSIS == token_id(*cit) && + va_args == (*it).get_value()) + { + // __VA_ARGS__ requires special handling + (*it).set_token_id(token_id(T_EXTPARAMETERBASE+i)); + break; + } +#endif #if BOOST_WAVE_SUPPORT_VA_OPT != 0 else if (need_va_opt(ctx.get_language()) && T_ELLIPSIS == token_id(*cit) && diff --git a/src/token_ids.cpp b/src/token_ids.cpp index 6a0b1cc6d..8851da2e6 100644 --- a/src/token_ids.cpp +++ b/src/token_ids.cpp @@ -232,6 +232,7 @@ static char const *tok_names[] = { /* 439 */ "T_CO_YIELD", /* 440 */ "T_REQUIRES", /* 441 */ "T_SPACESHIP", + /* 442 */ "T_GNU_NAMED_ELLIPSIS", }; // make sure, I have not forgotten any commas (as I did more than once) @@ -444,6 +445,7 @@ static char const *tok_values[] = { /* 439 */ "co_yield", /* 440 */ "requires", /* 441 */ "<=>", + /* 442 */ "", // gnu_named_ellipsis }; // make sure, I have not forgotten any commas (as I did more than once) From 48292da797525eed2b8b55d6a556dfd82f362e7d Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 18:22:53 +0800 Subject: [PATCH 08/14] reworked --- include/boost/wave/grammars/cpp_grammar.hpp | 1 + include/boost/wave/util/cpp_iterator.hpp | 17 +++++++++++++++++ include/boost/wave/util/macro_definition.hpp | 8 ++++++++ 3 files changed, 26 insertions(+) diff --git a/include/boost/wave/grammars/cpp_grammar.hpp b/include/boost/wave/grammars/cpp_grammar.hpp index d3e35a606..f53ffb73f 100644 --- a/include/boost/wave/grammars/cpp_grammar.hpp +++ b/include/boost/wave/grammars/cpp_grammar.hpp @@ -355,6 +355,7 @@ struct cpp_grammar : const auto &named_variadics = [](tree_node& node, iterator_t begin, iterator_t end) { container_iterator_t it = node.value.begin(); it->set_token_id(T_GNU_NAMED_ELLIPSIS); + it->set_value(it->get_value() + "..."); }; #endif #endif diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index fcfb2239b..d9c24f4c5 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1719,6 +1719,15 @@ pp_iterator_functor::on_define (parse_node_type const &node) typedef typename std::vector::iterator parameter_iterator_t; +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + string_type named_variadic; + if (boost::wave::need_named_variadics(ctx.get_language()) && + token_id(macroparameters.back()) == T_GNU_NAMED_ELLIPSIS) { + named_variadic = macroparameters.back().get_value(); + named_variadic = named_variadic.substr(0, named_variadic.size()-3); + } +#endif + bool seen_ellipses = false; parameter_iterator_t end = macroparameters.end(); for (parameter_iterator_t pit = macroparameters.begin(); @@ -1743,6 +1752,14 @@ pp_iterator_functor::on_define (parse_node_type const &node) return; } } + + if (named_variadic == (*pit).get_value()) { + // can't use named_variadic as a argument name + BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, + duplicate_parameter_name, + macroname.get_value().c_str(), (*pit).get_position()); + return; + } #endif if (T_ELLIPSIS == token_id(*pit)) seen_ellipses = true; diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index 5cad29554..d1a023def 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -88,6 +88,7 @@ struct macro_definition { if (macroparameters.size() > 0 && T_GNU_NAMED_ELLIPSIS == token_id(macroparameters.back())) { va_args = macroparameters.back().get_value(); + va_args = va_args.substr(0, va_args.size()-3); } } #endif @@ -152,6 +153,13 @@ struct macro_definition { { has_ellipsis = true; } +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + if (macroparameters.size() > 0 && + T_GNU_NAMED_ELLIPSIS == token_id(macroparameters.back())) + { + has_ellipsis = true; + } +#endif #endif replaced_parameters = true; // do it only once } From c0267748ef7197a44caee77d5fb72a3803a033c1 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 18:49:51 +0800 Subject: [PATCH 09/14] fix space between x and ... --- include/boost/wave/grammars/cpp_grammar.hpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/boost/wave/grammars/cpp_grammar.hpp b/include/boost/wave/grammars/cpp_grammar.hpp index f53ffb73f..63776905b 100644 --- a/include/boost/wave/grammars/cpp_grammar.hpp +++ b/include/boost/wave/grammars/cpp_grammar.hpp @@ -373,12 +373,8 @@ struct cpp_grammar : TokenTypeMask|PPTokenFlag) // true/false #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - | access_node_d[ - token_node_d[ - lexeme_d[ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)] - | (ch_p(T_IDENTIFIER) >> ch_p(T_ELLIPSIS)) - ]][named_variadics] - + | access_node_d[token_node_d[(ch_p(T_IDENTIFIER) >> *ppsp >> ch_p(T_ELLIPSIS))]] + [named_variadics] #endif | ch_p(T_ELLIPSIS) #endif From eecac648e0a6dc10e8812cc94490803a714d5e55 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 19:05:07 +0800 Subject: [PATCH 10/14] rework on non-support case --- include/boost/wave/cpp_exceptions.hpp | 3 +-- include/boost/wave/util/cpp_iterator.hpp | 19 +++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/include/boost/wave/cpp_exceptions.hpp b/include/boost/wave/cpp_exceptions.hpp index 37dc5a893..e70e27353 100644 --- a/include/boost/wave/cpp_exceptions.hpp +++ b/include/boost/wave/cpp_exceptions.hpp @@ -267,8 +267,7 @@ class BOOST_SYMBOL_VISIBLE preprocess_exception : "ill formed #define directive", // bad_define_statement "__VA_ARGS__ can only appear in the " "expansion of a C99 variadic macro", // bad_define_statement_va_args - "named variadic like x... is disabled, " - "please enable_named_variadics() to enable", // bad_define_statement_named_va_args + "named variadic like x... is disabled", // bad_define_statement_named_va_args "__VA_OPT__ can only appear in the " "expansion of a C++20 variadic macro", // bad_define_statement_va_opt "__VA_OPT__ must be followed by a left " diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index d9c24f4c5..a3289fb20 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1742,17 +1742,16 @@ pp_iterator_functor::on_define (parse_node_type const &node) } #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (T_GNU_NAMED_ELLIPSIS == token_id(*pit)) { - if (boost::wave::need_named_variadics(ctx.get_language())) - seen_ellipses = true; - else { - // named variadics are not supported - BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, - bad_define_statement_named_va_args, macroname.get_value().c_str(), - (*pit).get_position()); - return; - } + if (boost::wave::need_named_variadics(ctx.get_language())) { + seen_ellipses = true; + } else { + // named variadics are not supported + BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, + bad_define_statement_named_va_args, macroname.get_value().c_str(), + (*pit).get_position()); + return; + } } - if (named_variadic == (*pit).get_value()) { // can't use named_variadic as a argument name BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, From 77e8546af608fd6d728530c75992110a075ea194 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 21:45:07 +0800 Subject: [PATCH 11/14] rename language support --- include/boost/wave/language_support.hpp | 4 ++-- include/boost/wave/util/cpp_iterator.hpp | 4 ++-- include/boost/wave/util/macro_definition.hpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/wave/language_support.hpp b/include/boost/wave/language_support.hpp index 5e5dc7922..459da1d7f 100644 --- a/include/boost/wave/language_support.hpp +++ b/include/boost/wave/language_support.hpp @@ -34,7 +34,7 @@ enum language_support { support_option_variadics = 0x04, support_c99 = support_option_variadics | support_option_long_long | 0x08, #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - support_option_named_variadics = 0x100000, + support_option_gnu_named_variadics = 0x100000, #endif #endif #if BOOST_WAVE_SUPPORT_CPP0X != 0 @@ -244,7 +244,7 @@ BOOST_WAVE_OPTION(include_guard_detection) // support_option_include_guard_det #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 BOOST_WAVE_OPTION(variadics) // support_option_variadics #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 -BOOST_WAVE_OPTION(named_variadics) // support_option_named_variadics +BOOST_WAVE_OPTION(gnu_named_variadics) // support_option_named_variadics #endif #endif #if BOOST_WAVE_SUPPORT_VA_OPT != 0 diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index a3289fb20..36548fe18 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1721,7 +1721,7 @@ pp_iterator_functor::on_define (parse_node_type const &node) #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 string_type named_variadic; - if (boost::wave::need_named_variadics(ctx.get_language()) && + if (boost::wave::need_gnu_named_variadics(ctx.get_language()) && token_id(macroparameters.back()) == T_GNU_NAMED_ELLIPSIS) { named_variadic = macroparameters.back().get_value(); named_variadic = named_variadic.substr(0, named_variadic.size()-3); @@ -1742,7 +1742,7 @@ pp_iterator_functor::on_define (parse_node_type const &node) } #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 if (T_GNU_NAMED_ELLIPSIS == token_id(*pit)) { - if (boost::wave::need_named_variadics(ctx.get_language())) { + if (boost::wave::need_gnu_named_variadics(ctx.get_language())) { seen_ellipses = true; } else { // named variadics are not supported diff --git a/include/boost/wave/util/macro_definition.hpp b/include/boost/wave/util/macro_definition.hpp index d1a023def..5e9379180 100644 --- a/include/boost/wave/util/macro_definition.hpp +++ b/include/boost/wave/util/macro_definition.hpp @@ -84,7 +84,7 @@ struct macro_definition { typename ContextT::string_type va_args = "__VA_ARGS__"; #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - if (need_named_variadics(ctx.get_language())) { + if (need_gnu_named_variadics(ctx.get_language())) { if (macroparameters.size() > 0 && T_GNU_NAMED_ELLIPSIS == token_id(macroparameters.back())) { va_args = macroparameters.back().get_value(); @@ -122,7 +122,7 @@ struct macro_definition { break; } #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 - else if (need_named_variadics(ctx.get_language()) && + else if (need_gnu_named_variadics(ctx.get_language()) && T_GNU_NAMED_ELLIPSIS == token_id(*cit) && va_args == (*it).get_value()) { From 2cb29f91509d0aa50dfe3f18da2cd19f25c7060c Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 21:58:06 +0800 Subject: [PATCH 12/14] fix support_option_mask --- include/boost/wave/language_support.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/wave/language_support.hpp b/include/boost/wave/language_support.hpp index 459da1d7f..1ad0d03c3 100644 --- a/include/boost/wave/language_support.hpp +++ b/include/boost/wave/language_support.hpp @@ -64,7 +64,7 @@ enum language_support { #endif #endif - support_option_mask = 0xFFC0, + support_option_mask = 0x10FFC0, support_option_emit_contnewlines = 0x0040, support_option_insert_whitespace = 0x0080, support_option_preserve_comments = 0x0100, From f55c0167eeee4829953137d439ffda0c3526f01b Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 22:16:01 +0800 Subject: [PATCH 13/14] allow this extension to work with CPP2A --- include/boost/wave/util/cpp_macromap.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index cca2b18d7..81711367b 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -1493,7 +1493,11 @@ macromap::expand_macro(ContainerT &expanded, // entirely, so reduce the mandatory argument count by one // if the last parameter is ellipsis: if ((parm_count_required > 0) && - (T_ELLIPSIS == token_id(macro_def.macroparameters.back()))) { + (T_ELLIPSIS == token_id(macro_def.macroparameters.back()) +#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 + || T_GNU_NAMED_ELLIPSIS == token_id(macro_def.macroparameters.back()) +#endif + )) { --parm_count_required; } } From 7b1bc0e7314d649307a10c9318c1dba93af1a8e5 Mon Sep 17 00:00:00 2001 From: john Date: Tue, 10 Sep 2024 22:28:57 +0800 Subject: [PATCH 14/14] fix missing size check --- include/boost/wave/util/cpp_iterator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index 36548fe18..d1a997237 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1722,6 +1722,7 @@ pp_iterator_functor::on_define (parse_node_type const &node) #if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0 string_type named_variadic; if (boost::wave::need_gnu_named_variadics(ctx.get_language()) && + macroparameters.size() > 0 && token_id(macroparameters.back()) == T_GNU_NAMED_ELLIPSIS) { named_variadic = macroparameters.back().get_value(); named_variadic = named_variadic.substr(0, named_variadic.size()-3);