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:
wave/include/boost/wave/util/cpp_macromap.hpp
Lines 1789 to 1797 in b8cbd86
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;
}
jefftrull commented
@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!