2
0
mirror of https://github.com/boostorg/wave.git synced 2026-01-19 04:42:16 +00:00

Implement __has_include() (#102)

Resolve #96 by introducing C++17 feature (and frequent vendor extension) __has_include(), along with appropriate unit tests and documentation updates
This commit is contained in:
Jeff Trull
2020-06-27 07:22:52 -07:00
committed by GitHub
parent 81397434f1
commit ee0a7c14c5
37 changed files with 1308 additions and 82 deletions

View File

@@ -22,7 +22,8 @@ Boost V1.74:
- Fixed TRAC #10733: Hooks not called for expanding specific predefined macros
- Fixed #58: C++11 long long literals must use consistent case
- Repaired two samples and added a new one for macro naming enforcement
- Implemented C++20 changes for variadic macros, including __VA_OPT__
- Implemented C++20 changes for variadic macros, including __VA_OPT__()
- Added C++17 feature __has_include()
Boost V1.73:
- Fixed TRAC #7822: waveidl sample does not use the IDL lexer

View File

@@ -22,6 +22,7 @@ SOURCES =
instantiate_cpp_grammar
instantiate_cpp_literalgrs
instantiate_defined_grammar
instantiate_has_include_grammar
instantiate_predef_macros
instantiate_re2c_lexer
instantiate_re2c_lexer_str

View File

@@ -381,7 +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> // 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>
<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++17</span><br> support_option_has_include = 0x10000,<br> support_cpp1z = support_option_variadics | support_option_long_long |<br> support_option_no_newline_at_end_of_file | support_option_has_include | 0x20000,<br> support_cpp17 = support_cpp1z<br><br><span class="comment"> // support flags for C++20</span><br> support_option_va_opt = 0x40000,<br> support_cpp2a = support_option_variadics | support_option_long_long |<br> support_option_no_newline_at_end_of_file | support_option_has_include |<br> support_option_va_opt | 0x80000,<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&nbsp;_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&nbsp;_Pragma</tt> and long long suffixes by default. Additionally it disables the C++

View File

@@ -88,10 +88,15 @@
<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_CPP1Z</code></td>
<td class="table_cells"><p>If defined, then the preprocessor library supports
C++17 keywords - currently just <code>__has_include</code>. It implies <code>BOOST_WAVE_SUPPORT_CPP0X</code>.</p></td>
</tr>
</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>
C++20 keywords, specifically <code>__VA_OPT__</code>. It implies <code>BOOST_WAVE_SUPPORT_CPP1Z</code>.</p></td>
</tr>
</tr> <tr>
<td class="table_cells"><code>BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH</code></td>

View File

@@ -318,6 +318,7 @@ public:
protected:
friend class boost::wave::pp_iterator<context>;
friend class boost::wave::impl::pp_iterator_functor<context>;
friend class boost::wave::util::macromap<context>;
#endif
// make sure the context has been initialized
@@ -371,25 +372,28 @@ protected:
// and '#' pp operators and re-scans the resulting sequence
// (essentially pre-processes the token sequence).
//
// The expand_undefined parameter is true during macro expansion inside
// The expand_defined parameter is true during macro expansion inside
// a C++ expression given for a #if or #elif statement.
//
///////////////////////////////////////////////////////////////////////////////
template <typename IteratorT2>
token_type expand_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
token_sequence_type &pending, token_sequence_type &expanded,
bool& seen_newline, bool expand_undefined = false)
bool& seen_newline, bool expand_defined = false,
bool expand_has_include = false)
{
return macros.expand_tokensequence(first_, last_, pending, expanded,
seen_newline, expand_undefined);
seen_newline, expand_defined, expand_has_include);
}
template <typename IteratorT2>
void expand_whole_tokensequence(IteratorT2 &first_, IteratorT2 const &last_,
token_sequence_type &expanded, bool expand_undefined = true)
token_sequence_type &expanded, bool expand_defined = true,
bool expand_has_include = true)
{
macros.expand_whole_tokensequence(expanded, first_, last_,
expand_undefined);
macros.expand_whole_tokensequence(
expanded, first_, last_,
expand_defined, expand_has_include);
// remove any contained placeholder
boost::wave::util::impl::remove_placeholders(expanded);

View File

@@ -106,6 +106,7 @@ public:
macro_insertion_error,
bad_include_file,
bad_include_statement,
bad_has_include_expression,
ill_formed_directive,
error_directive,
warning_directive,
@@ -198,6 +199,7 @@ public:
case preprocess_exception::invalid_macroname:
case preprocess_exception::bad_include_file:
case preprocess_exception::bad_include_statement:
case preprocess_exception::bad_has_include_expression:
case preprocess_exception::ill_formed_directive:
case preprocess_exception::error_directive:
case preprocess_exception::warning_directive:
@@ -252,6 +254,7 @@ public:
"macro definition failed (out of memory?)", // macro_insertion_error
"could not find include file", // bad_include_file
"ill formed #include directive", // bad_include_statement
"ill formed __has_include expression", // bad_has_include_expression
"ill formed preprocessor directive", // ill_formed_directive
"encountered #error directive or #pragma wave stop()", // error_directive
"encountered #warning directive", // warning_directive
@@ -321,6 +324,7 @@ public:
util::severity_fatal, // macro_insertion_error
util::severity_error, // bad_include_file
util::severity_error, // bad_include_statement
util::severity_error, // bad_has_include_expression
util::severity_error, // ill_formed_directive
util::severity_fatal, // error_directive
util::severity_warning, // warning_directive

View File

@@ -0,0 +1,216 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
http://www.boost.org/
Copyright (c) 2020 Jeff Trull
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)
=============================================================================*/
#if !defined(BOOST_CPP_HAS_INCLUDE_GRAMMAR_HPP_F48287B2_DC67_40A8_B4A1_800EFBD67869_INCLUDED)
#define BOOST_CPP_HAS_INCLUDE_GRAMMAR_HPP_F48287B2_DC67_40A8_B4A1_800EFBD67869_INCLUDED
#include <boost/wave/wave_config.hpp>
#include <boost/assert.hpp>
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_closure.hpp>
#include <boost/spirit/include/classic_assign_actor.hpp>
#include <boost/spirit/include/classic_push_back_actor.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/util/pattern_parser.hpp>
#include <boost/wave/grammars/cpp_has_include_grammar_gen.hpp>
#if !defined(spirit_append_actor)
#define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor)
#endif // !has_include(spirit_append_actor)
// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace grammars {
///////////////////////////////////////////////////////////////////////////////
// define, whether the rule's should generate some debug output
#define TRACE_CPP_HAS_INCLUDE_GRAMMAR \
bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_HAS_INCLUDE_GRAMMAR) \
/**/
template <typename ContainerT>
struct has_include_grammar :
public boost::spirit::classic::grammar<has_include_grammar<ContainerT> >
{
has_include_grammar(ContainerT &tokens_seq_,
bool &is_quoted_filename_,
bool &is_system_)
: tokens_seq(tokens_seq_), is_quoted_filename(is_quoted_filename_),
is_system(is_system_), true_(true)
{
BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "has_include_grammar",
TRACE_CPP_HAS_INCLUDE_GRAMMAR);
is_quoted_filename = false;
is_system = false;
}
template <typename ScannerT>
struct definition
{
typedef boost::spirit::classic::rule<ScannerT> rule_t;
rule_t has_include_op;
rule_t system_include;
rule_t nonsystem_include;
rule_t computed_include;
definition(has_include_grammar const & self)
{
using namespace boost::spirit::classic;
using namespace boost::wave;
using namespace boost::wave::util;
has_include_op
= ch_p(T_IDENTIFIER) // token contains '__has_include'
>> (
ch_p(T_LEFTPAREN) >>
(system_include | nonsystem_include | computed_include)
// final right paren removed by caller
)
>> end_p
;
system_include
= ch_p(T_LESS)
[
spirit_append_actor(self.tokens_seq)
]
>> * (~ch_p(T_GREATER))
[
spirit_append_actor(self.tokens_seq)
]
>> ch_p(T_GREATER)
[
spirit_append_actor(self.tokens_seq)
][
assign_a(self.is_quoted_filename, self.true_)
][
assign_a(self.is_system, self.true_)
]
;
nonsystem_include = ch_p(T_STRINGLIT)
[
spirit_append_actor(self.tokens_seq)
][
assign_a(self.is_quoted_filename, self.true_)
]
;
// if neither of the above match we take everything between
// the parentheses and evaluate it ("computed include")
computed_include = * anychar_p
[
spirit_append_actor(self.tokens_seq)
]
;
BOOST_SPIRIT_DEBUG_TRACE_RULE(has_include_op, TRACE_CPP_HAS_INCLUDE_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(system_include, TRACE_CPP_HAS_INCLUDE_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(nonsystem_include, TRACE_CPP_HAS_INCLUDE_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(computed_include, TRACE_CPP_HAS_INCLUDE_GRAMMAR);
}
// start rule of this grammar
rule_t const& start() const
{ return has_include_op; }
};
ContainerT &tokens_seq;
bool &is_quoted_filename;
bool &is_system;
const bool true_; // Spirit Classic actors operate on references, not values
};
///////////////////////////////////////////////////////////////////////////////
#undef TRACE_CPP_HAS_INCLUDE_GRAMMAR
///////////////////////////////////////////////////////////////////////////////
//
// The following parse function is has_include here, to allow the separation of
// the compilation of the has_include_grammar from the function
// using it.
//
///////////////////////////////////////////////////////////////////////////////
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#define BOOST_WAVE_HAS_INCLUDE_GRAMMAR_GEN_INLINE
#else
#define BOOST_WAVE_HAS_INCLUDE_GRAMMAR_GEN_INLINE inline
#endif
// The parse_operator_define function is instantiated manually twice to
// simplify the explicit specialization of this template. This way the user
// has only to specify one template parameter (the lexer type) to correctly
// formulate the required explicit specialization.
// This results in no code overhead, because otherwise the function would be
// generated by the compiler twice anyway.
template <typename LexIteratorT>
BOOST_WAVE_HAS_INCLUDE_GRAMMAR_GEN_INLINE
boost::spirit::classic::parse_info<
typename has_include_grammar_gen<LexIteratorT>::iterator1_type
>
has_include_grammar_gen<LexIteratorT>::parse_operator_has_include (
iterator1_type const &first, iterator1_type const &last,
token_sequence_type &tokens,
bool &is_quoted_filename, bool &is_system)
{
using namespace boost::spirit::classic;
using namespace boost::wave;
has_include_grammar<token_sequence_type>
g(tokens, is_quoted_filename, is_system);
return boost::spirit::classic::parse (
first, last, g, ch_p(T_SPACE) | ch_p(T_CCOMMENT));
}
template <typename LexIteratorT>
BOOST_WAVE_HAS_INCLUDE_GRAMMAR_GEN_INLINE
boost::spirit::classic::parse_info<
typename has_include_grammar_gen<LexIteratorT>::iterator2_type
>
has_include_grammar_gen<LexIteratorT>::parse_operator_has_include (
iterator2_type const &first, iterator2_type const &last,
token_sequence_type &found_qualified_name,
bool &is_quoted_filename, bool &is_system)
{
using namespace boost::spirit::classic;
using namespace boost::wave;
has_include_grammar<token_sequence_type>
g(found_qualified_name, is_quoted_filename, is_system);
return boost::spirit::classic::parse (
first, last, g, ch_p(T_SPACE) | ch_p(T_CCOMMENT));
}
#undef BOOST_WAVE_HAS_INCLUDE_GRAMMAR_GEN_INLINE
///////////////////////////////////////////////////////////////////////////////
} // namespace grammars
} // namespace wave
} // namespace boost
// the suffix header occurs after all of the code
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // !defined(BOOST_CPP_HAS_INCLUDE_GRAMMAR_HPP_F48287B2_DC67_40A8_B4A1_800EFBD67869_INCLUDED)

