Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/boost/wave/cpp_exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -265,6 +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", // 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 "
Expand Down Expand Up @@ -334,6 +337,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
Expand Down
21 changes: 18 additions & 3 deletions include/boost/wave/grammars/cpp_grammar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,23 +347,38 @@ 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<iterator_t, nil_t> node_t;
typedef typename node_t::iterator_t container_iterator_t;
const auto &named_variadics = [](tree_node<node_t>& 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
// parameter list
// normal C++ mode
macro_parameters
= 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
| access_node_d[token_node_d[(ch_p(T_IDENTIFIER) >> *ppsp >> ch_p(T_ELLIPSIS))]]
[named_variadics]
#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]
),
Expand Down
10 changes: 8 additions & 2 deletions include/boost/wave/language_support.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_gnu_named_variadics = 0x100000,
#endif
#endif
#if BOOST_WAVE_SUPPORT_CPP0X != 0
// support flags for C++11
Expand Down Expand Up @@ -61,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,
Expand All @@ -71,7 +74,7 @@ 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,
};

///////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -240,6 +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
#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0
BOOST_WAVE_OPTION(gnu_named_variadics) // support_option_named_variadics
#endif
#endif
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
BOOST_WAVE_OPTION(va_opt) // support_option_va_opt
Expand Down
3 changes: 3 additions & 0 deletions include/boost/wave/token_ids.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down
30 changes: 30 additions & 0 deletions include/boost/wave/util/cpp_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1719,6 +1719,16 @@ pp_iterator_functor<ContextT>::on_define (parse_node_type const &node)
typedef typename std::vector<result_type>::iterator
parameter_iterator_t;

#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);
}
#endif

bool seen_ellipses = false;
parameter_iterator_t end = macroparameters.end();
for (parameter_iterator_t pit = macroparameters.begin();
Expand All @@ -1731,6 +1741,26 @@ pp_iterator_functor<ContextT>::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_gnu_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,
duplicate_parameter_name,
macroname.get_value().c_str(), (*pit).get_position());
return;
}
#endif
if (T_ELLIPSIS == token_id(*pit))
seen_ellipses = true;

Expand Down
7 changes: 6 additions & 1 deletion include/boost/wave/util/cpp_macromap.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1486,13 +1486,18 @@ macromap<ContextT>::expand_macro(ContainerT &expanded,
macro_def.macroparameters.size(), seen_newline);

std::size_t parm_count_required = macro_def.macroparameters.size();

#if BOOST_WAVE_SUPPORT_CPP2A
if (boost::wave::need_cpp2a(ctx.get_language())) {
// Starting with C++20, variable arguments may be left out
// 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;
}
}
Expand Down
31 changes: 30 additions & 1 deletion include/boost/wave/util/macro_definition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_VARIADICS_PLACEMARKERS != 0
#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0
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();
va_args = va_args.substr(0, va_args.size()-3);
}
}
#endif
#endif

for (/**/; it != end; ++it) {
token_id id = *it;
Expand All @@ -103,12 +115,22 @@ 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));
break;
}
#if BOOST_WAVE_SUPPORT_GNU_NAMED_VARIADICS_PLACEMARKERS != 0
else if (need_gnu_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) &&
Expand All @@ -131,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
}
Expand Down
17 changes: 17 additions & 0 deletions include/boost/wave/wave_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions src/token_ids.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down