Serialize clang_parseTranslationUnit2FullArgv requests.

Also try to emit diagnostics when translation unit creation fails.
This commit is contained in:
Jacob Dufault 2017-11-29 19:52:55 -08:00
parent 29185c2fe3
commit f1f2cc3bd1

View File

@ -1,5 +1,6 @@
#include "clang_translation_unit.h" #include "clang_translation_unit.h"
#include "clang_utils.h"
#include "platform.h" #include "platform.h"
#include "utils.h" #include "utils.h"
@ -8,8 +9,65 @@
#include <cassert> #include <cassert>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <mutex>
#include <sstream> #include <sstream>
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 // static
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create( std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
ClangIndex* index, ClangIndex* index,
@ -26,9 +84,16 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
args.push_back(arg.c_str()); args.push_back(arg.c_str());
CXTranslationUnit cx_tu; CXTranslationUnit cx_tu;
CXErrorCode error_code = clang_parseTranslationUnit2FullArgv( CXErrorCode error_code;
index->cx_index, filepath.c_str(), args.data(), (int)args.size(), {
unsaved_files.data(), (unsigned)unsaved_files.size(), flags, &cx_tu); std::lock_guard<std::mutex> 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) { switch (error_code) {
case CXError_Success: case CXError_Success:
@ -58,9 +123,17 @@ std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Reparse( std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Reparse(
std::unique_ptr<ClangTranslationUnit> tu, std::unique_ptr<ClangTranslationUnit> tu,
std::vector<CXUnsavedFile>& unsaved) { std::vector<CXUnsavedFile>& unsaved) {
int error_code = clang_reparseTranslationUnit( int error_code;
tu->cx_tu, (unsigned)unsaved.size(), unsaved.data(), {
clang_defaultReparseOptions(tu->cx_tu)); std::lock_guard<std::mutex> 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("<unknown>", tu->cx_tu);
switch (error_code) { switch (error_code) {
case CXError_Success: case CXError_Success:
return tu; return tu;