View File

@@ -0,0 +1,87 @@
/*=============================================================================
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)
=============================================================================*/
#if !defined(BOOST_CPP_HAS_INCLUDE_GRAMMAR_GEN_HPP_825BE9F5_98A3_400D_A97C_AD76B3B08632_INCLUDED)
#define BOOST_CPP_HAS_INCLUDE_GRAMMAR_GEN_HPP_825BE9F5_98A3_400D_A97C_AD76B3B08632_INCLUDED
#include <boost/wave/wave_config.hpp>
#include <list>
#include <boost/spirit/include/classic_parser.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <boost/wave/util/unput_queue_iterator.hpp>
// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif
// suppress warnings about dependent classes not being exported from the dll
#ifdef BOOST_MSVC
#pragma warning(push)
#pragma warning(disable : 4251 4231 4660)
#endif
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace grammars {
template <typename LexIteratorT>
struct BOOST_WAVE_DECL has_include_grammar_gen
{
typedef typename LexIteratorT::token_type token_type;
typedef std::list<token_type, boost::fast_pool_allocator<token_type> >
token_sequence_type;
// The parse_operator_has_include function is instantiated manually twice to
// simplify the explicit specialization of this template. This way the user
// has only to specify one template parameter (the lexer iterator type) to
// correctly formulate the required explicit specialization.
// This results in no code overhead, because otherwise the function would be
// generated by the compiler twice anyway.
typedef boost::wave::util::unput_queue_iterator<
typename token_sequence_type::iterator, token_type, token_sequence_type>
iterator1_type;
typedef boost::wave::util::unput_queue_iterator<
LexIteratorT, token_type, token_sequence_type>
iterator2_type;
// parse the operator has_include and return the found qualified name
static boost::spirit::classic::parse_info<iterator1_type>
parse_operator_has_include (iterator1_type const &first,
iterator1_type const &last, token_sequence_type &found_qualified_name,
bool &is_quoted_filename, bool &is_system);
static boost::spirit::classic::parse_info<iterator2_type>
parse_operator_has_include (iterator2_type const &first,
iterator2_type const &last, token_sequence_type &found_qualified_name,
bool &is_quoted_filename, bool &is_system);
};
///////////////////////////////////////////////////////////////////////////////
} // namespace grammars
} // namespace wave
} // namespace boost
#ifdef BOOST_MSVC
#pragma warning(pop)
#endif
// the suffix header occurs after all of the code
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // !defined(BOOST_CPP_HAS_INCLUDE_GRAMMAR_GEN_HPP_825BE9F5_98A3_400D_A97C_AD76B3B08632_INCLUDED)

View File

