From f1f2cc3bd1c7f10c19ee457ed2038b2022e86d6a Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Wed, 29 Nov 2017 19:52:55 -0800 Subject: [PATCH] Serialize clang_parseTranslationUnit2FullArgv requests. Also try to emit diagnostics when translation unit creation fails. --- src/clang_translation_unit.cc | 85 ++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/src/clang_translation_unit.cc b/src/clang_translation_unit.cc index d86fc266..39f84ae5 100644 --- a/src/clang_translation_unit.cc +++ b/src/clang_translation_unit.cc @@ -1,5 +1,6 @@ #include "clang_translation_unit.h" +#include "clang_utils.h" #include "platform.h" #include "utils.h" @@ -8,8 +9,65 @@ #include #include #include +#include #include +namespace { + +// We need to serialize requests to clang_parseTranslationUnit2FullArgv and +// clang_reparseTranslationUnit. See +// https://github.com/jacobdufault/cquery/issues/43#issuecomment-347614504. +std::mutex g_parse_translation_unit_mutex; +std::mutex g_reparse_translation_unit_mutex; + +void EmitDiagnostics(std::string path, CXTranslationUnit tu) { + std::string output = "Fatal errors while trying to parse " + path + "\n"; + + size_t num_diagnostics = clang_getNumDiagnostics(tu); + for (unsigned i = 0; i < num_diagnostics; ++i) { + output += " - "; + + CXDiagnostic diagnostic = clang_getDiagnostic(tu, i); + + // Location. + CXFile file; + unsigned int line, column; + clang_getSpellingLocation(clang_getDiagnosticLocation(diagnostic), &file, + &line, &column, nullptr); + std::string path = FileName(file); + output += path + ":" + std::to_string(line - 1) + ":" + + std::to_string(column) + " "; + + // Severity + switch (clang_getDiagnosticSeverity(diagnostic)) { + case CXDiagnostic_Ignored: + case CXDiagnostic_Note: + output += "[info]"; + break; + case CXDiagnostic_Warning: + output += "[warning]"; + break; + case CXDiagnostic_Error: + output += "[error]"; + break; + case CXDiagnostic_Fatal: + output += "[fatal]"; + break; + } + + // Content. + output += " " + ToString(clang_getDiagnosticSpelling(diagnostic)); + + clang_disposeDiagnostic(diagnostic); + + output += "\n"; + } + + std::cerr << output; + std::cerr.flush(); +} +} // namespace + // static std::unique_ptr ClangTranslationUnit::Create( ClangIndex* index, @@ -26,9 +84,16 @@ std::unique_ptr ClangTranslationUnit::Create( args.push_back(arg.c_str()); CXTranslationUnit cx_tu; - CXErrorCode error_code = clang_parseTranslationUnit2FullArgv( - index->cx_index, filepath.c_str(), args.data(), (int)args.size(), - unsaved_files.data(), (unsigned)unsaved_files.size(), flags, &cx_tu); + CXErrorCode error_code; + { + std::lock_guard lock(g_parse_translation_unit_mutex); + error_code = clang_parseTranslationUnit2FullArgv( + index->cx_index, filepath.c_str(), args.data(), (int)args.size(), + unsaved_files.data(), (unsigned)unsaved_files.size(), flags, &cx_tu); + } + + if (error_code != CXError_Success && cx_tu) + EmitDiagnostics(filepath, cx_tu); switch (error_code) { case CXError_Success: @@ -58,9 +123,17 @@ std::unique_ptr ClangTranslationUnit::Create( std::unique_ptr ClangTranslationUnit::Reparse( std::unique_ptr tu, std::vector& unsaved) { - int error_code = clang_reparseTranslationUnit( - tu->cx_tu, (unsigned)unsaved.size(), unsaved.data(), - clang_defaultReparseOptions(tu->cx_tu)); + int error_code; + { + std::lock_guard lock(g_reparse_translation_unit_mutex); + error_code = clang_reparseTranslationUnit( + tu->cx_tu, (unsigned)unsaved.size(), unsaved.data(), + clang_defaultReparseOptions(tu->cx_tu)); + } + + if (error_code != CXError_Success && tu->cx_tu) + EmitDiagnostics("", tu->cx_tu); + switch (error_code) { case CXError_Success: return tu;