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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 37 additions & 60 deletions include/boost/wave/util/cpp_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -1045,8 +1047,7 @@ pp_iterator_functor<ContextT>::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<string_type>(
iter_ctx->first, it));
string_type str(util::impl::as_string<string_type>(iter_ctx->first, it));

seen_newline = true;
iter_ctx->first = it;
Expand Down Expand Up @@ -1254,24 +1255,6 @@ pp_iterator_functor<ContextT>::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;
Expand Down Expand Up @@ -1466,13 +1449,13 @@ pp_iterator_functor<ContextT>::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);
Expand Down Expand Up @@ -1860,26 +1843,23 @@ pp_iterator_functor<ContextT>::on_undefine (lexer_type const &it)
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::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<result_type, parse_node_type> 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<result_type, parse_node_type> 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);
}

Expand All @@ -1891,26 +1871,23 @@ pp_iterator_functor<ContextT>::on_ifdef(
template <typename ContextT>
inline void
pp_iterator_functor<ContextT>::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<result_type, parse_node_type> 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<result_type, parse_node_type> 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);
}

Expand Down
9 changes: 9 additions & 0 deletions test/build/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -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
]
;

137 changes: 137 additions & 0 deletions test/testwave/default_hooks.cpp
Original file line number Diff line number Diff line change
@@ -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 <boost/wave.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
#include <iostream>
#include <vector>
#include <utility>
#include <string>

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<token_id, char const*> tokdata_type;
typedef std::vector<tokdata_type> 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<token_type> lex_iterator_type;
typedef context<std::string::iterator, lex_iterator_type> 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;
}
}