@@ -41,14 +41,24 @@ enum language_support {
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_CPP1Z != 0
// support flags for C++17
support_option_has_include = 0x10000,
support_cpp1z = support_option_variadics | support_option_long_long |
support_option_no_newline_at_end_of_file | support_option_has_include |
0x20000,
support_cpp17 = support_cpp1z,
#if BOOST_WAVE_SUPPORT_CPP2A != 0
// support flags for C++20
support_option_va_opt = 0x10000,
support_option_va_opt = 0x40000,
support_cpp2a = support_option_variadics | support_option_long_long |
support_option_no_newline_at_end_of_file | support_option_va_opt | 0x20000,
support_option_no_newline_at_end_of_file | support_option_has_include |
support_option_va_opt | 0x80000,
support_cpp20 = support_cpp2a,
#endif
#endif
#endif
support_option_mask = 0xFFC0,
@@ -242,6 +252,9 @@ BOOST_WAVE_OPTION(emit_contnewlines) // support_option_emit_contnewlines
#if BOOST_WAVE_SUPPORT_CPP0X != 0
BOOST_WAVE_OPTION(no_newline_at_end_of_file) // support_no_newline_at_end_of_file
#endif
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
BOOST_WAVE_OPTION(has_include) // support_option_has_include
#endif
#undef BOOST_WAVE_NEED_OPTION
#undef BOOST_WAVE_ENABLE_OPTION

View File

@@ -1680,23 +1680,6 @@ char const *current_name = 0; // never try to match current file name
//
///////////////////////////////////////////////////////////////////////////////
namespace impl {
// trim all whitespace from the beginning and the end of the given string
template <typename StringT>
inline StringT
trim_whitespace(StringT const &s)
{
typedef typename StringT::size_type size_type;
size_type first = s.find_first_not_of(" \t\v\f");
if (StringT::npos == first)
return StringT();
size_type last = s.find_last_not_of(" \t\v\f");
return s.substr(first, last-first+1);
}
}
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::on_include(
@@ -1715,12 +1698,14 @@ token_sequence_type toexpand;
std::inserter(toexpand, toexpand.end()));
typename token_sequence_type::iterator begin2 = toexpand.begin();
// expanding the computed include
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
false, false);
// now, include the file
string_type s (impl::trim_whitespace(boost::wave::util::impl::as_string(expanded)));
bool is_system = '<' == s[0] && '>' == s[s.size()-1];
// now, include the file
using namespace boost::wave::util::impl;
string_type s (trim_whitespace(as_string(expanded)));
bool is_system = '<' == s[0] && '>' == s[s.size()-1];
if (!is_system && !('\"' == s[0] && '\"' == s[s.size()-1])) {
// should resolve into something like <...> or "..."
@@ -2322,7 +2307,7 @@ token_sequence_type toexpand;
// preprocess the body of this #line message
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(),
expanded, false);
expanded, false, false);
error = preprocess_exception::no_error;
if (!impl::retrieve_line_info(expanded.begin(), expanded.end(),
@@ -2404,7 +2389,7 @@ token_sequence_type toexpand;
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
false, false);
if (!ctx.get_hooks().found_error_directive(ctx.derived(), toexpand))
#else
// simply copy the body of this #error message to the issued diagnostic
@@ -2453,7 +2438,7 @@ token_sequence_type toexpand;
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(), expanded,
false);
false, false);
if (!ctx.get_hooks().found_warning_directive(ctx.derived(), toexpand))
#else
// simply copy the body of this #warning message to the issued diagnostic
@@ -2523,7 +2508,7 @@ const_tree_iterator_t last = make_ref_transform_iterator(end, get_value);
typename token_sequence_type::iterator begin2 = toexpand.begin();
ctx.expand_whole_tokensequence(begin2, toexpand.end(),
expanded, false);
expanded, false, false);
#else
// do _not_ preprocess the token sequence
std::copy(first, last, std::inserter(expanded, expanded.end()));

View File

