Adjust FrontendOpts.Inputs[0] for inferred files

This commit is contained in:
Fangrui Song 2018-12-23 21:22:51 -08:00
parent d430cb8ff9
commit 70e0eec831
7 changed files with 43 additions and 57 deletions

View File

@ -81,7 +81,7 @@ Range FromTokenRangeDefaulted(const SourceManager &SM, const LangOptions &Lang,
}
std::unique_ptr<CompilerInvocation>
BuildCompilerInvocation(std::vector<const char *> args,
BuildCompilerInvocation(const std::string &main, std::vector<const char *> args,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
std::string save = "-resource-dir=" + g_config->clang.resourceDir;
args.push_back(save.c_str());
@ -94,6 +94,9 @@ BuildCompilerInvocation(std::vector<const char *> args,
CI->getDiagnosticOpts().IgnoreWarnings = true;
CI->getFrontendOpts().DisableFree = false;
CI->getLangOpts()->SpellChecking = false;
auto &IS = CI->getFrontendOpts().Inputs;
if (IS.size())
IS[0] = FrontendInputFile(main, IS[0].getKind(), IS[0].isSystem());
}
return CI;
}

View File

@ -39,7 +39,8 @@ Range FromTokenRangeDefaulted(const clang::SourceManager &SM,
Range range);
std::unique_ptr<clang::CompilerInvocation>
BuildCompilerInvocation(std::vector<const char *> args,
BuildCompilerInvocation(const std::string &main,
std::vector<const char *> args,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS);
const char *ClangBuiltinTypeName(int);

View File

@ -1217,14 +1217,15 @@ void Init() {
std::vector<std::unique_ptr<IndexFile>>
Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
const std::string &opt_wdir, const std::string &file,
const std::string &opt_wdir, const std::string &main,
const std::vector<const char *> &args,
const std::vector<std::pair<std::string, std::string>> &remapped,
bool &ok) {
ok = true;
auto PCH = std::make_shared<PCHContainerOperations>();
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getRealFileSystem();
std::shared_ptr<CompilerInvocation> CI = BuildCompilerInvocation(args, FS);
std::shared_ptr<CompilerInvocation> CI =
BuildCompilerInvocation(main, args, FS);
// e.g. .s
if (!CI)
return {};
@ -1234,35 +1235,13 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
CI->getLangOpts()->CommentOpts.ParseAllComments =
g_config->index.comments > 1;
CI->getLangOpts()->RetainCommentsFromSystemHeaders = true;
std::string buf = wfiles->GetContent(file);
std::string buf = wfiles->GetContent(main);
std::vector<std::unique_ptr<llvm::MemoryBuffer>> Bufs;
if (buf.size()) {
// If there is a completion session, reuse its preamble if exists.
bool done_remap = false;
#if 0
std::shared_ptr<CompletionSession> session =
manager->TryGetSession(file, false, false);
if (session)
if (auto preamble = session->GetPreamble()) {
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(buf));
auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), Bufs.back().get(), 0);
if (preamble->Preamble.CanReuse(*CI, Bufs.back().get(), Bounds,
FS.get())) {
preamble->Preamble.AddImplicitPreamble(*CI, FS, Bufs.back().get());
done_remap = true;
}
}
#endif
if (buf.size())
for (auto &[filename, content] : remapped) {
if (filename == file && done_remap)
continue;
Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content));
CI->getPreprocessorOpts().addRemappedFile(
filename == file ? CI->getFrontendOpts().Inputs[0].getFile()
: StringRef(filename),
Bufs.back().get());
CI->getPreprocessorOpts().addRemappedFile(filename, Bufs.back().get());
}
}
DiagnosticConsumer DC;
auto Clang = std::make_unique<CompilerInstance>(PCH);
@ -1291,20 +1270,20 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
{
llvm::CrashRecoveryContext CRC;
auto parse = [&]() {
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
return;
if (!Action->Execute())
return;
Action->EndSourceFile();
ok = true;
};
if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0]))
return;
if (!Action->Execute())
return;
Action->EndSourceFile();
ok = true;
};
if (!CRC.RunSafely(parse)) {
LOG_S(ERROR) << "clang crashed for " << file;
LOG_S(ERROR) << "clang crashed for " << main;
return {};
}
}
if (!ok) {
LOG_S(ERROR) << "failed to index " << file;
LOG_S(ERROR) << "failed to index " << main;
return {};
}
for (auto &Buf : Bufs)
@ -1315,7 +1294,7 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
if (!it.second.db)
continue;
std::unique_ptr<IndexFile> &entry = it.second.db;
entry->import_file = file;
entry->import_file = main;
entry->args = args;
for (auto &[_, it] : entry->uid2lid_and_path)
entry->lid2path.emplace_back(it.first, std::move(it.second));

