From b28fff6c371089223598b13f1276db224f085bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Tue, 10 Oct 2017 21:13:29 +0200 Subject: [PATCH] Fix preprocessor line numbers if includes aren't supported --- src/libclang/libclang_parser.cpp | 26 ++++++++++++++------------ src/libclang/preprocessor.cpp | 20 ++++++++++++++++---- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/libclang/libclang_parser.cpp b/src/libclang/libclang_parser.cpp index 996b8ec..12b602a 100644 --- a/src/libclang/libclang_parser.cpp +++ b/src/libclang/libclang_parser.cpp @@ -403,9 +403,8 @@ namespace auto args = get_arguments(config); CXTranslationUnit tu; - auto flags = CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing; - if (detail::libclang_compile_config_access::clang_version(config) >= 40000) - flags |= CXTranslationUnit_DetailedPreprocessingRecord; + auto flags = CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing + | CXTranslationUnit_DetailedPreprocessingRecord; auto error = clang_parseTranslationUnit2(idx.get(), path, // index and path @@ -479,17 +478,20 @@ std::unique_ptr libclang_parser::do_parse(const cpp_entity_index& idx, detail::visit_tu(tu, path.c_str(), [&](const CXCursor& cur) { if (clang_getCursorKind(cur) == CXCursor_InclusionDirective) { - DEBUG_ASSERT(include_iter != preprocessed.includes.end() - && get_line_no(cur) >= include_iter->line, - detail::assert_handler{}); + if (!preprocessed.includes.empty()) + { + DEBUG_ASSERT(include_iter != preprocessed.includes.end() + && get_line_no(cur) >= include_iter->line, + detail::assert_handler{}); - auto include = - cpp_include_directive::build(std::move(include_iter->file), include_iter->kind, - detail::get_cursor_name(cur).c_str()); - context.comments.match(*include, include_iter->line); - builder.add_child(std::move(include)); + auto include = + cpp_include_directive::build(std::move(include_iter->file), include_iter->kind, + detail::get_cursor_name(cur).c_str()); + context.comments.match(*include, include_iter->line); + builder.add_child(std::move(include)); - ++include_iter; + ++include_iter; + } } else if (clang_getCursorKind(cur) != CXCursor_MacroDefinition) { diff --git a/src/libclang/preprocessor.cpp b/src/libclang/preprocessor.cpp index aa75277..c6802fd 100644 --- a/src/libclang/preprocessor.cpp +++ b/src/libclang/preprocessor.cpp @@ -30,6 +30,11 @@ namespace return '"' + std::move(str) + '"'; } + bool support_include(const libclang_compile_config& c) + { + return detail::libclang_compile_config_access::clang_version(c) >= 40000; + } + // build the command that runs the preprocessor std::string get_command(const libclang_compile_config& c, const char* full_path) { @@ -39,7 +44,7 @@ namespace // -C: keep comments // -dD: print macro definitions as well auto flags = std::string("-x c++ -I. -E -C -dD"); - if (detail::libclang_compile_config_access::clang_version(c) >= 40000) + if (support_include(c)) // -Xclang -dI: print include directives as well (clang >= 4.0.0) flags += " -Xclang -dI"; // -fno-caret-diagnostics: don't show the source extract in diagnostics @@ -784,9 +789,16 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co if (file_depth == 0u) { DEBUG_ASSERT(lm.value().file == path, detail::assert_handler{}); - // difference is 1 if coming from an included file (because newline of include is already written) - // difference is 0 if coming from a builtin file (because no include has been written) - DEBUG_ASSERT(p.cur_line() - lm.value().line <= 1u, detail::assert_handler{}); + + if (lm.value().line > p.cur_line()) + // might happen in weird cases + p.write_str(std::string(lm.value().line - p.cur_line(), '\n')); + else + // difference is 1 if coming from an included file (because newline of include is already written) + // difference is 0 if coming from a builtin file (because no include has been written) + DEBUG_ASSERT(p.cur_line() - lm.value().line <= 1u, + detail::assert_handler{}); + p.enable_write(); } break;