@@ -43,6 +43,9 @@
#include <boost/wave/util/cpp_macromap_predef.hpp>
#include <boost/wave/util/filesystem_compatibility.hpp>
#include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
#include <boost/wave/grammars/cpp_has_include_grammar_gen.hpp>
#endif
#include <boost/wave/wave_version.hpp>
#include <boost/wave/cpp_exceptions.hpp>
@@ -109,6 +112,13 @@ public:
// expects an arbitrary string as its parameter
bool is_defined(string_type const &str) const;
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
// expects a token sequence as its parameters
template <typename IteratorT>
bool has_include(IteratorT const &begin, IteratorT const &end,
bool is_quoted_filename, bool is_system) const;
#endif
// Get the macro definition for the given macro scope
bool get_macro(string_type const &name, bool &has_parameters,
bool &is_predefined, position_type &pos,
@@ -123,13 +133,15 @@ public:
template <typename IteratorT, typename ContainerT>
token_type const &expand_tokensequence(IteratorT &first,
IteratorT const &last, ContainerT &pending, ContainerT &expanded,
bool& seen_newline, bool expand_operator_defined);
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include);
// Expand all macros inside the given token sequence
template <typename IteratorT, typename ContainerT>
void expand_whole_tokensequence(ContainerT &expanded,
IteratorT &first, IteratorT const &last,
bool expand_operator_defined);
bool expand_operator_defined,
bool expand_operator_has_include);
// Init the predefined macros (add them to the given scope)
void init_predefined_macros(char const *fname = "<Unknown>",
@@ -162,7 +174,8 @@ protected:
token_type const &expand_tokensequence_worker(ContainerT &pending,
unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
bool& seen_newline, bool expand_operator_defined);
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include);
// Collect all arguments supplied to a macro invocation
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
@@ -185,6 +198,7 @@ protected:
typename defined_macros_type::iterator it,
IteratorT &first, IteratorT const &last,
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include,
defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
// Expand a predefined macro (__LINE__, __FILE__ and __INCLUDE_LEVEL__)
@@ -197,6 +211,7 @@ protected:
void expand_argument (typename std::vector<ContainerT>::size_type arg,
std::vector<ContainerT> &arguments,
std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
bool expand_operator_has_include,
std::vector<bool> &has_expanded_args);
// Expand the replacement list (replaces parameters with arguments)
@@ -205,20 +220,30 @@ protected:
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);
bool expand_operator_defined,
bool expand_operator_has_include,
ContainerT &expanded);
// Rescans the replacement list for macro expansion
template <typename IteratorT, typename ContainerT>
void rescan_replacement_list(token_type const &curr_token,
macro_definition_type &macrodef, ContainerT &replacement_list,
ContainerT &expanded, bool expand_operator_defined,
bool expand_operator_has_include,
IteratorT &nfirst, IteratorT const &nlast);
// Resolves the operator defined() and replces the token with "0" or "1"
// Resolves the operator defined() and replaces the token with "0" or "1"
template <typename IteratorT, typename ContainerT>
token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
ContainerT &expanded);
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
// Resolves the operator __has_include() and replaces the token with "0" or "1"
template <typename IteratorT, typename ContainerT>
token_type const &resolve_has_include(IteratorT &first, IteratorT const &last,
ContainerT &expanded);
#endif
// Resolve operator _Pragma or the #pragma directive
template <typename IteratorT, typename ContainerT>
bool resolve_operator_pragma(IteratorT &first,
@@ -232,6 +257,8 @@ protected:
bool is_valid_concat(string_type new_value,
position_type const &pos, ContainerT &rescanned);
static bool is_space(char);
#if BOOST_WAVE_SERIALIZATION != 0
public:
BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
@@ -283,7 +310,7 @@ macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
parameter_container_type &parameters, definition_container_type &definition,
bool is_predefined, defined_macros_type *scope)
{
if (!is_predefined && impl::is_special_macroname (name.get_value())) {
if (!is_predefined && impl::is_special_macroname (ctx, name.get_value())) {
// exclude special macro names
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
illegal_redefinition, name.get_value().c_str(), main_pos,
@@ -308,6 +335,17 @@ macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
name.get_value().c_str());
return false;
}
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
if (boost::wave::need_has_include(ctx.get_language()) &&
"__has_include" == name.get_value())
{
// can't use __has_include 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;
}
#endif
if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
// exclude special operator names
BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
@@ -459,8 +497,16 @@ macromap<ContextT>::is_defined(typename token_type::string_type const &name,
if (name.size() < 8 || '_' != name[0] || '_' != name[1])
return false; // quick check failed
return name == "__LINE__" || name == "__FILE__" ||
name == "__INCLUDE_LEVEL__";
if (name == "__LINE__" || name == "__FILE__" ||
name == "__INCLUDE_LEVEL__")
return true;
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
return (boost::wave::need_has_include(ctx.get_language()) &&
(name == "__has_include"));
#else
return false;
#endif
}
template <typename ContextT>
@@ -508,6 +554,51 @@ macromap<ContextT>::is_defined(string_type const &str) const
return is_defined(str, cit, 0);
}
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
///////////////////////////////////////////////////////////////////////////////
//
// has_include(): returns whether a path expression is an valid include file
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
template <typename IteratorT>
inline bool
macromap<ContextT>::has_include(
IteratorT const &begin, IteratorT const &end,
bool is_quoted_filename, bool is_system) const
{
typename ContextT::token_sequence_type filetoks;
if (is_quoted_filename) {
filetoks = typename ContextT::token_sequence_type(begin, end);
} else {
IteratorT first = begin;
IteratorT last = end;
ctx.expand_whole_tokensequence(first, last, filetoks);
}
// extract tokens into string and trim whitespace
using namespace boost::wave::util::impl;
std::string fn(trim_whitespace(as_string(filetoks)).c_str());
// verify and remove initial and final delimiters
if (!((fn.size() >= 3) &&
(((fn[0] == '"') && (*fn.rbegin() == '"')) ||
((fn[0] == '<') && (*fn.rbegin() == '>')))))
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_has_include_expression,
fn.c_str(), ctx.get_main_pos());
fn = fn.substr(1, fn.size() - 2);
// test header existence
std::string dir_path;
std::string native_path;
return ctx.get_hooks().locate_include_file(
ctx, fn, is_system, 0, dir_path, native_path);
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Get the macro definition for the given macro scope
@@ -549,7 +640,7 @@ macromap<ContextT>::remove_macro(string_type const &name,
if (it != current_macros->end()) {
if ((*it).second->is_predefined) {
if (!even_predefined || impl::is_special_macroname(name)) {
if (!even_predefined || impl::is_special_macroname(ctx, name)) {
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
bad_undefine_statement, name.c_str(), main_pos);
return false;
@@ -567,7 +658,7 @@ macromap<ContextT>::remove_macro(string_type const &name,
#endif
return true;
}
else if (impl::is_special_macroname(name)) {
else if (impl::is_special_macroname(ctx, name)) {
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement,
name.c_str(), pos);
}
@@ -591,7 +682,8 @@ template <typename IteratorT, typename ContainerT>
inline typename ContextT::token_type const &
macromap<ContextT>::expand_tokensequence(IteratorT &first,
IteratorT const &last, ContainerT &pending, ContainerT &expanded,
bool& seen_newline, bool expand_operator_defined)
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include)
{
typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
gen_type;
@@ -603,7 +695,7 @@ macromap<ContextT>::expand_tokensequence(IteratorT &first,
on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
return expand_tokensequence_worker(pending, first_it, last_it,
seen_newline, expand_operator_defined);
seen_newline, expand_operator_defined, expand_operator_has_include);
}
///////////////////////////////////////////////////////////////////////////////
@@ -625,7 +717,8 @@ macromap<ContextT>::expand_tokensequence_worker(
ContainerT &pending,
unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
bool& seen_newline, bool expand_operator_defined)
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include)
{
// if there exist pending tokens (tokens, which are already preprocessed), then
// return the next one from there
@@ -661,6 +754,14 @@ macromap<ContextT>::expand_tokensequence_worker(
// resolve operator defined()
return resolve_defined(first, last, pending);
}
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
else if (boost::wave::need_has_include(ctx.get_language()) &&
expand_operator_has_include &&
(*first).get_value() == "__has_include") {
// resolve operator __has_include()
return resolve_has_include(first, last, pending);
}
#endif
else if (boost::wave::need_variadics(ctx.get_language()) &&
(*first).get_value() == "_Pragma")
{
@@ -689,7 +790,8 @@ macromap<ContextT>::expand_tokensequence_worker(
// the current token contains an identifier, which is currently
// defined as a macro
if (expand_macro(pending, name_token, it, first, last,
seen_newline, expand_operator_defined))
seen_newline, expand_operator_defined,
expand_operator_has_include))
{
// the tokens returned by expand_macro should be rescanned
// beginning at the last token of the returned replacement list
@@ -716,15 +818,11 @@ macromap<ContextT>::expand_tokensequence_worker(
}
// return the next preprocessed token
return expand_tokensequence_worker(pending, first, last,
seen_newline, expand_operator_defined);
return expand_tokensequence_worker(
pending, first, last,
seen_newline, expand_operator_defined,
expand_operator_has_include);
}
// else if (expand_operator_defined) {
// // in preprocessing conditionals undefined identifiers and keywords
// // are to be replaced with '0' (see. C++ standard 16.1.4, [cpp.cond])
// return act_token =
// token_type(T_INTLIT, "0", (*first++).get_position());
// }
else {
act_token = name_token;
++first;
@@ -913,8 +1011,9 @@ template <typename ContextT>
template <typename IteratorT, typename ContainerT>
inline void
macromap<ContextT>::expand_whole_tokensequence(ContainerT &expanded,
IteratorT &first, IteratorT const &last,
bool expand_operator_defined)
IteratorT &first, IteratorT const &last,
bool expand_operator_defined,
bool expand_operator_has_include)
{
typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
gen_type;
@@ -930,8 +1029,10 @@ macromap<ContextT>::expand_whole_tokensequence(ContainerT &expanded,
while (!pending_queue.empty() || first_it != last_it) {
expanded.push_back(
expand_tokensequence_worker(pending_queue, first_it,
last_it, seen_newline, expand_operator_defined)
expand_tokensequence_worker(
pending_queue, first_it,
last_it, seen_newline, expand_operator_defined,
expand_operator_has_include)
);
}
@@ -952,7 +1053,8 @@ inline void
macromap<ContextT>::expand_argument (
typename std::vector<ContainerT>::size_type arg,
std::vector<ContainerT> &arguments, std::vector<ContainerT> &expanded_args,
bool expand_operator_defined, std::vector<bool> &has_expanded_args)
bool expand_operator_defined, bool expand_operator_has_include,
std::vector<bool> &has_expanded_args)
{
if (!has_expanded_args[arg]) {
// expand the argument only once
@@ -962,8 +1064,9 @@ macromap<ContextT>::expand_argument (
argument_iterator_type begin_it = arguments[arg].begin();
argument_iterator_type end_it = arguments[arg].end();
expand_whole_tokensequence(expanded_args[arg], begin_it, end_it,
expand_operator_defined);
expand_whole_tokensequence(
expanded_args[arg], begin_it, end_it,
expand_operator_defined, expand_operator_has_include);
impl::remove_placeholders(expanded_args[arg]);
has_expanded_args[arg] = true;
}
@@ -985,6 +1088,7 @@ macromap<ContextT>::expand_replacement_list(
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,
bool expand_operator_has_include,
ContainerT &expanded)
{
using namespace boost::wave;
@@ -1064,8 +1168,10 @@ bool adjacent_stringize = false;
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);
expand_argument(
arg, arguments, expanded_args,
expand_operator_defined, expand_operator_has_include,
has_expanded_args);
}
impl::replace_ellipsis(expanded_args, i, expanded, pos);
}
@@ -1081,8 +1187,10 @@ bool adjacent_stringize = false;
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);
expand_argument(
arg, arguments, expanded_args,
expand_operator_defined, expand_operator_has_include,
has_expanded_args);
}
// locate the end of the __VA_OPT__ call
@@ -1136,7 +1244,9 @@ bool adjacent_stringize = false;
// [cstart, cit) is now the args to va_opt
// recursively process them
expand_replacement_list(arg_start, cit, arguments,
expand_operator_defined, va_expanded);
expand_operator_defined,
expand_operator_has_include,
va_expanded);
}
// run final hooks
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
@@ -1157,8 +1267,10 @@ bool adjacent_stringize = false;
{
BOOST_ASSERT(i < arguments.size());
// ensure argument i to be expanded
expand_argument(i, arguments, expanded_args,
expand_operator_defined, has_expanded_args);
expand_argument(
i, arguments, expanded_args,
expand_operator_defined, expand_operator_has_include,
has_expanded_args);
// replace argument
BOOST_ASSERT(i < expanded_args.size());
@@ -1259,7 +1371,9 @@ template <typename IteratorT, typename ContainerT>
inline void
macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
macro_definition_type &macro_def, ContainerT &replacement_list,
ContainerT &expanded, bool expand_operator_defined,
ContainerT &expanded,
bool expand_operator_defined,
bool expand_operator_has_include,
IteratorT &nfirst, IteratorT const &nlast)
{
if (!replacement_list.empty()) {
@@ -1290,8 +1404,9 @@ macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
typename ContainerT::iterator begin_it = replacement_list.begin();
typename ContainerT::iterator end_it = replacement_list.end();
expand_whole_tokensequence(expanded, begin_it, end_it,
expand_operator_defined);
expand_whole_tokensequence(
expanded, begin_it, end_it,
expand_operator_defined, expand_operator_has_include);
// trim replacement list, leave placeholder tokens untouched
impl::trim_replacement_list(expanded);
@@ -1320,6 +1435,7 @@ macromap<ContextT>::expand_macro(ContainerT &expanded,
token_type const &curr_token, typename defined_macros_type::iterator it,
IteratorT &first, IteratorT const &last,
bool& seen_newline, bool expand_operator_defined,
bool expand_operator_has_include,
defined_macros_type *scope, ContainerT *queue_symbol)
{
using namespace boost::wave;
@@ -1471,6 +1587,7 @@ ContainerT replacement_list;
expand_replacement_list(macro_def.macrodefinition.begin(),
macro_def.macrodefinition.end(),
arguments, expand_operator_defined,
expand_operator_has_include,
replacement_list);
}
else {
@@ -1556,8 +1673,10 @@ ContainerT expanded_list;
ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
#endif
rescan_replacement_list(curr_token, macro_def, replacement_list,
expanded_list, expand_operator_defined, first, last);
rescan_replacement_list(
curr_token, macro_def, replacement_list,
expanded_list, expand_operator_defined,
expand_operator_has_include, first, last);
#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
ctx.get_hooks().rescanned_macro(expanded_list);
@@ -1699,6 +1818,69 @@ on_exit::pop_front<definition_container_type> pop_front_token(pending);
return act_token = pending.front();
}
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
///////////////////////////////////////////////////////////////////////////////
//
// resolve_has_include(): resolve the operator __has_include() and replace
// it with the correct T_INTLIT token
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
template <typename IteratorT, typename ContainerT>
inline typename ContextT::token_type const &
macromap<ContextT>::resolve_has_include(IteratorT &first,
IteratorT const &last, ContainerT &pending)
{
using namespace boost::wave;
using namespace boost::wave::grammars;
ContainerT result;
bool is_quoted_filename;
bool is_system;
// to simplify the parser we check for the trailing right paren first
// scan from the beginning because unput_queue_iterator is Forward
IteratorT end_find_it = first;
++end_find_it;
IteratorT rparen_it = first;
while (end_find_it != last) {
++end_find_it;
++rparen_it;
}
boost::spirit::classic::parse_info<IteratorT> hit(first);
if ((rparen_it != first) && (T_RIGHTPAREN == *rparen_it)) {
IteratorT start = first;
hit = has_include_grammar_gen<typename ContextT::lexer_type>::
parse_operator_has_include(start, rparen_it, result, is_quoted_filename, is_system);
}
if (!hit.hit) {
string_type msg ("__has_include(): ");
msg = msg + util::impl::as_string<string_type>(first, last);
BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
msg.c_str(), main_pos);
// insert a dummy token
pending.push_back(token_type(T_INTLIT, "0", main_pos));
}
else {
impl::assign_iterator<IteratorT>::do_(first, last);
// insert a token, which reflects the outcome
pending.push_back(
token_type(T_INTLIT,
has_include(result.begin(), result.end(),
is_quoted_filename, is_system) ? "1" : "0",
main_pos));
}
on_exit::pop_front<definition_container_type> pop_front_token(pending);
return act_token = pending.front();
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// resolve_operator_pragma(): resolve the operator _Pragma() and dispatch to
@@ -1761,7 +1943,7 @@ macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
ContainerT expanded;
argument_iterator_type begin_it = arguments[0].begin();
argument_iterator_type end_it = arguments[0].end();
expand_whole_tokensequence(expanded, begin_it, end_it, false);
expand_whole_tokensequence(expanded, begin_it, end_it, false, false);
// un-escape the parameter of the operator _Pragma
typedef typename token_type::string_type string_type;

View File

@@ -18,6 +18,7 @@
#include <boost/wave/wave_config.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/util/unput_queue_iterator.hpp>
#include <boost/wave/language_support.hpp>
// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
@@ -135,9 +136,9 @@ namespace impl {
// Test, whether a given identifier resolves to a predefined name
//
///////////////////////////////////////////////////////////////////////////////
template <typename StringT>
template <typename ContextT, typename StringT>
inline bool
is_special_macroname (StringT const &name)
is_special_macroname (ContextT const & ctx, StringT const &name)
{
if (name.size() < 7)
return false;
@@ -145,6 +146,12 @@ is_special_macroname (StringT const &name)
if ("defined" == name)
return true;
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
if (boost::wave::need_has_include(ctx.get_language()) &&
("__has_include" == name))
return true;
#endif
if ('_' == name[0] && '_' == name[1]) {
StringT str = name.substr(2);

View File

@@ -330,6 +330,20 @@ namespace impl {
return id;
}
// trim all whitespace from the beginning and the end of the given string
template <typename StringT>
inline StringT
trim_whitespace(StringT const &s)
{
typedef typename StringT::size_type size_type;
size_type first = s.find_first_not_of(" \t\v\f");
if (StringT::npos == first)
return StringT();
size_type last = s.find_last_not_of(" \t\v\f");
return s.substr(first, last-first+1);
}
} // namespace impl
///////////////////////////////////////////////////////////////////////////////

View File

@@ -102,6 +102,22 @@
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
#endif
///////////////////////////////////////////////////////////////////////////////
// Decide whether to support C++17
//
#if !defined(BOOST_WAVE_SUPPORT_CPP1Z)
# define BOOST_WAVE_SUPPORT_CPP1Z 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_HAS_INCLUDE)
# define BOOST_WAVE_SUPPORT_HAS_INCLUDE 1
# endif
#elif BOOST_WAVE_SUPPORT_CPP1Z == 0
# undef BOOST_WAVE_SUPPORT_HAS_INCLUDE
# define BOOST_WAVE_SUPPORT_HAS_INCLUDE 0
#endif
///////////////////////////////////////////////////////////////////////////////
// Decide whether to support C++20
@@ -112,8 +128,12 @@
# define BOOST_WAVE_SUPPORT_CPP0X 1
# undef BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS
# define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 1
# undef BOOST_WAVE_SUPPORT_CPP1Z
# define BOOST_WAVE_SUPPORT_CPP1Z 1
# if !defined(BOOST_WAVE_SUPPORT_HAS_INCLUDE)
# define BOOST_WAVE_SUPPORT_HAS_INCLUDE 1
# endif
# 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
@@ -287,6 +307,7 @@
#define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
#define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
#define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
#define BOOST_SPIRIT_DEBUG_FLAGS_HAS_INCLUDE_GRAMMAR 0x0080
#if !defined(BOOST_SPIRIT_DEBUG_FLAGS_CPP)
#define BOOST_SPIRIT_DEBUG_FLAGS_CPP 0 // default is no debugging

View File

@@ -14,6 +14,7 @@ SOURCES =
../instantiate_cpp_grammar
../instantiate_cpp_literalgrs
../instantiate_defined_grammar
../instantiate_has_include_grammar
../instantiate_slex_lexer
;

View File

@@ -0,0 +1,39 @@
/*=============================================================================
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)
=============================================================================*/
#include "cpp_tokens.hpp" // config data
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/token_ids.hpp>
#include "slex_token.hpp"
#include "slex_iterator.hpp"
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
typedef boost::wave::cpplexer::slex::slex_iterator<
boost::wave::cpplexer::slex_token<> >
lexer_type;
template struct boost::wave::grammars::has_include_grammar_gen<lexer_type>;
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View File

@@ -14,6 +14,7 @@ SOURCES =
../instantiate_cpp_grammar
../instantiate_cpp_literalgrs
../instantiate_defined_grammar
../instantiate_has_include_grammar
../instantiate_lexertl_lexer
;

View File

@@ -0,0 +1,41 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Sample: List include dependencies of a given source file
http://www.boost.org/
Copyright (c) 2001-2010 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)
=============================================================================*/
#include "list_includes.hpp" // config data
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include "lexertl_iterator.hpp"
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
typedef boost::wave::cpplexer::lexertl::lex_iterator<
boost::wave::cpplexer::lex_token<> >
lexer_type;
template struct boost::wave::grammars::has_include_grammar_gen<lexer_type>;
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View File

@@ -14,6 +14,7 @@ exe real_positions
../instantiate_cpp_grammar.cpp
../instantiate_cpp_literalgrs.cpp
../instantiate_defined_grammar.cpp
../instantiate_has_include_grammar.cpp
../instantiate_re2c_lexer.cpp
../instantiate_re2c_lexer_str.cpp
/boost/wave//boost_wave

View File

@@ -0,0 +1,39 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Example: real_positions
http://www.boost.org/
Copyright (c) 2001-2010 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
=============================================================================*/
#include <boost/wave/wave_config.hpp>
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/token_ids.hpp>
#include "real_position_token.hpp" // token class
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer type
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
typedef boost::wave::cpplexer::lex_iterator<lex_token<> > lexer_type;
template struct boost::wave::grammars::has_include_grammar_gen<lexer_type>;
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View File

@@ -13,6 +13,7 @@ SOURCES =
../instantiate_xlex_lexer
../instantiate_cpp_grammar
../instantiate_defined_grammar
../instantiate_has_include_grammar
;
exe token_statistics

View File

@@ -0,0 +1,42 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Sample: Collect token statistics
Explicit instantiation of the has_include_grammar template
http://www.boost.org/
Copyright (c) 2001-2010 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)
=============================================================================*/
#include "token_statistics.hpp"
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include "xlex_iterator.hpp"
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
typedef boost::wave::cpplexer::xlex::xlex_iterator<
boost::wave::cpplexer::lex_token<> >
lexer_type;
template struct boost::wave::grammars::has_include_grammar_gen<lexer_type>;
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View File

@@ -12,6 +12,7 @@ SOURCES =
../idl
../instantiate_cpp_grammar
../instantiate_defined_grammar
../instantiate_has_include_grammar
../instantiate_predef_macros
../instantiate_re2c_lexer
../instantiate_re2c_lexer_str

View File

@@ -45,6 +45,7 @@
#include <boost/wave/grammars/cpp_expression_grammar.hpp>
#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
#endif
///////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,42 @@
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Sample: IDL oriented preprocessor
Explicit instantiation of the has_include_grammar template
http://www.boost.org/
Copyright (c) 2001-2010 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)
=============================================================================*/
#include "idl.hpp"
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include "idllexer/idl_lex_iterator.hpp"
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
typedef boost::wave::idllexer::lex_iterator<
boost::wave::cpplexer::lex_token<> >
lexer_type;
template struct boost::wave::grammars::has_include_grammar_gen<lexer_type>;
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View File

@@ -0,0 +1,52 @@
/*=============================================================================
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)
=============================================================================*/
#define BOOST_WAVE_SOURCE 1
// disable stupid compiler warnings
#include <boost/config/warning_disable.hpp>
#include <boost/wave/wave_config.hpp>
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#include <string>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Explicit instantiation of the has_include_grammar_gen template
// with the correct token type. This instantiates the corresponding parse
// function, which in turn instantiates the has_include_grammar
// object (see wave/grammars/cpp_has_include_grammar.hpp)
//
///////////////////////////////////////////////////////////////////////////////
// if you want to use your own token type the following line must be adjusted
typedef boost::wave::cpplexer::lex_token<> token_type;
// no need to change anything below
typedef boost::wave::cpplexer::lex_iterator<token_type> lexer_type;
template struct BOOST_SYMBOL_VISIBLE boost::wave::grammars::has_include_grammar_gen<lexer_type>;
// the suffix header occurs after all of the code
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_SUFFIX
#endif
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0

View 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++17
//O -Werror
// Test __has_include() returning false
#ifdef __has_include
#if __has_include("some_include_file.h")
#warning found header, but should not have
#elif __has_include("some_include_file.h")
#warning found header, but should not have : elif
#else
#define NOTFOUND_AS_EXPECTED
#endif
#else
#warning has_include does not seem to be working
#endif
//H 10: t_2_023.cpp(15): #ifdef
//H 11: t_2_023.cpp(15): #ifdef __has_include: 1
//H 10: t_2_023.cpp(16): #if
//H 11: t_2_023.cpp(16): #if __has_include("some_include_file.h"): 0
//H 10: t_2_023.cpp(18): #elif
//H 11: t_2_023.cpp(18): #elif __has_include("some_include_file.h"): 0
//H 10: t_2_023.cpp(21): #define
//H 08: t_2_023.cpp(21): NOTFOUND_AS_EXPECTED=
//H 10: t_2_023.cpp(22): #endif
//H 10: t_2_023.cpp(23): #else
#ifndef __has_include
#warning has_include appears to be disabled
#else
#define HAS_INCLUDE_WORKS_IFNDEF
#if __has_include("t_2_023.cpp")
#define HAS_INCLUDE_WORKS_FILECHECK
#endif
#if !__has_include("t_2_023.cpp")
#warning has_include cannot find the file it is in
#elif __has_include("t_2_023.cpp")
#define HAS_INCLUDE_ELIF_FILECHECK
#else
#warning has_include cannot find the file it is in - elif
#endif
#endif
//H 10: t_2_023.cpp(38): #ifndef
//H 11: t_2_023.cpp(38): #ifndef __has_include: 1
//H 10: t_2_023.cpp(41): #define
//H 08: t_2_023.cpp(41): HAS_INCLUDE_WORKS_IFNDEF=
//H 10: t_2_023.cpp(42): #if
//H 11: t_2_023.cpp(42): #if __has_include("t_2_023.cpp"): 1
//H 10: t_2_023.cpp(43): #define
//H 08: t_2_023.cpp(43): HAS_INCLUDE_WORKS_FILECHECK=
//H 10: t_2_023.cpp(44): #endif
//H 10: t_2_023.cpp(45): #if
//H 11: t_2_023.cpp(45): #if !__has_include("t_2_023.cpp"): 0
//H 10: t_2_023.cpp(47): #elif
//H 11: t_2_023.cpp(47): #elif __has_include("t_2_023.cpp"): 1
//H 10: t_2_023.cpp(48): #define
//H 08: t_2_023.cpp(48): HAS_INCLUDE_ELIF_FILECHECK=
//H 10: t_2_023.cpp(49): #else
//H 10: t_2_023.cpp(52): #endif

View File

@@ -0,0 +1,95 @@
/*=============================================================================
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++17
//O -Werror
// Test __has_include() with system paths
// point system path to this directory
//O -S.
#ifdef __has_include
#if __has_include(<t_2_024.cpp>)
#define FOUND_SELF_VIA_SYSTEM_PATH
#else
#warning could not find this file via system path
#endif
#else
#warning has_include is not defined
#endif
//H 10: t_2_024.cpp(18): #ifdef
//H 11: t_2_024.cpp(18): #ifdef __has_include: 1
//H 10: t_2_024.cpp(19): #if
//H 11: t_2_024.cpp(19): #if __has_include(<t_2_024.cpp>): 1
//H 10: t_2_024.cpp(20): #define
//H 08: t_2_024.cpp(20): FOUND_SELF_VIA_SYSTEM_PATH=
//H 10: t_2_024.cpp(21): #else
//H 10: t_2_024.cpp(24): #else
#ifdef __has_include
#if 0
#elif __has_include(<t_2_024.cpp>)
#define FOUND_SELF_VIA_SYSTEM_PATH_ELIF
#else
#warning could not find this file via system path - elif
#endif
#endif
//H 10: t_2_024.cpp(37): #ifdef
//H 11: t_2_024.cpp(37): #ifdef __has_include: 1
//H 10: t_2_024.cpp(38): #if
//H 11: t_2_024.cpp(38): #if 0: 0
//H 10: t_2_024.cpp(39): #elif
//H 11: t_2_024.cpp(39): #elif __has_include(<t_2_024.cpp>): 1
//H 10: t_2_024.cpp(40): #define
//H 08: t_2_024.cpp(40): FOUND_SELF_VIA_SYSTEM_PATH_ELIF=
//H 10: t_2_024.cpp(41): #else
//H 10: t_2_024.cpp(44): #endif
#ifdef __has_include
#if !__has_include(<some_include_file.h>)
#define NOTFOUND_AS_EXPECTED
#else
#warning found nonexistent file
#endif
#else
#warning has_include is not defined
#endif
//H 10: t_2_024.cpp(57): #ifdef
//H 11: t_2_024.cpp(57): #ifdef __has_include: 1
//H 10: t_2_024.cpp(58): #if
//H 11: t_2_024.cpp(58): #if !__has_include(<some_include_file.h>): 1
//H 10: t_2_024.cpp(59): #define
//H 08: t_2_024.cpp(59): NOTFOUND_AS_EXPECTED=
//H 10: t_2_024.cpp(60): #else
//H 10: t_2_024.cpp(63): #else
#ifdef __has_include
#if 0
#elif !__has_include(<some_include_file.h>)
#define NOTFOUND_AS_EXPECTED_ELIF
#else
#warning found nonexistent file - elif
#endif
#endif
//H 10: t_2_024.cpp(76): #ifdef
//H 11: t_2_024.cpp(76): #ifdef __has_include: 1
//H 10: t_2_024.cpp(77): #if
//H 11: t_2_024.cpp(77): #if 0: 0
//H 10: t_2_024.cpp(78): #elif
//H 11: t_2_024.cpp(78): #elif !__has_include(<some_include_file.h>): 1
//H 10: t_2_024.cpp(79): #define
//H 08: t_2_024.cpp(79): NOTFOUND_AS_EXPECTED_ELIF=
//H 10: t_2_024.cpp(80): #else
//H 10: t_2_024.cpp(83): #endif

View File

@@ -0,0 +1,76 @@
/*=============================================================================
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++17
//O -Werror
// Test __has_include() with computed includes
// point system path to this directory
//O -S.
// does this file exist?
#if __has_include(__FILE__)
#define GOTTHISFILE
#else
#warning has_include could not find with file predefined macro
#endif
//H 10: t_2_025.cpp(19): #if
//H 01: <built-in>(1): __FILE__
//H 02: "$F"
//H 03: "$F"
//H 11: t_2_025.cpp(19): #if __has_include(__FILE__): 1
//H 10: t_2_025.cpp(20): #define
//H 08: t_2_025.cpp(20): GOTTHISFILE=
//H 10: t_2_025.cpp(21): #else
// try a computation producing a quoted file
#define FOO(X) "t_2_025.cpp"
#define BAR 0
#if __has_include(FOO(BAR))
#define FOUND_DQUOTE
#else
#warning has_include could not find this file using quotes
#endif
//H 10: t_2_025.cpp(35): #define
//H 08: t_2_025.cpp(35): FOO(X)="t_2_025.cpp"
//H 10: t_2_025.cpp(36): #define
//H 08: t_2_025.cpp(36): BAR=0
//H 10: t_2_025.cpp(37): #if
//H 00: t_2_025.cpp(37): FOO(BAR), [t_2_025.cpp(35): FOO(X)="t_2_025.cpp"]
//H 02: "t_2_025.cpp"
//H 03: "t_2_025.cpp"
//H 11: t_2_025.cpp(37): #if __has_include(FOO(BAR)): 1
//H 10: t_2_025.cpp(38): #define
//H 08: t_2_025.cpp(38): FOUND_DQUOTE=
//H 10: t_2_025.cpp(39): #else
// try a computation producing a bracketed name
#define EMPTY
#define ASSEMBLE(ARG) <t_2_025.cpp>
#if __has_include(ASSEMBLE(EMPTY))
#define FOUND_ABRACKET
#else
#warning has_include could not find this file using angle brackets
#endif
//H 10: t_2_025.cpp(57): #define
//H 08: t_2_025.cpp(57): EMPTY=
//H 10: t_2_025.cpp(58): #define
//H 08: t_2_025.cpp(58): ASSEMBLE(ARG)=<t_2_025.cpp>
//H 10: t_2_025.cpp(59): #if
//H 00: t_2_025.cpp(59): ASSEMBLE(EMPTY), [t_2_025.cpp(58): ASSEMBLE(ARG)=<t_2_025.cpp>]
//H 02: <t_2_025.cpp>
//H 03: <t_2_025.cpp>
//H 11: t_2_025.cpp(59): #if __has_include(ASSEMBLE(EMPTY)): 1
//H 10: t_2_025.cpp(60): #define
//H 08: t_2_025.cpp(60): FOUND_ABRACKET=
//H 10: t_2_025.cpp(61): #else

View File

@@ -0,0 +1,30 @@
/*=============================================================================
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++17
//O -Werror
// Test __has_include() with some interesting cases
#if __has_include(/* comment */ __FILE__ /* comment */)
#define GOTTHISFILE_WITHCOMMENTS
#else
#warning cannot find using file macro when comments are present
#endif
//H 10: t_2_026.cpp(15): #if
//H 01: <built-in>(1): __FILE__
//H 02: "$F"
//H 03: "$F"
//H 11: t_2_026.cpp(15): #if __has_include(/* comment */ __FILE__ /* comment */): 1
//H 10: t_2_026.cpp(16): #define
//H 08: t_2_026.cpp(16): GOTTHISFILE_WITHCOMMENTS=
//H 10: t_2_026.cpp(17): #else

