From ca2fae08a2c50c9759433b5abb1345fc78dcfc55 Mon Sep 17 00:00:00 2001 From: Zsolt Erhardt Date: Mon, 22 Jan 2018 11:18:38 +0100 Subject: [PATCH] Bugfix/escaped character parsing (#32) So as it turns out there's a nasty little piece of code in rapidjson's source which breaks the preprocessor and will leave things a little bit weird. The test "preprocessor_parses_escaped_character" should prove its validity. --- src/libclang/preprocessor.cpp | 10 +++++----- test/CMakeLists.txt | 2 ++ test/preprocessor.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 test/preprocessor.cpp diff --git a/src/libclang/preprocessor.cpp b/src/libclang/preprocessor.cpp index e3036f3..d05c739 100644 --- a/src/libclang/preprocessor.cpp +++ b/src/libclang/preprocessor.cpp @@ -740,11 +740,7 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co if (next && next > p.ptr()) p.bump(std::size_t(next - p.ptr() - 1)); // subtract one to get before that character - if (starts_with(p, "\\\"")) // starts with \" - p.bump(2u); - else if (starts_with(p, "\\'")) // starts with \' - p.bump(2u); - else if (in_char == false && starts_with(p, "\"")) // starts with " + if (in_char == false && starts_with(p, "\"")) // starts with " { p.bump(); in_string.toggle(); @@ -756,6 +752,10 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co } else if (in_string == true || in_char == true) p.bump(); + else if (starts_with(p, "\\\"")) // starts with \" + p.bump(2u); + else if (starts_with(p, "\\'")) // starts with \' + p.bump(2u); else if (auto macro = parse_macro(p, result, file_depth == 0u)) { if (logger.is_verbose()) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 281a4b1..9858f97 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -31,10 +31,12 @@ set(tests integration.cpp libclang_parser.cpp parser.cpp + preprocessor.cpp visitor.cpp) add_executable(cppast_test test.cpp test_parser.hpp ${tests}) target_include_directories(cppast_test PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(cppast_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../src) target_link_libraries(cppast_test PUBLIC cppast) set_target_properties(cppast_test PROPERTIES CXX_STANDARD 11) diff --git a/test/preprocessor.cpp b/test/preprocessor.cpp new file mode 100644 index 0000000..28b870f --- /dev/null +++ b/test/preprocessor.cpp @@ -0,0 +1,34 @@ +#include +#include + +#include "libclang/preprocessor.hpp" +#include "test_parser.hpp" + +using namespace cppast; + +TEST_CASE("preprocessor_parses_escaped_character", "[!hide][clang4]") +{ + write_file("ppec.hpp", R"( +)"); + // This is an actual macro from the rapidjson source (reader.h) + write_file("ppec.cpp", R"( +#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + static const char escape[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/', + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, + 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0, + 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; +#undef Z16 + +#include "ppec.hpp" +)"); + + libclang_compile_config config; + config.set_flags(cpp_standard::cpp_latest); + + auto&& preprocessed = detail::preprocess(config, "ppec.cpp", default_logger().get()); + REQUIRE(preprocessed.includes.size() == 1); + REQUIRE(preprocessed.includes[0].file_name == "ppec.hpp"); +}