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-14 23:02:59 +00:00
|
|
|
Range FromSourceRange(const SourceManager &SM, const LangOptions &LangOpts,
|
|
|
|
SourceRange R, llvm::sys::fs::UniqueID *UniqueID,
|
|
|
|
bool token) {
|
|
|
|
SourceLocation BLoc = R.getBegin(), ELoc = R.getEnd();
|
|
|
|
std::pair<FileID, unsigned> BInfo = SM.getDecomposedLoc(BLoc);
|
|
|
|
std::pair<FileID, unsigned> EInfo = SM.getDecomposedLoc(ELoc);
|
|
|
|
if (token)
|
|
|
|
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,
|
|
|
|
SourceRange R,
|
|
|
|
llvm::sys::fs::UniqueID *UniqueID) {
|
|
|
|
return FromSourceRange(SM, LangOpts, R, UniqueID, false);
|
2018-03-31 05:05:21 +00:00
|
|
|
}
|
|
|
|
|
2018-07-14 23:02:59 +00:00
|
|
|
Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts,
|
|
|
|
SourceRange R,
|
|
|
|
llvm::sys::fs::UniqueID *UniqueID) {
|
|
|
|
return FromSourceRange(SM, LangOpts, R, UniqueID, true);
|
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-14 23:02:59 +00:00
|
|
|
std::unique_ptr<ClangTranslationUnit>
|
|
|
|
ClangTranslationUnit::Create(const std::string &filepath,
|
|
|
|
const std::vector<std::string> &args,
|
|
|
|
const WorkingFiles::Snapshot &snapshot) {
|
|
|
|
std::vector<const char *> Args;
|
|
|
|
for (auto& arg : args)
|
|
|
|
Args.push_back(arg.c_str());
|
|
|
|
Args.push_back("-fno-spell-checking");
|
|
|
|
|
|
|
|
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,
|
|
|
|
/*ResourceFilePath=*/"", /*OnlyLocalDecls=*/false,
|
|
|
|
/*CaptureDiagnostics=*/true, Remapped,
|
|
|
|
/*RemappedFilesKeepOriginalName=*/true, 1, TU_Prefix,
|
|
|
|
/*CacheCodeCompletionResults=*/true, true,
|
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));
|
|
|
|
};
|
|
|
|
if (!RunSafely(CRC, parse)) {
|
|
|
|
LOG_S(ERROR)
|
|
|
|
<< "clang crashed for " << filepath << "\n"
|
|
|
|
<< StringJoin(args, " ") + " -fsyntax-only";
|
|
|
|
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;
|
|
|
|
auto parse = [&]() { ret = Unit->Reparse(PCHCO, GetRemapped(snapshot)); };
|
|
|
|
(void)RunSafely(CRC, parse);
|
|
|
|
return ret;
|
2018-05-28 00:50:02 +00:00
|
|
|
}
|