View 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)
=============================================================================*/
// Test error reporting on undefinition of '__has_include'
//O --c++17
//O -Werror
#undef __has_include
//E t_2_027.cpp(15): warning: #undef may not be used on this predefined name: __has_include

View 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)
=============================================================================*/
// Test error reporting during redefinition of '__has_include'
//O --c++17
//O -Werror
#define __has_include(X) something
//E t_2_028.cpp(15): warning: this predefined name may not be redefined: __has_include

View File

@@ -0,0 +1,25 @@
/*=============================================================================
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)
=============================================================================*/
// Test that __has_include is an available macro name before C++17
//O --c++11
//O -Werror
#ifdef __has_include
#warning has_include is available in C++11 mode
#endif
#define __has_include(X) something
//H 10: t_2_029.cpp(15): #ifdef
//H 11: t_2_029.cpp(15): #ifdef __has_include: 0
//H 10: t_2_029.cpp(19): #define
//H 08: t_2_029.cpp(19): __has_include(X)=something

View File

@@ -0,0 +1,21 @@
/*=============================================================================
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)
=============================================================================*/
// Check for malformed computed includes
//O --c++17
//O -Werror
// macro that does *not* evaluate to a quoted or bracketed string
#define FOO BAR
#if __has_include(FOO)
#warning for some reason has_include likes this non-file-looking macro
#endif
//E t_2_030.cpp(17): error: ill formed __has_include expression: BAR

