diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index dfaa0127e..432d12203 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -327,10 +327,12 @@ class pp_iterator_functor { void on_define(parse_node_type const &node); void on_undefine(lexer_type const &it); - void on_ifdef(result_type const& found_directive, lexer_type const &it); -// typename parse_tree_type::const_iterator const &end); - void on_ifndef(result_type const& found_directive, lexer_type const& it); -// typename parse_tree_type::const_iterator const &end); + void on_ifdef(result_type const& found_directive, + typename parse_tree_type::const_iterator const &begin, + typename parse_tree_type::const_iterator const &end); + void on_ifndef(result_type const& found_directive, + typename parse_tree_type::const_iterator const &begin, + typename parse_tree_type::const_iterator const &end); void on_else(); void on_endif(); void on_illformed(typename result_type::string_type s); @@ -946,7 +948,7 @@ namespace impl { util::impl::call_skipped_token_hook(ctx, *it); for (++it; it != end; ++it) { - token_id id = token_id(*it); + token_id id = token_id(*it); if (T_CPPCOMMENT == id || T_NEWLINE == id || context_policies::util::ccomment_has_newline(*it)) @@ -1045,8 +1047,7 @@ pp_iterator_functor::ensure_is_last_on_line(IteratorT& it, bool call_h // enable error recovery (start over with the next line) impl::skip_to_eol(ctx, it, iter_ctx->last); - string_type str(util::impl::as_string( - iter_ctx->first, it)); + string_type str(util::impl::as_string(iter_ctx->first, it)); seen_newline = true; iter_ctx->first = it; @@ -1254,24 +1255,6 @@ pp_iterator_functor::handle_pp_directive(IteratorT &it) call_hook_in_skip = false; break; - case T_PP_IFDEF: // #ifdef - if (!impl::call_found_directive_hook(ctx, *it) && - extract_identifier(it)) - { - on_ifdef(directive, it); - } - call_hook_in_skip = false; - break; - - case T_PP_IFNDEF: // #ifndef - if (!impl::call_found_directive_hook(ctx, *it) && - extract_identifier(it)) - { - on_ifndef(directive, it); - } - call_hook_in_skip = false; - break; - #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 // case T_MSEXT_PP_REGION: // #region ... // break; @@ -1466,13 +1449,13 @@ pp_iterator_functor::dispatch_directive( // on_undefine(*nodeval.begin()); // break; // -// case T_PP_IFDEF: // #ifdef -// on_ifdef(found_directive, begin_child_it, end_child_it); -// break; -// -// case T_PP_IFNDEF: // #ifndef -// on_ifndef(found_directive, begin_child_it, end_child_it); -// break; + case T_PP_IFDEF: // #ifdef + on_ifdef(found_directive, begin_child_it, end_child_it); + break; + + case T_PP_IFNDEF: // #ifndef + on_ifndef(found_directive, begin_child_it, end_child_it); + break; case T_PP_IF: // #if on_if(found_directive, begin_child_it, end_child_it); @@ -1860,26 +1843,23 @@ pp_iterator_functor::on_undefine (lexer_type const &it) template inline void pp_iterator_functor::on_ifdef( - result_type const& found_directive, lexer_type const &it) -// typename parse_tree_type::const_iterator const &it) -// typename parse_tree_type::const_iterator const &end) + result_type const& found_directive, + typename parse_tree_type::const_iterator const &begin, + typename parse_tree_type::const_iterator const &end) { - // get_token_value get_value; - // token_sequence_type toexpand; - // - // std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value), - // make_ref_transform_iterator((*begin).children.end(), get_value), - // std::inserter(toexpand, toexpand.end())); + get_token_value get_value; + token_sequence_type toexpand; - bool is_defined = false; - token_sequence_type directive; + std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value), + make_ref_transform_iterator((*begin).children.end(), get_value), + std::inserter(toexpand, toexpand.end())); - directive.insert(directive.end(), *it); + bool is_defined = false; do { - is_defined = ctx.is_defined_macro((*it).get_value()); // toexpand.begin(), toexpand.end()); + is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end()); } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(), - found_directive, directive, is_defined)); + found_directive, toexpand, is_defined)); ctx.enter_if_block(is_defined); } @@ -1891,26 +1871,23 @@ pp_iterator_functor::on_ifdef( template inline void pp_iterator_functor::on_ifndef( - result_type const& found_directive, lexer_type const &it) -// typename parse_tree_type::const_iterator const &it) -// typename parse_tree_type::const_iterator const &end) + result_type const& found_directive, + typename parse_tree_type::const_iterator const &begin, + typename parse_tree_type::const_iterator const &end) { - // get_token_value get_value; - // token_sequence_type toexpand; - // - // std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value), - // make_ref_transform_iterator((*begin).children.end(), get_value), - // std::inserter(toexpand, toexpand.end())); + get_token_value get_value; + token_sequence_type toexpand; - bool is_defined = false; - token_sequence_type directive; + std::copy(make_ref_transform_iterator((*begin).children.begin(), get_value), + make_ref_transform_iterator((*begin).children.end(), get_value), + std::inserter(toexpand, toexpand.end())); - directive.insert(directive.end(), *it); + bool is_defined = false; do { - is_defined = ctx.is_defined_macro((*it).get_value()); // toexpand.begin(), toexpand.end()); + is_defined = ctx.is_defined_macro(toexpand.begin(), toexpand.end()); } while (ctx.get_hooks().evaluated_conditional_expression(ctx.derived(), - found_directive, directive, is_defined)); + found_directive, toexpand, is_defined)); ctx.enter_if_block(!is_defined); } diff --git a/test/build/Jamfile.v2 b/test/build/Jamfile.v2 index 0e935bb4e..9ba2a6050 100644 --- a/test/build/Jamfile.v2 +++ b/test/build/Jamfile.v2 @@ -224,5 +224,14 @@ test-suite wave /boost/thread//boost_thread /boost/filesystem//boost_filesystem ] + + [ + run + # sources + ../testwave/default_hooks.cpp + /boost/wave//boost_wave + /boost/thread//boost_thread + /boost/filesystem//boost_filesystem + ] ; diff --git a/test/testwave/default_hooks.cpp b/test/testwave/default_hooks.cpp new file mode 100644 index 000000000..16e5678bf --- /dev/null +++ b/test/testwave/default_hooks.cpp @@ -0,0 +1,137 @@ + +// Copyright 2018 Peter Dimov. +// Copyrigth 2022 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 + +// Most test coverage of Wave happens with the "eat_whitespace" hooks in effect +// This adds some coverage for Wave with the (minimal) default hooks + +#include +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + std::string input( + // check LINE directives after conditional (false) sections + "#if 0\n" + "int aa;\n" + "#endif\n" + "char c1;\n" // #LINE 4 + + "#ifdef FOO\n" + "int bb;\n" + "#endif\n" + "char c2;\n" // #LINE 8 + + "#ifndef __FILE__\n" + "int cc;\n" + "#endif\n" + "char c3;\n" // #LINE 12 + ); + + using namespace boost::wave; + + typedef std::pair tokdata_type; + typedef std::vector tokdata_list_type; + tokdata_list_type expected{ + {T_PP_LINE, "#line"}, + {T_SPACE, " "}, + {T_INTLIT, "4"}, + {T_SPACE, " "}, + {T_STRINGLIT, nullptr}, // exact filepath is not interesting + {T_NEWLINE, "\n"}, + {T_CHAR, "char"}, + {T_SPACE, " "}, + {T_IDENTIFIER, "c1"}, + {T_SEMICOLON, ";"}, + {T_NEWLINE, "\n"}, + + {T_PP_LINE, "#line"}, + {T_SPACE, " "}, + {T_INTLIT, "8"}, + {T_SPACE, " "}, + {T_STRINGLIT, nullptr}, + {T_NEWLINE, "\n"}, + {T_CHAR, "char"}, + {T_SPACE, " "}, + {T_IDENTIFIER, "c2"}, + {T_SEMICOLON, ";"}, + {T_NEWLINE, "\n"}, + + {T_PP_LINE, "#line"}, + {T_SPACE, " "}, + {T_INTLIT, "12"}, + {T_SPACE, " "}, + {T_STRINGLIT, nullptr}, + {T_NEWLINE, "\n"}, + {T_CHAR, "char"}, + {T_SPACE, " "}, + {T_IDENTIFIER, "c3"}, + {T_SEMICOLON, ";"}, + {T_NEWLINE, "\n"}, + + {T_EOF, nullptr} +}; + + try + { + typedef cpplexer::lex_token<> token_type; + typedef cpplexer::lex_iterator lex_iterator_type; + typedef context context_type; + + context_type ctx( input.begin(), input.end(), "input.cpp" ); + + tokdata_list_type::const_iterator first_expect = expected.begin(); + tokdata_list_type::const_iterator last_expect = expected.end(); + for( context_type::iterator_type first = ctx.begin(), last = ctx.end(); first != last; ++first, ++first_expect ) + { + if (first_expect == last_expect) + { + std::cerr << "more tokens were produced than expected\n"; + return 3; + } + + if (token_id(*first) != first_expect->first) + { + std::cerr << "expected " << get_token_name(first_expect->first) << ", got " << get_token_name(token_id(*first)) << "\n"; + return 3; + } + + if ((first_expect->second != nullptr) && (first_expect->second != first->get_value())) + { + std::cerr << "expected token value " << first_expect->second << ", got " << first->get_value() << "\n"; + return 3; + } + + std::cout << first->get_value(); + } + + if (first_expect != last_expect) + { + std::cerr << "fewer tokens were produced than expected\n"; + return 3; + } + + return 0; + } + catch( cpp_exception const & x ) + { + std::cerr << x.file_name() << "(" << x.line_no() << "): " << x.description() << std::endl; + return 1; + } + catch( std::exception const & x ) + { + std::cerr << "Exception: " << x.what() << std::endl; + return 2; + } +}