2018-05-28 00:50:02 +00:00
|
|
|
#include "clang_tu.h"
|
2017-11-11 19:31:05 +00:00
|
|
|
|
|
|
|
#include "clang_utils.h"
|
2018-05-28 00:50:02 +00:00
|
|
|
#include "log.hh"
|
|
|
|
#include "platform.h"
|
|
|
|
#include "utils.h"
|
2018-07-14 23:02:59 +00:00
|
|
|
#include "working_files.h"
|
|
|
|
|
|
|
|
#include <llvm/Support/CrashRecoveryContext.h>
|
|
|
|
using namespace clang;
|
2017-11-11 19:31:05 +00:00
|
|
|
|
2018-03-31 05:05:21 +00:00
|
|
|
#include <assert.h>
|
|
|
|
#include <mutex>
|
2017-11-11 19:31:05 +00:00
|
|
|
|
2018-07-29 04:32:41 +00:00
|
|
|
Range FromCharSourceRange(const SourceManager &SM, const LangOptions &LangOpts,
|
|
|
|
CharSourceRange R,
|
|
|
|
llvm::sys::fs::UniqueID *UniqueID) {
|
2018-07-14 23:02:59 +00:00
|
|
|
SourceLocation BLoc = R.getBegin(), ELoc = R.getEnd();
|
|
|
|
std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
|
|
|
|
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
|
2018-07-29 04:32:41 +00:00
|
|
|
if (R.isTokenRange())
|
2018-07-14 23:02:59 +00:00
|
|
|
EInfo.second += Lexer::MeasureTokenLength(ELoc, SM, LangOpts);
|
|
|
|
unsigned l0 = SM.getLineNumber(BInfo.first, BInfo.second) - 1,
|
|
|
|
c0 = SM.getColumnNumber(BInfo.first, BInfo.second) - 1,
|
|
|
|
l1 = SM.getLineNumber(EInfo.first, EInfo.second) - 1,
|
|
|
|
c1 = SM.getColumnNumber(EInfo.first, EInfo.second) - 1;
|
|
|
|
if (l0 > INT16_MAX)
|
|
|
|
l0 = 0;
|
|
|
|
if (c0 > INT16_MAX)
|
|
|
|
c0 = 0;
|
|
|
|
if (l1 > INT16_MAX)
|
|
|
|
l1 = 0;
|
|
|
|
if (c1 > INT16_MAX)
|
|
|
|
c1 = 0;
|
|
|
|
if (UniqueID) {
|
|
|
|
if (const FileEntry *F = SM.getFileEntryForID(BInfo.first))
|
|
|
|
*UniqueID = F->getUniqueID();
|
|
|
|
else
|
|
|
|
*UniqueID = llvm::sys::fs::UniqueID(0, 0);
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
2018-07-14 23:02:59 +00:00
|
|
|
return {{int16_t(l0), int16_t(c0)}, {int16_t(l1), int16_t(c1)}};
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
2018-03-31 05:05:21 +00:00
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
Range FromCharRange(const SourceManager &SM, const LangOptions &LangOpts,
|
2018-07-29 04:32:41 +00:00
|
|
|
SourceRange R, llvm::sys::fs::UniqueID *UniqueID) {
|
|
|
|
return FromCharSourceRange(SM, LangOpts, CharSourceRange::getCharRange(R),
|
|
|
|
UniqueID);
|
2018-03-31 05:05:21 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts,
|
2018-07-29 04:32:41 +00:00
|
|
|
SourceRange R, llvm::sys::fs::UniqueID *UniqueID) {
|
|
|
|
return FromCharSourceRange(SM, LangOpts, CharSourceRange::getTokenRange(R),
|
|
|
|
UniqueID);
|
2018-03-31 05:05:21 +00:00
|
|
|
}
|
2018-05-28 00:50:02 +00:00
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
std::vector<ASTUnit::RemappedFile>
|
|
|
|
GetRemapped(const WorkingFiles::Snapshot &snapshot) {
|
|
|
|
std::vector<ASTUnit::RemappedFile> Remapped;
|
|
|
|
for (auto &file : snapshot.files) {
|
|
|
|
std::unique_ptr<llvm::MemoryBuffer> MB =
|
|
|
|
llvm::MemoryBuffer::getMemBufferCopy(file.content, file.filename);
|
|
|
|
Remapped.emplace_back(file.filename, MB.release());
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
2018-07-14 23:02:59 +00:00
|
|
|
return Remapped;
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
|
|
|
|
2018-07-15 17:10:24 +00:00
|
|
|
std::unique_ptr<ClangTranslationUnit> ClangTranslationUnit::Create(
|
|
|
|
const std::string &filepath, const std::vector<std::string> &args,
|
|
|
|
const WorkingFiles::Snapshot &snapshot, bool diagnostic) {
|
2018-07-14 23:02:59 +00:00
|
|
|
std::vector<const char *> Args;
|
2018-08-09 17:08:14 +00:00
|
|
|
for (auto &arg : args)
|
2018-07-14 23:02:59 +00:00
|
|
|
Args.push_back(arg.c_str());
|
2018-07-15 17:10:24 +00:00
|
|
|
Args.push_back("-fallow-editor-placeholders");
|
2018-07-29 04:32:41 +00:00
|
|
|
if (!diagnostic)
|
|
|
|
Args.push_back("-fno-spell-checking");
|
2018-07-14 23:02:59 +00:00
|
|
|
|
|
|
|
auto ret = std::make_unique<ClangTranslationUnit>();
|
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
|
|
|
|
CompilerInstance::createDiagnostics(new DiagnosticOptions));
|
|
|
|
std::vector<ASTUnit::RemappedFile> Remapped = GetRemapped(snapshot);
|
|
|
|
|
|
|
|
ret->PCHCO = std::make_shared<PCHContainerOperations>();
|
|
|
|
std::unique_ptr<ASTUnit> ErrUnit, Unit;
|
|
|
|
llvm::CrashRecoveryContext CRC;
|
|
|
|
auto parse = [&]() {
|
|
|
|
Unit.reset(ASTUnit::LoadFromCommandLine(
|
|
|
|
Args.data(), Args.data() + Args.size(),
|
|
|
|
/*PCHContainerOpts=*/ret->PCHCO, Diags,
|
2018-07-27 03:08:22 +00:00
|
|
|
/*ResourceFilePath=*/g_config->clang.resourceDir,
|
|
|
|
/*OnlyLocalDecls=*/false,
|
2018-07-15 17:10:24 +00:00
|
|
|
/*CaptureDiagnostics=*/diagnostic, Remapped,
|
|
|
|
/*RemappedFilesKeepOriginalName=*/true, 1,
|
|
|
|
diagnostic ? TU_Complete : TU_Prefix,
|
|
|
|
/*CacheCodeCompletionResults=*/true, g_config->index.comments,
|
2018-07-15 07:57:48 +00:00
|
|
|
/*AllowPCHWithCompilerErrors=*/true,
|
|
|
|
#if LLVM_VERSION_MAJOR >= 7
|
|
|
|
SkipFunctionBodiesScope::None,
|
|
|
|
#else
|
|
|
|
false,
|
|
|
|
#endif
|
2018-07-14 23:02:59 +00:00
|
|
|
/*SingleFileParse=*/false,
|
|
|
|
/*UserFilesAreVolatile=*/true, false,
|
|
|
|
ret->PCHCO->getRawReader().getFormat(), &ErrUnit));
|
|
|
|
};
|
2018-07-16 05:49:32 +00:00
|
|
|
if (!CRC.RunSafely(parse)) {
|
2018-08-09 17:08:14 +00:00
|
|
|
LOG_S(ERROR) << "clang crashed for " << filepath << "\n"
|
|
|
|
<< StringJoin(args, " ") + " -fsyntax-only";
|
2018-07-14 23:02:59 +00:00
|
|
|
return {};
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
2018-07-14 23:02:59 +00:00
|
|
|
if (!Unit && !ErrUnit)
|
|
|
|
return {};
|
2018-05-28 00:50:02 +00:00
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
ret->Unit = std::move(Unit);
|
|
|
|
return ret;
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
int ClangTranslationUnit::Reparse(llvm::CrashRecoveryContext &CRC,
|
|
|
|
const WorkingFiles::Snapshot &snapshot) {
|
|
|
|
int ret = 1;
|
2018-07-16 05:49:32 +00:00
|
|
|
(void)CRC.RunSafely(
|
|
|
|
[&]() { ret = Unit->Reparse(PCHCO, GetRemapped(snapshot)); });
|
2018-07-14 23:02:59 +00:00
|
|
|
return ret;
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|