boostorg/wave

Parsing __has_include() fails with trailing tokens

r0mai opened this issue · 2 comments

r0mai commented

Lines containing a __has_include() operator will fail if any token (even whitespace) follows the __has_include() expression.

I believe the error can be traced back to this look-ahead loop, which implicitly expects the last token of the line to be the matching closing parenthesis of the __has_include expression:

// 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;
}

Repro code:

#include <string>
#include <iostream>
#include <boost/wave.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>

int main() {
#define CASE_1
#if defined(CASE_1) // BUG: any token after a __has_include expression will fail parsing
	std::string input =
		"#if __has_include(<foo.h>) && 0\n"
		"#endif\n"
		;
#elif defined(CASE_2) // BUG: even with trailing whitespace fails
	std::string input =
		"#if __has_include(<foo.h>) \n"
		"#endif\n"
		;
#elif defined(CASE_3) // GOOD: no token after __has_include succeeds
	std::string input =
		"#if __has_include(<foo.h>)\n"
		"#endif\n"
		;
#endif

	typedef boost::wave::cpplexer::lex_iterator<
			boost::wave::cpplexer::lex_token<>>
		lex_iterator_type;
	typedef boost::wave::context<
			std::string::iterator, lex_iterator_type>
		context_type;

	context_type ctx(input.begin(), input.end(), "input.cpp");
	ctx.set_language(boost::wave::language_support::support_option_has_include);

	auto first = ctx.begin();
	auto last = ctx.end();

	try {
		while (first != last) {
			std::cout << (*first).get_value();
			++first;
		}
	} catch (boost::wave::preprocess_exception& e) {
		std::cout << boost::wave::preprocess_exception::error_text(e.get_errorcode()) << std::endl;
		return 1;
	}
	std::cout << "Success" << std::endl;
	return 0;
}

@r0mai Thanks for the excellent bug report. Your analysis was correct! I believe the PR branch resolves your issue. Please let me know if not.

r0mai commented

@jefftrull I tried the PR branch, and it works perfectly. Thank you very much for the quick fix!