View File

@ -17,6 +17,7 @@
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <llvm/Support/Path.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/Threading.h>
using namespace llvm;
@ -110,9 +111,11 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
}
}
// For inferred files, allow -o a a.cc -> -o b b.cc
std::string stem = sys::path::stem(path);
bool changed = prev->args.size() != args.size();
for (size_t i = 0; !changed && i < args.size(); i++)
if (strcmp(prev->args[i], args[i]))
if (strcmp(prev->args[i], args[i]) && sys::path::stem(args[i]) != stem)
changed = true;
if (changed)
LOG_S(INFO) << "args changed for " << path
@ -195,7 +198,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
}
// must_exist is currently unused.
Project::Entry entry = project->FindEntry(request.path, false);
Project::Entry entry =
project->FindEntry(request.path, true, request.must_exist);
if (request.must_exist && entry.filename.empty())
return true;
if (request.args.size())

View File

@ -411,17 +411,24 @@ void Project::Load(const std::string &root) {
}
}
Project::Entry Project::FindEntry(const std::string &path,
Project::Entry Project::FindEntry(const std::string &path, bool can_redirect,
bool must_exist) {
Project::Folder *best_folder = nullptr;
const Entry *best = nullptr;
std::lock_guard lock(mtx);
for (auto &[root, folder] : root2folder) {
// The entry may have different filename but it doesn't matter when building
// CompilerInvocation. The main filename is specified separately.
auto it = folder.path2entry_index.find(path);
if (it != folder.path2entry_index.end()) {
Project::Entry &entry = folder.entries[it->second];
if (!must_exist || entry.filename == path)
if (can_redirect || entry.filename == path)
return entry;
if (entry.compdb_size) {
best_folder = &folder;
best = &entry;
}
break;
}
}
@ -471,7 +478,7 @@ out:
best_folder = &folder;
}
}
}
}
}
ret.is_inferred = true;
@ -485,14 +492,6 @@ out:
ret.root = best->root;
ret.directory = best->directory;
ret.args = best->args;
std::string base_name = sys::path::filename(best->filename);
for (const char *&arg : ret.args) {
try {
if (arg == best->filename || sys::path::filename(arg) == base_name)
arg = Intern(path);
} catch (...) {
}
}
ret.args.resize(best->compdb_size);
if (extra && extra->size())
ret.args.insert(ret.args.end(), extra->begin() + 1, extra->end());

View File

@ -56,7 +56,7 @@ struct Project {
// Lookup the CompilationEntry for |filename|. If no entry was found this
// will infer one based on existing project structure.
Entry FindEntry(const std::string &path, bool can_be_inferred);
Entry FindEntry(const std::string &path, bool can_redirect, bool must_exist);
// If the client has overridden the flags, or specified them for a file
// that is not in the compilation_database.json make sure those changes

View File

@ -409,7 +409,7 @@ void *PreambleMain(void *manager_) {
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
stat_cache->Producer(session->FS);
if (std::unique_ptr<CompilerInvocation> CI =
BuildCompilerInvocation(session->file.args, FS))
BuildCompilerInvocation(task.path, session->file.args, FS))
BuildPreamble(*session, *CI, FS, task, std::move(stat_cache));
if (task.from_diag) {
@ -449,7 +449,7 @@ void *CompletionMain(void *manager_) {
IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
preamble ? preamble->stat_cache->Consumer(session->FS) : session->FS;
std::unique_ptr<CompilerInvocation> CI =
BuildCompilerInvocation(session->file.args, FS);
BuildCompilerInvocation(task->path, session->file.args, FS);
if (!CI)
continue;
auto &FOpts = CI->getFrontendOpts();
@ -551,7 +551,7 @@ void *DiagnosticMain(void *manager_) {
}
std::unique_ptr<CompilerInvocation> CI =
BuildCompilerInvocation(session->file.args, FS);
BuildCompilerInvocation(task.path, session->file.args, FS);
if (!CI)
continue;
// If main file is a header, add -Wno-unused-function
@ -696,7 +696,7 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
std::shared_ptr<ccls::Session> session = sessions.Get(path);
if (!session) {
session = std::make_shared<ccls::Session>(
project_->FindEntry(path, true), wfiles, PCH);
project_->FindEntry(path, false, false), wfiles, PCH);
std::string line;
if (LOG_V_ENABLED(1)) {
line = "\n ";