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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 _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,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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
216
include/boost/wave/grammars/cpp_has_include_grammar.hpp
Normal file
216
include/boost/wave/grammars/cpp_has_include_grammar.hpp
Normal 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)
|
||||
87
include/boost/wave/grammars/cpp_has_include_grammar_gen.hpp
Normal file
87
include/boost/wave/grammars/cpp_has_include_grammar_gen.hpp
Normal 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)
|
||||
@@ -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
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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 ¯odef, 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 ¶meters, 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 ¯o_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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -14,6 +14,7 @@ SOURCES =
|
||||
../instantiate_cpp_grammar
|
||||
../instantiate_cpp_literalgrs
|
||||
../instantiate_defined_grammar
|
||||
../instantiate_has_include_grammar
|
||||
../instantiate_slex_lexer
|
||||
;
|
||||
|
||||
|
||||
39
samples/cpp_tokens/instantiate_has_include_grammar.cpp
Normal file
39
samples/cpp_tokens/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
@@ -14,6 +14,7 @@ SOURCES =
|
||||
../instantiate_cpp_grammar
|
||||
../instantiate_cpp_literalgrs
|
||||
../instantiate_defined_grammar
|
||||
../instantiate_has_include_grammar
|
||||
../instantiate_lexertl_lexer
|
||||
;
|
||||
|
||||
|
||||
41
samples/list_includes/instantiate_has_include_grammar.cpp
Normal file
41
samples/list_includes/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
39
samples/real_positions/instantiate_has_include_grammar.cpp
Normal file
39
samples/real_positions/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
@@ -13,6 +13,7 @@ SOURCES =
|
||||
../instantiate_xlex_lexer
|
||||
../instantiate_cpp_grammar
|
||||
../instantiate_defined_grammar
|
||||
../instantiate_has_include_grammar
|
||||
;
|
||||
|
||||
exe token_statistics
|
||||
|
||||
42
samples/token_statistics/instantiate_has_include_grammar.cpp
Normal file
42
samples/token_statistics/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
42
samples/waveidl/instantiate_has_include_grammar.cpp
Normal file
42
samples/waveidl/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
52
src/instantiate_has_include_grammar.cpp
Normal file
52
src/instantiate_has_include_grammar.cpp
Normal 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
|
||||
|
||||
72
test/testwave/testfiles/t_2_023.cpp
Normal file
72
test/testwave/testfiles/t_2_023.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++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
|
||||
|
||||
|
||||
95
test/testwave/testfiles/t_2_024.cpp
Normal file
95
test/testwave/testfiles/t_2_024.cpp
Normal 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
|
||||
|
||||
76
test/testwave/testfiles/t_2_025.cpp
Normal file
76
test/testwave/testfiles/t_2_025.cpp
Normal 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
|
||||
30
test/testwave/testfiles/t_2_026.cpp
Normal file
30
test/testwave/testfiles/t_2_026.cpp
Normal 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
|
||||
|
||||
|
||||
16
test/testwave/testfiles/t_2_027.cpp
Normal file
16
test/testwave/testfiles/t_2_027.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)
|
||||
=============================================================================*/
|
||||
|
||||
// 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
|
||||
16
test/testwave/testfiles/t_2_028.cpp
Normal file
16
test/testwave/testfiles/t_2_028.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)
|
||||
=============================================================================*/
|
||||
|
||||
// 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
|
||||
25
test/testwave/testfiles/t_2_029.cpp
Normal file
25
test/testwave/testfiles/t_2_029.cpp
Normal 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
|
||||
|
||||
21
test/testwave/testfiles/t_2_030.cpp
Normal file
21
test/testwave/testfiles/t_2_030.cpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
31
tool/cpp.cpp
31
tool/cpp.cpp
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user