mirror of
https://github.com/boostorg/wave.git
synced 2026-01-19 04:42:16 +00:00
Implement C++20 features (#75)
* Introduce support for C++20 preprocessor features - add __VA_OPT__ feature to variadic macros - allow supplying 0 variadic arguments in more cases - add related unit tests
This commit is contained in:
@@ -1391,7 +1391,7 @@ Wed May 7 22:44:21 2003
|
||||
- Introduced the wave::language_support enum for convenient switching of the
|
||||
supported language features throughout the library.
|
||||
- Fixed a bug, which prevented the definition of the predefined macro
|
||||
__WAVE_HAS_VARRIADICS__, if --variadics were given on the command line.
|
||||
__WAVE_HAS_VARIADICS__, if --variadics were given on the command line.
|
||||
|
||||
Tue May 6 15:49:45 2003
|
||||
- Made predefined macros available at every macro scope without qualification.
|
||||
|
||||
@@ -381,8 +381,7 @@
|
||||
<p>This functions allows to specify the language mode, in which
|
||||
the <tt>Wave</tt> library should work. The possible
|
||||
language modes are defined by the enumerated type <tt>language_support</tt>:</p>
|
||||
<pre> <span class="keyword">enum</span> language_support {<br> <span class="comment">// support flags for C++98</span><br> support_normal = 0x01,<br> support_cpp = support_normal,<br><span class="comment"><br> // support flags for C99</span><br> support_option_long_long = 0x02,<br> support_option_variadics = 0x04,<br> support_c99 = support_option_variadics | support_option_long_long | 0x08,<br><span class="comment"><br> // the mask for the main language settings</span><br> support_option_mask = 0xFFB0,<br><br><span class="comment"> // additional fine tuning of the general behavior</span>
|
||||
support_option_emit_contline = 0x0040,<br> support_option_insert_whitespace = 0x0080,<br> support_option_preserve_comments = 0x0100,<br> support_option_no_character_validation = 0x0200,<br> support_option_convert_trigraphs = 0x0400,<br> support_option_single_line = 0x0800,<br> support_option_prefer_pp_numbers = 0x1000,<br> support_option_emit_line_directives = 0x2000,<br> support_option_include_guard_detection = 0x4000,<br> support_option_emit_pragma_directives = 0x8000<br> };</pre>
|
||||
<pre> <span class="keyword">enum</span> language_support {<br> <span class="comment">// support flags for C++98</span><br> support_normal = 0x01,<br> support_cpp = support_normal,<br><span class="comment"><br> // support flags for C99</span><br> support_option_long_long = 0x02,<br> support_option_variadics = 0x04,<br> support_c99 = support_option_variadics | support_option_long_long | 0x08,<br><span class="comment"><br> // support flags for C++11</span><br> support_option_no_newline_at_end_of_file = 0x20,<br> support_cpp0x = support_option_variadics | support_option_long_long |<br> support_option_no_newline_at_end_of_file | 0x10,<br> support_cpp11 = support_cpp0x,<br><br><span class="comment"> // support flags for C++20</span><br> support_option_va_opt = 0x10000,<br><br> support_cpp2a = support_option_variadics | support_option_long_long |<br> support_option_no_newline_at_end_of_file | support_option_va_opt | 0x20000,<br> support_cpp20 = support_cpp2a,<br><span class="comment"><br> // the mask for the main language settings</span><br> support_option_mask = 0xFFC0,<br><br><span class="comment"> // additional fine tuning of the general behavior</span><br> support_option_emit_contline = 0x0040,<br> support_option_insert_whitespace = 0x0080,<br> support_option_preserve_comments = 0x0100,<br> support_option_no_character_validation = 0x0200,<br> support_option_convert_trigraphs = 0x0400,<br> support_option_single_line = 0x0800,<br> support_option_prefer_pp_numbers = 0x1000,<br> support_option_emit_line_directives = 0x2000,<br> support_option_include_guard_detection = 0x4000,<br> support_option_emit_pragma_directives = 0x8000<br> };</pre>
|
||||
<p>When used with <tt>support_option_variadics</tt> the support for variadics, placemarkers and the <tt>operator _Pragma()</tt> is enabled in normal C++ mode. When used with the <tt>support_option_long_long</tt> the support for long long suffixes is enabled in C++ mode. </p>
|
||||
<p>The <tt>support_c99</tt> switches on the C99
|
||||
language support, which enables variadics, placemarkers, the <tt>operator _Pragma</tt> and long long suffixes by default. Additionally it disables the C++
|
||||
|
||||
@@ -88,6 +88,11 @@
|
||||
<td class="table_cells"><code>BOOST_WAVE_SUPPORT_CPP0X</code></td>
|
||||
<td class="table_cells"><p>If defined, then the preprocessor library supports
|
||||
C++0x keywords and C++0x specific features, such as variadics, placemarkers, extended character and string literals. This implies the definitions of the <code>BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS</code> constant.</p></td>
|
||||
</tr> <tr>
|
||||
<td class="table_cells"><code>BOOST_WAVE_SUPPORT_CPP2A</code></td>
|
||||
<td class="table_cells"><p>If defined, then the preprocessor library supports
|
||||
C++2A keywords, specifically __VA_OPT__. It implies BOOST_WAVE_SUPPORT_CPP0X.</p></td>
|
||||
</tr>
|
||||
</tr> <tr>
|
||||
<td class="table_cells"><code>BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH</code></td>
|
||||
<td class="table_cells"><p>If defined, it will determine the initial maximal
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
<td class="table_cells"><code>__WAVE_HAS_VARIADICS__</code></td>
|
||||
<td class="table_cells"><p>1 (a decimal constant), this is defined in C++
|
||||
mode only if variadics and placemarkers are enabled, and it is defined
|
||||
in the C99 and C++0x modes</p></td>
|
||||
in the C99, C++0x, and C++2A modes</p></td>
|
||||
<td class="table_cells"><p>no</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
||||
@@ -56,7 +56,9 @@
|
||||
--long_long: enable long long support if C++ mode
|
||||
--variadics: enable variadics and placemarkers in C++ mode
|
||||
--c99: enable C99 mode (implies variadics and placemarkers)
|
||||
--c++11 enable C++11 mode (implies --variadics and --long_long)
|
||||
--c++11: enable C++11 mode (implies --variadics and --long_long)
|
||||
--c++20: enable C++20 mode (adds __VA_OPT__ to variadics)
|
||||
(implies --variadics and --long_long)
|
||||
-l [ --listincludes ] arg: list included file to a file [arg] or to stdout [-]
|
||||
-m [ --macronames ] arg: list names of all defined macros to a file [arg] or
|
||||
to stdout [-]
|
||||
|
||||
@@ -115,6 +115,9 @@ public:
|
||||
ill_formed_operator,
|
||||
bad_define_statement,
|
||||
bad_define_statement_va_args,
|
||||
bad_define_statement_va_opt,
|
||||
bad_define_statement_va_opt_parens,
|
||||
bad_define_statement_va_opt_recurse,
|
||||
too_few_macroarguments,
|
||||
too_many_macroarguments,
|
||||
empty_macroarguments,
|
||||
@@ -204,6 +207,9 @@ public:
|
||||
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_va_opt:
|
||||
case preprocess_exception::bad_define_statement_va_opt_parens:
|
||||
case preprocess_exception::bad_define_statement_va_opt_recurse:
|
||||
case preprocess_exception::bad_line_statement:
|
||||
case preprocess_exception::bad_line_number:
|
||||
case preprocess_exception::bad_line_filename:
|
||||
@@ -256,6 +262,11 @@ public:
|
||||
"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
|
||||
"__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 "
|
||||
"paren in a C++20 variadic macro", // bad_define_statement_va_opt_parens
|
||||
"__VA_OPT__() may not contain __VA_OPT__", // bad_define_statement_va_opt_recurse
|
||||
"too few macro arguments", // too_few_macroarguments
|
||||
"too many macro arguments", // too_many_macroarguments
|
||||
"empty macro arguments are not supported in pure C++ mode, "
|
||||
@@ -319,6 +330,9 @@ public:
|
||||
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_va_opt
|
||||
util::severity_error, // bad_define_statement_va_opt_parens
|
||||
util::severity_error, // bad_define_statement_va_opt_recurse
|
||||
util::severity_warning, // too_few_macroarguments
|
||||
util::severity_warning, // too_many_macroarguments
|
||||
util::severity_warning, // empty_macroarguments
|
||||
|
||||
@@ -35,11 +35,20 @@ enum language_support {
|
||||
support_c99 = support_option_variadics | support_option_long_long | 0x08,
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_CPP0X != 0
|
||||
// support flags for C++11
|
||||
support_option_no_newline_at_end_of_file = 0x20,
|
||||
|
||||
support_cpp0x = support_option_variadics | support_option_long_long |
|
||||
support_option_no_newline_at_end_of_file | 0x10,
|
||||
support_cpp11 = support_cpp0x,
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
// support flags for C++20
|
||||
support_option_va_opt = 0x10000,
|
||||
|
||||
support_cpp2a = support_option_variadics | support_option_long_long |
|
||||
support_option_no_newline_at_end_of_file | support_option_va_opt | 0x20000,
|
||||
support_cpp20 = support_cpp2a,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
support_option_mask = 0xFFC0,
|
||||
@@ -93,6 +102,31 @@ need_cpp0x(language_support language)
|
||||
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// need_cpp2a
|
||||
//
|
||||
// Extract if the language to support is C++20
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
|
||||
inline bool
|
||||
need_cpp2a(language_support language)
|
||||
{
|
||||
return (language & ~support_option_mask) == support_cpp2a;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline bool
|
||||
need_cpp2a(language_support language)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -197,6 +231,9 @@ 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
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
BOOST_WAVE_OPTION(va_opt) // support_option_va_opt
|
||||
#endif
|
||||
#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
|
||||
BOOST_WAVE_OPTION(emit_pragma_directives) // support_option_emit_pragma_directives
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ enum token_category {
|
||||
IdentifierTokenType = 0x08040000,
|
||||
ParameterTokenType = 0x08840000,
|
||||
ExtParameterTokenType = 0x088C0000,
|
||||
OptParameterTokenType = 0x08940000,
|
||||
KeywordTokenType = 0x10040000,
|
||||
OperatorTokenType = 0x18040000,
|
||||
LiteralTokenType = 0x20040000,
|
||||
@@ -311,7 +312,8 @@ enum token_id {
|
||||
T_PLACEHOLDER = TOKEN_FROM_ID(T_LAST_TOKEN+2, WhiteSpaceTokenType),
|
||||
T_PLACEMARKER = TOKEN_FROM_ID(T_LAST_TOKEN+3, InternalTokenType),
|
||||
T_PARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+4, ParameterTokenType),
|
||||
T_EXTPARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+4, ExtParameterTokenType)
|
||||
T_EXTPARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+4, ExtParameterTokenType),
|
||||
T_OPTPARAMETERBASE = TOKEN_FROM_ID(T_LAST_TOKEN+4, OptParameterTokenType)
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1789,6 +1789,17 @@ position_type pos(act_token.get_position());
|
||||
macroname.get_value().c_str(), (*pit).get_position());
|
||||
return;
|
||||
}
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
// can't use __VA_OPT__ either
|
||||
if (boost::wave::need_va_opt(ctx.get_language()) &&
|
||||
("__VA_OPT__" == (*pit).get_value())) {
|
||||
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
|
||||
bad_define_statement_va_opt,
|
||||
macroname.get_value().c_str(), (*pit).get_position());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// if there wasn't an ellipsis, then there shouldn't be a __VA_ARGS__
|
||||
@@ -1797,6 +1808,9 @@ position_type pos(act_token.get_position());
|
||||
typedef typename token_sequence_type::iterator definition_iterator_t;
|
||||
|
||||
bool seen_va_args = false;
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
bool seen_va_opt = false;
|
||||
#endif
|
||||
definition_iterator_t pend = macrodefinition.end();
|
||||
for (definition_iterator_t dit = macrodefinition.begin();
|
||||
dit != pend; ++dit)
|
||||
@@ -1806,6 +1820,13 @@ position_type pos(act_token.get_position());
|
||||
{
|
||||
seen_va_args = true;
|
||||
}
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
if (T_IDENTIFIER == token_id(*dit) &&
|
||||
"__VA_OPT__" == (*dit).get_value())
|
||||
{
|
||||
seen_va_opt = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (seen_va_args) {
|
||||
// must not have seen __VA_ARGS__ placeholder
|
||||
@@ -1814,6 +1835,14 @@ position_type pos(act_token.get_position());
|
||||
macroname.get_value().c_str(), act_token.get_position());
|
||||
return;
|
||||
}
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
if (seen_va_opt) {
|
||||
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
|
||||
bad_define_statement_va_opt,
|
||||
macroname.get_value().c_str(), act_token.get_position());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -202,7 +202,8 @@ protected:
|
||||
// Expand the replacement list (replaces parameters with arguments)
|
||||
template <typename ContainerT>
|
||||
void expand_replacement_list(
|
||||
macro_definition_type const ¯odefinition,
|
||||
typename macro_definition_type::const_definition_iterator_t cbeg,
|
||||
typename macro_definition_type::const_definition_iterator_t cend,
|
||||
std::vector<ContainerT> &arguments,
|
||||
bool expand_operator_defined, ContainerT &expanded);
|
||||
|
||||
@@ -298,6 +299,15 @@ macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
|
||||
name.get_value().c_str());
|
||||
return false;
|
||||
}
|
||||
if (boost::wave::need_variadics(ctx.get_language()) &&
|
||||
"__VA_OPT__" == name.get_value())
|
||||
{
|
||||
// can't use __VA_OPT__ as a macro name
|
||||
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
|
||||
bad_define_statement_va_opt, name.get_value().c_str(), main_pos,
|
||||
name.get_value().c_str());
|
||||
return false;
|
||||
}
|
||||
if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
|
||||
// exclude special operator names
|
||||
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
|
||||
@@ -349,6 +359,51 @@ typename defined_macros_type::iterator it = current_scope->find(name.get_value()
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
// check that __VA_OPT__ is used as a function macro
|
||||
if (boost::wave::need_va_opt(ctx.get_language())) {
|
||||
// __VA_OPT__, if present, must be followed by an lparen
|
||||
typedef typename macro_definition_type::const_definition_iterator_t iter_t;
|
||||
iter_t mdit = definition.begin();
|
||||
iter_t mdend = definition.end();
|
||||
for (; mdit != mdend; ++mdit) {
|
||||
// is this va_opt?
|
||||
if ((IS_EXTCATEGORY((*mdit), OptParameterTokenType)) || // if params replaced
|
||||
("__VA_OPT__" == (*mdit).get_value())) { // if not
|
||||
iter_t va_opt_it = mdit;
|
||||
// next must be lparen
|
||||
if ((++mdit == mdend) || // no further tokens
|
||||
(T_LEFTPAREN != token_id(*mdit))) { // not lparen
|
||||
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
|
||||
bad_define_statement_va_opt_parens,
|
||||
name.get_value().c_str(), main_pos,
|
||||
name.get_value().c_str());
|
||||
return false;
|
||||
}
|
||||
// check that no __VA_OPT__ appears inside
|
||||
iter_t va_opt_end = va_opt_it;
|
||||
if (!impl::find_va_opt_args(va_opt_end, mdend)) {
|
||||
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
|
||||
improperly_terminated_macro, "missing ')' in __VA_OPT__",
|
||||
main_pos);
|
||||
return false;
|
||||
}
|
||||
// skip initial __VA_OPT__ and lparen
|
||||
++va_opt_it; ++va_opt_it;
|
||||
for (;va_opt_it != va_opt_end; ++va_opt_it) {
|
||||
if ((IS_EXTCATEGORY((*va_opt_it), OptParameterTokenType)) ||
|
||||
("__VA_OPT__" == (*va_opt_it).get_value())) {
|
||||
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
|
||||
bad_define_statement_va_opt_recurse,
|
||||
name.get_value().c_str(), (*va_opt_it).get_position(),
|
||||
name.get_value().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// insert a new macro node
|
||||
std::pair<typename defined_macros_type::iterator, bool> p =
|
||||
current_scope->insert(
|
||||
@@ -927,7 +982,8 @@ template <typename ContextT>
|
||||
template <typename ContainerT>
|
||||
inline void
|
||||
macromap<ContextT>::expand_replacement_list(
|
||||
macro_definition_type const ¯odef,
|
||||
typename macro_definition_type::const_definition_iterator_t cit,
|
||||
typename macro_definition_type::const_definition_iterator_t cend,
|
||||
std::vector<ContainerT> &arguments, bool expand_operator_defined,
|
||||
ContainerT &expanded)
|
||||
{
|
||||
@@ -941,9 +997,7 @@ bool seen_concat = false;
|
||||
bool adjacent_concat = false;
|
||||
bool adjacent_stringize = false;
|
||||
|
||||
macro_definition_iter_t cend = macrodef.macrodefinition.end();
|
||||
for (macro_definition_iter_t cit = macrodef.macrodefinition.begin();
|
||||
cit != cend; ++cit)
|
||||
for (;cit != cend; ++cit)
|
||||
{
|
||||
bool use_replaced_arg = true;
|
||||
token_id base_id = BASE_TOKEN(token_id(*cit));
|
||||
@@ -973,6 +1027,9 @@ bool adjacent_stringize = false;
|
||||
typename ContainerT::size_type i;
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
bool is_ellipsis = false;
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
bool is_va_opt = false;
|
||||
#endif
|
||||
|
||||
if (IS_EXTCATEGORY((*cit), ExtParameterTokenType)) {
|
||||
BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
|
||||
@@ -980,12 +1037,21 @@ bool adjacent_stringize = false;
|
||||
is_ellipsis = true;
|
||||
}
|
||||
else
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
|
||||
if (IS_EXTCATEGORY((*cit), OptParameterTokenType)) {
|
||||
BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
|
||||
i = token_id(*cit) - T_OPTPARAMETERBASE;
|
||||
is_va_opt = true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
i = token_id(*cit) - T_PARAMETERBASE;
|
||||
}
|
||||
|
||||
BOOST_ASSERT(i < arguments.size());
|
||||
BOOST_ASSERT(i <= arguments.size());
|
||||
if (use_replaced_arg) {
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
@@ -1004,13 +1070,56 @@ bool adjacent_stringize = false;
|
||||
impl::replace_ellipsis(expanded_args, i, expanded, pos);
|
||||
}
|
||||
else
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
if (is_va_opt) {
|
||||
position_type const &pos = (*cit).get_position();
|
||||
|
||||
BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
|
||||
|
||||
// ensure all variadic arguments to be expanded
|
||||
for (typename vector<ContainerT>::size_type arg = i;
|
||||
arg < expanded_args.size(); ++arg)
|
||||
{
|
||||
expand_argument(arg, arguments, expanded_args,
|
||||
expand_operator_defined, has_expanded_args);
|
||||
}
|
||||
|
||||
// locate the __VA_OPT__ arguments
|
||||
typename macro_definition_type::const_definition_iterator_t cstart = cit;
|
||||
if (!impl::find_va_opt_args(cit, cend)) {
|
||||
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
|
||||
improperly_terminated_macro, "missing '(' or ')' in __VA_OPT__",
|
||||
pos);
|
||||
}
|
||||
// cstart still points to __VA_OPT__; cit now points to the last rparen
|
||||
|
||||
if ((i == arguments.size()) || // no variadic argument
|
||||
impl::is_whitespace_only(arguments[i])) { // no visible tokens
|
||||
// no args; insert placemarker if one is not already present
|
||||
expanded.push_back(
|
||||
typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
|
||||
} else if (!impl::is_blank_only(arguments[i])) {
|
||||
++cstart; ++cstart;
|
||||
// [cstart, cit) is now the args to va_opt
|
||||
// recursively process them
|
||||
expand_replacement_list(cstart, cit, arguments,
|
||||
expand_operator_defined, expanded);
|
||||
}
|
||||
// continue from rparen
|
||||
}
|
||||
else
|
||||
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
BOOST_ASSERT(i < arguments.size());
|
||||
// ensure argument i to be expanded
|
||||
expand_argument(i, arguments, expanded_args,
|
||||
expand_operator_defined, has_expanded_args);
|
||||
|
||||
// replace argument
|
||||
BOOST_ASSERT(i < expanded_args.size());
|
||||
ContainerT const &arg = expanded_args[i];
|
||||
|
||||
std::copy(arg.begin(), arg.end(),
|
||||
@@ -1046,12 +1155,25 @@ bool adjacent_stringize = false;
|
||||
// simply copy the original argument (adjacent '##' or '#')
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
if (is_ellipsis) {
|
||||
position_type const &pos = (*cit).get_position();
|
||||
position_type const &pos = (*cit).get_position();
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
if (i < arguments.size())
|
||||
#endif
|
||||
{
|
||||
|
||||
impl::trim_sequence_left(arguments[i]);
|
||||
impl::trim_sequence_right(arguments.back());
|
||||
BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
|
||||
impl::replace_ellipsis(arguments, i, expanded, pos);
|
||||
impl::trim_sequence_left(arguments[i]);
|
||||
impl::trim_sequence_right(arguments.back());
|
||||
BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
|
||||
impl::replace_ellipsis(arguments, i, expanded, pos);
|
||||
}
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
else if (boost::wave::need_cpp2a(ctx.get_language())) {
|
||||
BOOST_ASSERT(i == arguments.size());
|
||||
// no argument supplied; insert placemarker
|
||||
expanded.push_back(
|
||||
typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -1187,7 +1309,7 @@ macromap<ContextT>::expand_macro(ContainerT &expanded,
|
||||
// ensure the parameters to be replaced with special parameter tokens
|
||||
macro_definition_type ¯o_def = *(*it).second.get();
|
||||
|
||||
macro_def.replace_parameters();
|
||||
macro_def.replace_parameters(ctx);
|
||||
|
||||
// test if this macro is currently available for replacement
|
||||
if (!macro_def.is_available_for_replacement) {
|
||||
@@ -1233,9 +1355,22 @@ ContainerT replacement_list;
|
||||
macro_def.macroparameters.size(), seen_newline);
|
||||
#endif
|
||||
|
||||
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()))) {
|
||||
--parm_count_required;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// verify the parameter count
|
||||
if (count_args < macro_def.macroparameters.size() ||
|
||||
arguments.size() < macro_def.macroparameters.size())
|
||||
if (count_args < parm_count_required ||
|
||||
arguments.size() < parm_count_required)
|
||||
{
|
||||
if (count_args != arguments.size()) {
|
||||
// must been at least one empty argument in C++ mode
|
||||
@@ -1291,7 +1426,9 @@ ContainerT replacement_list;
|
||||
#endif
|
||||
|
||||
// expand the replacement list of this macro
|
||||
expand_replacement_list(macro_def, arguments, expand_operator_defined,
|
||||
expand_replacement_list(macro_def.macrodefinition.begin(),
|
||||
macro_def.macrodefinition.end(),
|
||||
arguments, expand_operator_defined,
|
||||
replacement_list);
|
||||
}
|
||||
else {
|
||||
@@ -1857,6 +1994,17 @@ position_type pos("<built-in>");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
if (boost::wave::need_cpp2a(ctx.get_language())) {
|
||||
// define C++20 specifics
|
||||
for (int i = 0; 0 != predef.static_data_cpp2a(i).name; ++i) {
|
||||
predefined_macros::static_macros const& m = predef.static_data_cpp2a(i);
|
||||
predefine_macro(current_scope, m.name,
|
||||
token_type(m.token_id, m.value, pos));
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// define C++ specifics
|
||||
|
||||
@@ -240,6 +240,23 @@ namespace util {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
// C++20 mode
|
||||
static_macros const& static_data_cpp2a(std::size_t i) const
|
||||
{
|
||||
static static_macros data[] = {
|
||||
{ "__STDC__", T_INTLIT, "1" },
|
||||
{ "__cplusplus", T_INTLIT, "202002L" },
|
||||
{ "__STDC_VERSION__", T_INTLIT, "199901L" },
|
||||
{ "__STDC_HOSTED__", T_INTLIT, "0" },
|
||||
{ "__WAVE_HAS_VARIADICS__", T_INTLIT, "1" },
|
||||
{ 0, T_EOF, 0 }
|
||||
};
|
||||
BOOST_ASSERT(i < sizeof(data)/sizeof(data[0]));
|
||||
return data[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
// C99 mode
|
||||
static_macros const& static_data_c99(std::size_t i) const
|
||||
|
||||
@@ -343,6 +343,27 @@ is_whitespace_only (ContainerT const &argument)
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Tests whether the given token sequence consists only of whitespace
|
||||
// and placemarkers
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename ContainerT>
|
||||
inline bool
|
||||
is_blank_only (ContainerT const &argument)
|
||||
{
|
||||
typename ContainerT::const_iterator end = argument.end();
|
||||
for (typename ContainerT::const_iterator it = argument.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
if (!IS_CATEGORY(*it, WhiteSpaceTokenType) &&
|
||||
(T_PLACEMARKER != token_id(*it)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Remove all placeholder tokens from the given token sequence
|
||||
|
||||
@@ -73,7 +73,8 @@ struct macro_definition {
|
||||
// with special parameter tokens to simplify later macro replacement.
|
||||
// Additionally mark all occurrences of the macro name itself throughout
|
||||
// the macro definition
|
||||
void replace_parameters()
|
||||
template<typename ContextT>
|
||||
void replace_parameters(ContextT const & ctx)
|
||||
{
|
||||
using namespace boost::wave;
|
||||
|
||||
@@ -100,13 +101,24 @@ struct macro_definition {
|
||||
break;
|
||||
}
|
||||
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
|
||||
else if (T_ELLIPSIS == token_id(*cit) &&
|
||||
else if (need_variadics(ctx.get_language()) &&
|
||||
T_ELLIPSIS == token_id(*cit) &&
|
||||
"__VA_ARGS__" == (*it).get_value())
|
||||
{
|
||||
// __VA_ARGS__ requires special handling
|
||||
(*it).set_token_id(token_id(T_EXTPARAMETERBASE+i));
|
||||
break;
|
||||
}
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
else if (need_va_opt(ctx.get_language()) &&
|
||||
T_ELLIPSIS == token_id(*cit) &&
|
||||
"__VA_OPT__" == (*it).get_value())
|
||||
{
|
||||
// __VA_OPT__ also requires related special handling
|
||||
(*it).set_token_id(token_id(T_OPTPARAMETERBASE+i));
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +252,48 @@ namespace impl {
|
||||
expanded.push_back(comma);
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Finds the token range inside __VA_OPT__.
|
||||
// Updates mdit to the position of the final rparen.
|
||||
// If the parenthesis do not match up, or there are none, returns false
|
||||
// and leaves mdit unchanged.
|
||||
//
|
||||
template <typename MDefIterT>
|
||||
bool find_va_opt_args (
|
||||
MDefIterT & mdit, // VA_OPT
|
||||
MDefIterT mdend)
|
||||
{
|
||||
if ((std::distance(mdit, mdend) < 3) ||
|
||||
(T_LEFTPAREN != next_token<MDefIterT>::peek(mdit, mdend))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MDefIterT mdstart_it = mdit;
|
||||
++mdit; // skip to lparen
|
||||
std::size_t scope = 0;
|
||||
// search for final rparen, leaving iterator there
|
||||
for (; (mdit != mdend) && !((scope == 1) && (T_RIGHTPAREN == token_id(*mdit)));
|
||||
++mdit) {
|
||||
// count balanced parens
|
||||
if (T_RIGHTPAREN == token_id(*mdit)) {
|
||||
scope--;
|
||||
} else if (T_LEFTPAREN == token_id(*mdit)) {
|
||||
scope++;
|
||||
}
|
||||
}
|
||||
if ((mdit == mdend) && ((scope != 1) || (T_RIGHTPAREN != token_id(*mdit)))) {
|
||||
// arrived at end without matching rparen
|
||||
mdit = mdstart_it;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Skip all whitespace characters and queue the skipped characters into the
|
||||
|
||||
@@ -40,6 +40,14 @@
|
||||
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide whether to support the C++20 __VA_OPT__ variadics feature
|
||||
//
|
||||
//
|
||||
#if !defined(BOOST_WAVE_SUPPORT_VA_OPT) && BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS
|
||||
#define BOOST_WAVE_SUPPORT_VA_OPT 1
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement a #warning directive as an extension to the
|
||||
// C++ Standard (same as #error, but emits a warning, not an error)
|
||||
@@ -94,6 +102,25 @@
|
||||
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide whether to support C++20
|
||||
//
|
||||
#if !defined(BOOST_WAVE_SUPPORT_CPP2A)
|
||||
# define BOOST_WAVE_SUPPORT_CPP2A 1
|
||||
# undef BOOST_WAVE_SUPPORT_CPP0X
|
||||
# define BOOST_WAVE_SUPPORT_CPP0X 1
|
||||
# undef BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS
|
||||
# define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
|
||||
# if !defined(BOOST_WAVE_SUPPORT_VA_OPT)
|
||||
# undef BOOST_WAVE_SUPPORT_VA_OPT
|
||||
# define BOOST_WAVE_SUPPORT_VA_OPT 1
|
||||
# endif
|
||||
#elif BOOST_WAVE_SUPPORT_CPP2A == 0
|
||||
# undef BOOST_WAVE_SUPPORT_VA_OPT
|
||||
# define BOOST_WAVE_SUPPORT_VA_OPT 0
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Undefine the following, to enable some MS specific language extensions:
|
||||
// __int8, __int16, __int32, __int64, __based, __declspec, __cdecl,
|
||||
|
||||
@@ -69,9 +69,10 @@ test-suite wave
|
||||
:
|
||||
# arguments
|
||||
$(TESTWAVE_ARGUMENTS)
|
||||
--config-file $(TESTWAVE_DIR)/$(TESTWAVE_FILES)
|
||||
--config-file
|
||||
:
|
||||
# input files
|
||||
$(TESTWAVE_DIR)/$(TESTWAVE_FILES)
|
||||
:
|
||||
# requirements
|
||||
<threading>multi
|
||||
|
||||
72
test/testwave/testfiles/t_8_001.cpp
Normal file
72
test/testwave/testfiles/t_8_001.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// __VA_OPT__ examples from the proposal doc P00306
|
||||
// Those examples have a few weird typos. I've tried to match the
|
||||
// behavior of gcc in the expected results - JET
|
||||
|
||||
#define LOG(msg, ...) printf(msg __VA_OPT__(,) __VA_ARGS__)
|
||||
#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })
|
||||
#define LOG2(...) \
|
||||
printf("at line=%d" __VA_OPT__(": "), __LINE__); \
|
||||
__VA_OPT__(printf(__VA_ARGS__);) \
|
||||
printf("\n")
|
||||
|
||||
//R #line 28 "t_8_001.cpp"
|
||||
//R printf("hello world\n" );
|
||||
//R printf("hello world\n" );
|
||||
//R printf("hello %d\n" , n);
|
||||
LOG("hello world\n");
|
||||
LOG("hello world\n", );
|
||||
LOG("hello %d\n", n);
|
||||
|
||||
//R #line 35 "t_8_001.cpp"
|
||||
//R S foo;
|
||||
//R S bar = { 1, 2, 3 };
|
||||
SDEF(foo);
|
||||
SDEF(bar, 1, 2, 3);
|
||||
|
||||
//R #line 43 "t_8_001.cpp"
|
||||
//R printf("at line=%d" , 43); printf("\n");
|
||||
// P00306 example suggests the adjacent string literals are concatenated in
|
||||
// this test case but that's the *compiler's* job:
|
||||
//R printf("at line=%d" ": ", 44); printf("All well in zone %d", n); printf("\n");
|
||||
LOG2();
|
||||
LOG2("All well in zone %d", n);
|
||||
|
||||
//H 10: t_8_001.cpp(17): #define
|
||||
//H 08: t_8_001.cpp(17): LOG(msg, ...)=printf(msg __VA_OPT__(,) __VA_ARGS__)
|
||||
//H 10: t_8_001.cpp(18): #define
|
||||
//H 08: t_8_001.cpp(18): SDEF(sname, ...)=S sname __VA_OPT__(= { __VA_ARGS__ })
|
||||
//H 10: t_8_001.cpp(19): #define
|
||||
//H 08: t_8_001.cpp(19): LOG2(...)=printf("at line=%d" __VA_OPT__(": "), __LINE__); __VA_OPT__(printf(__VA_ARGS__);) printf("\n")
|
||||
//H 00: t_8_001.cpp(28): LOG("hello world\n"), [t_8_001.cpp(17): LOG(msg, ...)=printf(msg __VA_OPT__(,) __VA_ARGS__)]
|
||||
//H 02: printf("hello world\n" § )
|
||||
//H 03: printf("hello world\n" )
|
||||
//H 00: t_8_001.cpp(29): LOG("hello world\n", §), [t_8_001.cpp(17): LOG(msg, ...)=printf(msg __VA_OPT__(,) __VA_ARGS__)]
|
||||
//H 02: printf("hello world\n" )
|
||||
//H 03: printf("hello world\n" )
|
||||
//H 00: t_8_001.cpp(30): LOG("hello %d\n", n), [t_8_001.cpp(17): LOG(msg, ...)=printf(msg __VA_OPT__(,) __VA_ARGS__)]
|
||||
//H 02: printf("hello %d\n" , n)
|
||||
//H 03: printf("hello %d\n" , n)
|
||||
//H 00: t_8_001.cpp(35): SDEF(foo), [t_8_001.cpp(18): SDEF(sname, ...)=S sname __VA_OPT__(= { __VA_ARGS__ })]
|
||||
//H 02: S foo §
|
||||
//H 03: S foo
|
||||
//H 00: t_8_001.cpp(36): SDEF(bar, 1, 2, 3), [t_8_001.cpp(18): SDEF(sname, ...)=S sname __VA_OPT__(= { __VA_ARGS__ })]
|
||||
//H 02: S bar = { 1, 2, 3 }
|
||||
//H 03: S bar = { 1, 2, 3 }
|
||||
//H 00: t_8_001.cpp(43): LOG2(§), [t_8_001.cpp(19): LOG2(...)=printf("at line=%d" __VA_OPT__(": "), __LINE__); __VA_OPT__(printf(__VA_ARGS__);) printf("\n")]
|
||||
//H 02: printf("at line=%d" , __LINE__); printf("\n")
|
||||
//H 03: printf("at line=%d" , 43); printf("\n")
|
||||
//H 00: t_8_001.cpp(44): LOG2("All well in zone %d", n), [t_8_001.cpp(19): LOG2(...)=printf("at line=%d" __VA_OPT__(": "), __LINE__); __VA_OPT__(printf(__VA_ARGS__);) printf("\n")]
|
||||
//H 02: printf("at line=%d" ": ", __LINE__); printf("All well in zone %d", n); printf("\n")
|
||||
//H 03: printf("at line=%d" ": ", 44); printf("All well in zone %d", n); printf("\n")
|
||||
24
test/testwave/testfiles/t_8_002.cpp
Normal file
24
test/testwave/testfiles/t_8_002.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// tests for changes to variadics handling
|
||||
// specifically, that arg list after named args can be empty
|
||||
|
||||
#define ok_to_be_empty(BASE, ...) __VA_ARGS__##BASE##__VA_ARGS__
|
||||
|
||||
//R #line 20 "t_8_002.cpp"
|
||||
//R notemptyfillernotempty
|
||||
ok_to_be_empty(filler, notempty)
|
||||
|
||||
//R #line 24 "t_8_002.cpp"
|
||||
//R filler
|
||||
ok_to_be_empty(filler)
|
||||
22
test/testwave/testfiles/t_8_003.cpp
Normal file
22
test/testwave/testfiles/t_8_003.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++11
|
||||
//O -Werror
|
||||
|
||||
// test that arg list after named args CANNOT be empty (in c++11 mode)
|
||||
|
||||
#define ok_to_be_empty(BASE, ...) __VA_ARGS__##BASE##__VA_ARGS__
|
||||
|
||||
//R #line 19 "t_8_003.cpp"
|
||||
//R notemptyfillernotempty
|
||||
ok_to_be_empty(filler, notempty)
|
||||
|
||||
//E t_8_003.cpp(22): warning: too few macro arguments: ok_to_be_empty
|
||||
ok_to_be_empty(filler)
|
||||
24
test/testwave/testfiles/t_8_004.cpp
Normal file
24
test/testwave/testfiles/t_8_004.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test using __VA_ARGS__ inside __VA_OPT__
|
||||
// JET: Wave seems to inject a space after some lparens
|
||||
|
||||
#define sizedvec(TYPE, NAME, SIZE, ...) std::vector<TYPE> NAME(SIZE __VA_OPT__(, __VA_ARGS__))
|
||||
|
||||
//R #line 20 "t_8_004.cpp"
|
||||
//R std::vector<int> foo( 12 );
|
||||
sizedvec(int, foo, 12);
|
||||
|
||||
//R #line 24 "t_8_004.cpp"
|
||||
//R std::vector<double> bar( 3 , 42.0);
|
||||
sizedvec(double, bar, 3, 42.0);
|
||||
16
test/testwave/testfiles/t_8_005.cpp
Normal file
16
test/testwave/testfiles/t_8_005.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ cannot be used as a object-like macro
|
||||
|
||||
//E t_8_005.cpp(16): error: __VA_OPT__ can only appear in the expansion of a C++20 variadic macro: __VA_OPT__
|
||||
#define __VA_OPT__ something somethingelse
|
||||
16
test/testwave/testfiles/t_8_006.cpp
Normal file
16
test/testwave/testfiles/t_8_006.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ cannot be used as a function-like macro
|
||||
|
||||
//E t_8_006.cpp(16): error: __VA_OPT__ can only appear in the expansion of a C++20 variadic macro: __VA_OPT__
|
||||
#define __VA_OPT__(FOO, BAR) FOO BAR
|
||||
16
test/testwave/testfiles/t_8_007.cpp
Normal file
16
test/testwave/testfiles/t_8_007.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ cannot be used in a macro without variable args
|
||||
|
||||
//E t_8_007.cpp(16): error: __VA_OPT__ can only appear in the expansion of a C++20 variadic macro: FOO
|
||||
#define FOO(BAR) BAR __VA_OPT__(,) BAR
|
||||
62
test/testwave/testfiles/t_8_008.cpp
Normal file
62
test/testwave/testfiles/t_8_008.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
// Tests predefined macros
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
//R #line 16 "t_8_008.cpp"
|
||||
__STDC__ //R 1
|
||||
__STDC_VERSION__ //R 199901L
|
||||
__cplusplus //R 202002L
|
||||
__STDC_HOSTED__ //R 0
|
||||
__LINE__ //R 20
|
||||
__FILE__ //R "$P"
|
||||
__BASE_FILE__ //R "$F"
|
||||
__WAVE_HAS_VARIADICS__ //R 1
|
||||
__INCLUDE_LEVEL__ //R 0
|
||||
//R #line 53 "test.cpp"
|
||||
#line 53 "test.cpp"
|
||||
__LINE__ //R 53
|
||||
__FILE__ //R "test.cpp"
|
||||
__BASE_FILE__ //R "$F"
|
||||
|
||||
|
||||
//R #line 59 "test.cpp"
|
||||
__LINE__ //R 59
|
||||
__FILE__ //R "test.cpp"
|
||||
__BASE_FILE__ //R "$F"
|
||||
|
||||
//H 01: <built-in>(1): __STDC__
|
||||
//H 02: 1
|
||||
//H 03: 1
|
||||
//H 01: <built-in>(1): __STDC_VERSION__
|
||||
//H 02: 199901L
|
||||
//H 03: 199901L
|
||||
//H 01: <built-in>(1): __cplusplus
|
||||
//H 02: 202002L
|
||||
//H 03: 202002L
|
||||
//H 01: <built-in>(1): __STDC_HOSTED__
|
||||
//H 02: 0
|
||||
//H 03: 0
|
||||
//H 01: <built-in>(1): __BASE_FILE__
|
||||
//H 02: "$F"
|
||||
//H 03: "$F"
|
||||
//H 01: <built-in>(1): __WAVE_HAS_VARIADICS__
|
||||
//H 02: 1
|
||||
//H 03: 1
|
||||
//H 10: t_8_008.cpp(26): #line
|
||||
//H 17: 53 "test.cpp" (53, "test.cpp")
|
||||
//H 01: <built-in>(1): __BASE_FILE__
|
||||
//H 02: "$F"
|
||||
//H 03: "$F"
|
||||
//H 01: <built-in>(1): __BASE_FILE__
|
||||
//H 02: "$F"
|
||||
//H 03: "$F"
|
||||
17
test/testwave/testfiles/t_8_009.cpp
Normal file
17
test/testwave/testfiles/t_8_009.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ cannot be used in a macro definition without parens
|
||||
|
||||
// gcc detects this at definition time
|
||||
//E t_8_009.cpp(17): error: __VA_OPT__ must be followed by a left paren in a C++20 variadic macro: FOO
|
||||
#define FOO(...) BAR __VA_OPT__ BAR
|
||||
18
test/testwave/testfiles/t_8_010.cpp
Normal file
18
test/testwave/testfiles/t_8_010.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++20
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ cannot be used inside itself
|
||||
|
||||
// gcc detects this at definition time
|
||||
//E t_8_010.cpp(17): error: __VA_OPT__() may not contain __VA_OPT__: FOO
|
||||
#define FOO(...) BAR __VA_OPT__(__VA_OPT__(,) BAZ) BAR
|
||||
|
||||
19
test/testwave/testfiles/t_8_011.cpp
Normal file
19
test/testwave/testfiles/t_8_011.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/*=============================================================================
|
||||
Boost.Wave: A Standard compliant C++ preprocessor library
|
||||
http://www.boost.org/
|
||||
|
||||
Copyright (c) 2020 Jeff Trull. Distributed under the Boost
|
||||
Software License, Version 1.0. (See accompanying file
|
||||
LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
=============================================================================*/
|
||||
|
||||
//O --c++11
|
||||
//O -Werror
|
||||
|
||||
// test that __VA_OPT__ is ignored when not in c++20 mode
|
||||
|
||||
#define FOO(BAR, ...) BAR __VA_OPT__(,) __VA_ARGS__
|
||||
|
||||
//R #line 19 "t_8_011.cpp"
|
||||
//R something __VA_OPT__(,) other
|
||||
FOO(something, other)
|
||||
@@ -218,6 +218,21 @@ t_7_004.cpp
|
||||
t_7_005.cpp
|
||||
t_7_006.cpp
|
||||
|
||||
#
|
||||
# t_8: C++2a testing
|
||||
#
|
||||
t_8_001.cpp
|
||||
t_8_002.cpp
|
||||
t_8_003.cpp
|
||||
t_8_004.cpp
|
||||
t_8_005.cpp
|
||||
t_8_006.cpp
|
||||
t_8_007.cpp
|
||||
t_8_008.cpp
|
||||
t_8_009.cpp
|
||||
t_8_010.cpp
|
||||
t_8_011.cpp
|
||||
|
||||
#
|
||||
# t_9: General preprocessing problems
|
||||
#
|
||||
|
||||
@@ -418,6 +418,9 @@ testwave_app::testwave_app(po::variables_map const& vm)
|
||||
("skipped_token_hooks", "record skipped_token hook calls")
|
||||
#if BOOST_WAVE_SUPPORT_CPP0X != 0
|
||||
("c++11", "enable C++11 mode (implies --variadics and --long_long)")
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
("c++20", "enable C++20 mode (implies --variadics and --long_long, adds __VA_OPT__)")
|
||||
#endif
|
||||
("warning,W", po::value<std::vector<std::string> >()->composing(),
|
||||
"Warning settings.")
|
||||
@@ -971,12 +974,9 @@ testwave_app::initialise_options(Context& ctx, po::variables_map const& vm,
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_CPP0X
|
||||
if (vm.count("c++11")) {
|
||||
if (9 == debuglevel) {
|
||||
std::cerr << "initialise_options: option: c++11" << std::endl;
|
||||
}
|
||||
ctx.set_language(
|
||||
boost::wave::language_support(
|
||||
boost::wave::support_cpp0x
|
||||
boost::wave::support_cpp0x
|
||||
| boost::wave::support_option_convert_trigraphs
|
||||
| boost::wave::support_option_long_long
|
||||
| boost::wave::support_option_emit_line_directives
|
||||
@@ -988,6 +988,34 @@ testwave_app::initialise_options(Context& ctx, po::variables_map const& vm,
|
||||
#endif
|
||||
| boost::wave::support_option_insert_whitespace
|
||||
));
|
||||
} else {
|
||||
if (9 == debuglevel) {
|
||||
std::cerr << "initialise_options: option: c++11" << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A
|
||||
if (vm.count("c++20")) {
|
||||
ctx.set_language(
|
||||
boost::wave::language_support(
|
||||
boost::wave::support_cpp2a
|
||||
| boost::wave::support_option_va_opt
|
||||
| boost::wave::support_option_convert_trigraphs
|
||||
| boost::wave::support_option_long_long
|
||||
| boost::wave::support_option_emit_line_directives
|
||||
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
||||
| boost::wave::support_option_include_guard_detection
|
||||
#endif
|
||||
#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
|
||||
| boost::wave::support_option_emit_pragma_directives
|
||||
#endif
|
||||
| boost::wave::support_option_insert_whitespace
|
||||
));
|
||||
|
||||
if (9 == debuglevel) {
|
||||
std::cerr << "initialise_options: option: c++20" << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
23
tool/cpp.cpp
23
tool/cpp.cpp
@@ -897,6 +897,26 @@ const bool treat_warnings_as_error = vm.count("warning") &&
|
||||
}
|
||||
#endif // BOOST_WAVE_SUPPORT_CPP0X != 0
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
if (vm.count("c++20")) {
|
||||
ctx.set_language(
|
||||
boost::wave::language_support(
|
||||
boost::wave::support_cpp2a
|
||||
| boost::wave::support_option_va_opt
|
||||
| boost::wave::support_option_convert_trigraphs
|
||||
| boost::wave::support_option_long_long
|
||||
| boost::wave::support_option_emit_line_directives
|
||||
#if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
|
||||
| boost::wave::support_option_include_guard_detection
|
||||
#endif
|
||||
#if BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES != 0
|
||||
| boost::wave::support_option_emit_pragma_directives
|
||||
#endif
|
||||
| boost::wave::support_option_insert_whitespace
|
||||
));
|
||||
}
|
||||
#endif // BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
|
||||
// enable long long support, if appropriate
|
||||
if (vm.count("long_long")) {
|
||||
ctx.set_language(
|
||||
@@ -1329,6 +1349,9 @@ main (int argc, char *argv[])
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_CPP0X != 0
|
||||
("c++11", "enable C++11 mode (implies --variadics and --long_long)")
|
||||
#endif
|
||||
#if BOOST_WAVE_SUPPORT_CPP2A != 0
|
||||
("c++20", "enable C++20 mode (implies --variadics and --long_long, adds __VA_OPT__)")
|
||||
#endif
|
||||
("listincludes,l", po::value<std::string>(),
|
||||
"list names of included files to a file [arg] or to stdout [-]")
|
||||
|
||||
@@ -1207,9 +1207,7 @@ protected:
|
||||
using namespace boost::wave;
|
||||
|
||||
typedef typename ContextT::token_type token_type;
|
||||
typedef typename token_type::string_type string_type;
|
||||
typedef typename ContainerT::const_iterator const_iterator;
|
||||
typedef typename ContainerT::iterator iterator;
|
||||
|
||||
token_type* current = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user