View File

@@ -75,6 +75,14 @@ t_2_019.cpp
t_2_020.cpp
t_2_021.cpp
t_2_022.cpp
t_2_023.cpp
t_2_024.cpp
t_2_025.cpp
t_2_026.cpp
t_2_027.cpp
t_2_028.cpp
t_2_029.cpp
t_2_030.cpp
#
# t_3: Predefined macros

View File

@@ -419,8 +419,11 @@ testwave_app::testwave_app(po::variables_map const& vm)
#if BOOST_WAVE_SUPPORT_CPP0X != 0
("c++11", "enable C++11 mode (implies --variadics and --long_long)")
#endif
#if BOOST_WAVE_SUPPORT_CPP1Z != 0
("c++17", "enable C++17 mode (implies --variadics and --long_long, adds __has_include)")
#endif
#if BOOST_WAVE_SUPPORT_CPP2A != 0
("c++20", "enable C++20 mode (implies --variadics and --long_long, adds __VA_OPT__)")
("c++20", "enable C++20 mode (implies --variadics and --long_long, adds __has_include and __VA_OPT__)")
#endif
("warning,W", po::value<std::vector<std::string> >()->composing(),
"Warning settings.")
@@ -995,12 +998,44 @@ testwave_app::initialise_options(Context& ctx, po::variables_map const& vm,
}
#endif
#if BOOST_WAVE_SUPPORT_CPP1Z
if (vm.count("c++17")) {
ctx.set_language(
boost::wave::language_support(
boost::wave::support_cpp1z
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
| boost::wave::support_option_has_include
#endif
| 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
));
} else {
if (9 == debuglevel) {
std::cerr << "initialise_options: option: c++17" << std::endl;
}
}
#endif
#if BOOST_WAVE_SUPPORT_CPP2A
if (vm.count("c++20")) {
ctx.set_language(
boost::wave::language_support(
boost::wave::support_cpp2a
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
| boost::wave::support_option_has_include
#endif
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
| boost::wave::support_option_va_opt
#endif
| boost::wave::support_option_convert_trigraphs
| boost::wave::support_option_long_long
| boost::wave::support_option_emit_line_directives

View File

@@ -80,6 +80,7 @@ typedef boost::archive::text_oarchive oarchive;
#include <boost/wave/grammars/cpp_expression_grammar.hpp>
#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
#include <boost/wave/grammars/cpp_has_include_grammar.hpp>
#endif
///////////////////////////////////////////////////////////////////////////////
@@ -899,12 +900,39 @@ const bool treat_warnings_as_error = vm.count("warning") &&
}
#endif // BOOST_WAVE_SUPPORT_CPP0X != 0
#if BOOST_WAVE_SUPPORT_CPP1Z != 0
if (vm.count("c++17")) {
ctx.set_language(
boost::wave::language_support(
boost::wave::support_cpp1z
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
| boost::wave::support_option_has_include
#endif
| 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_CPP1Z
#if BOOST_WAVE_SUPPORT_CPP2A != 0
if (vm.count("c++20")) {
ctx.set_language(
boost::wave::language_support(
boost::wave::support_cpp2a
#if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
| boost::wave::support_option_has_include
#endif
#if BOOST_WAVE_SUPPORT_VA_OPT != 0
| boost::wave::support_option_va_opt
#endif
| boost::wave::support_option_convert_trigraphs
| boost::wave::support_option_long_long
| boost::wave::support_option_emit_line_directives
@@ -1352,6 +1380,9 @@ main (int argc, char *argv[])
#if BOOST_WAVE_SUPPORT_CPP0X != 0
("c++11", "enable C++11 mode (implies --variadics and --long_long)")
#endif
#if BOOST_WAVE_SUPPORT_CPP1Z != 0
("c++17", "enable C++17 mode (implies --variadics and --long_long, adds __has_include)")
#endif
#if BOOST_WAVE_SUPPORT_CPP2A != 0
("c++20", "enable C++20 mode (implies --variadics and --long_long, adds __VA_OPT__)")
#endif