From 65f86d0498ced6e44648b5d18d145a02b413cc59 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 21 Aug 2019 23:46:02 -0700 Subject: [PATCH] indexer: llvm::sys::fs::UniqueID -> clang::FileID Fix a minor issue that an empty included file is not recorded. Note, we need to skip invalid uid2lid_and_path because otherwise lid2path may contain invalid entries with lid: 0, which will cause the file entry with file_id 0 to have an empty path. --- src/clang_tu.cc | 28 ++++--------- src/clang_tu.hh | 12 ++---- src/indexer.cc | 106 ++++++++++++++++++++++++------------------------ src/indexer.hh | 12 ++---- 4 files changed, 69 insertions(+), 89 deletions(-) diff --git a/src/clang_tu.cc b/src/clang_tu.cc index ea580b6d..67909bed 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -42,42 +42,30 @@ static Pos decomposed2LineAndCol(const SourceManager &sm, } Range fromCharSourceRange(const SourceManager &sm, const LangOptions &lang, - CharSourceRange csr, - llvm::sys::fs::UniqueID *uniqueID) { + CharSourceRange csr, FileID *fid) { SourceLocation bloc = csr.getBegin(), eloc = csr.getEnd(); std::pair binfo = sm.getDecomposedLoc(bloc), einfo = sm.getDecomposedLoc(eloc); if (csr.isTokenRange()) einfo.second += Lexer::MeasureTokenLength(eloc, sm, lang); - if (uniqueID) { - if (const FileEntry *F = sm.getFileEntryForID(binfo.first)) - *uniqueID = F->getUniqueID(); - else - *uniqueID = llvm::sys::fs::UniqueID(0, 0); - } + if (fid) + *fid = binfo.first; return {decomposed2LineAndCol(sm, binfo), decomposed2LineAndCol(sm, einfo)}; } -Range fromCharRange(const SourceManager &sm, const LangOptions &lang, - SourceRange sr, llvm::sys::fs::UniqueID *uniqueID) { - return fromCharSourceRange(sm, lang, CharSourceRange::getCharRange(sr), - uniqueID); -} - Range fromTokenRange(const SourceManager &sm, const LangOptions &lang, - SourceRange sr, llvm::sys::fs::UniqueID *uniqueID) { - return fromCharSourceRange(sm, lang, CharSourceRange::getTokenRange(sr), - uniqueID); + SourceRange sr, FileID *fid) { + return fromCharSourceRange(sm, lang, CharSourceRange::getTokenRange(sr), fid); } Range fromTokenRangeDefaulted(const SourceManager &sm, const LangOptions &lang, - SourceRange sr, const FileEntry *fe, Range range) { + SourceRange sr, FileID fid, Range range) { auto decomposed = sm.getDecomposedLoc(sm.getExpansionLoc(sr.getBegin())); - if (sm.getFileEntryForID(decomposed.first) == fe) + if (decomposed.first == fid) range.start = decomposed2LineAndCol(sm, decomposed); SourceLocation sl = sm.getExpansionLoc(sr.getEnd()); decomposed = sm.getDecomposedLoc(sl); - if (sm.getFileEntryForID(decomposed.first) == fe) { + if (decomposed.first == fid) { decomposed.second += Lexer::MeasureTokenLength(sl, sm, lang); range.end = decomposed2LineAndCol(sm, decomposed); } diff --git a/src/clang_tu.hh b/src/clang_tu.hh index d105e09a..b53799a8 100644 --- a/src/clang_tu.hh +++ b/src/clang_tu.hh @@ -22,20 +22,16 @@ std::string pathFromFileEntry(const clang::FileEntry &file); Range fromCharSourceRange(const clang::SourceManager &sm, const clang::LangOptions &lang, - clang::CharSourceRange sr, - llvm::sys::fs::UniqueID *uniqueID = nullptr); - -Range fromCharRange(const clang::SourceManager &sm, - const clang::LangOptions &lang, clang::SourceRange sr, - llvm::sys::fs::UniqueID *uniqueID = nullptr); + clang::CharSourceRange csr, + clang::FileID *fid = nullptr); Range fromTokenRange(const clang::SourceManager &sm, const clang::LangOptions &lang, clang::SourceRange sr, - llvm::sys::fs::UniqueID *uniqueID = nullptr); + clang::FileID *fid = nullptr); Range fromTokenRangeDefaulted(const clang::SourceManager &sm, const clang::LangOptions &lang, - clang::SourceRange sr, const clang::FileEntry *fe, + clang::SourceRange sr, clang::FileID fid, Range range); std::unique_ptr diff --git a/src/indexer.cc b/src/indexer.cc index dd727a72..ea63db0a 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -40,8 +40,8 @@ struct File { }; struct IndexParam { - std::unordered_map uid2file; - std::unordered_map uid2multi; + std::unordered_map uid2file; + std::unordered_map uid2multi; struct DeclInfo { Usr usr; std::string short_name; @@ -54,14 +54,17 @@ struct IndexParam { bool no_linkage; IndexParam(VFS &vfs, bool no_linkage) : vfs(vfs), no_linkage(no_linkage) {} - void seenFile(const FileEntry &file) { + void seenFile(FileID fid) { // If this is the first time we have seen the file (ignoring if we are // generating an index for it): - auto [it, inserted] = uid2file.try_emplace(file.getUniqueID()); + auto [it, inserted] = uid2file.try_emplace(fid); if (inserted) { - std::string path = pathFromFileEntry(file); + const FileEntry *fe = ctx->getSourceManager().getFileEntryForID(fid); + if (!fe) + return; + std::string path = pathFromFileEntry(*fe); it->second.path = path; - it->second.mtime = file.getModificationTime(); + it->second.mtime = fe->getModificationTime(); if (!it->second.mtime) if (auto tim = lastWriteTime(path)) it->second.mtime = *tim; @@ -75,15 +78,16 @@ struct IndexParam { } } - IndexFile *consumeFile(const FileEntry &fe) { - seenFile(fe); - return uid2file[fe.getUniqueID()].db.get(); + IndexFile *consumeFile(FileID fid) { + seenFile(fid); + return uid2file[fid].db.get(); } - bool useMultiVersion(const FileEntry &fe) { - auto it = uid2multi.try_emplace(fe.getUniqueID()); + bool useMultiVersion(FileID fid) { + auto it = uid2multi.try_emplace(fid); if (it.second) - it.first->second = multiVersionMatcher->matches(pathFromFileEntry(fe)); + if (const FileEntry *fe = ctx->getSourceManager().getFileEntryForID(fid)) + it.first->second = multiVersionMatcher->matches(pathFromFileEntry(*fe)); return it.first->second; } }; @@ -609,27 +613,24 @@ public: } } - static int getFileLID(IndexFile *db, SourceManager &sm, const FileEntry &fe) { - auto [it, inserted] = db->uid2lid_and_path.try_emplace(fe.getUniqueID()); + static int getFileLID(IndexFile *db, SourceManager &sm, FileID fid) { + auto [it, inserted] = db->uid2lid_and_path.try_emplace(fid); if (inserted) { - it->second.first = db->uid2lid_and_path.size() - 1; - SmallString<256> path = fe.tryGetRealPathName(); - if (path.empty()) - path = fe.getName(); - if (!llvm::sys::path::is_absolute(path) && - !sm.getFileManager().makeAbsolutePath(path)) + const FileEntry *fe = sm.getFileEntryForID(fid); + if (!fe) { + it->second.first = -1; return -1; - it->second.second = llvm::sys::path::convert_to_slash(path.str()); + } + it->second.first = db->uid2lid_and_path.size() - 1; + it->second.second = pathFromFileEntry(*fe); } return it->second.first; } void addMacroUse(IndexFile *db, SourceManager &sm, Usr usr, Kind kind, SourceLocation sl) const { - const FileEntry *FE = sm.getFileEntryForID(sm.getFileID(sl)); - if (!FE) - return; - int lid = getFileLID(db, sm, *FE); + FileID fid = sm.getFileID(sl); + int lid = getFileLID(db, sm, fid); if (lid < 0) return; Range spell = fromTokenRange(sm, ctx->getLangOpts(), SourceRange(sl, sl)); @@ -693,27 +694,25 @@ public: const LangOptions &lang = ctx->getLangOpts(); FileID fid; SourceLocation spell = sm.getSpellingLoc(src_loc); - const FileEntry *fe; Range loc; auto r = sm.isMacroArgExpansion(src_loc) ? CharSourceRange::getTokenRange(spell) : sm.getExpansionRange(src_loc); loc = fromCharSourceRange(sm, lang, r); fid = sm.getFileID(r.getBegin()); - fe = sm.getFileEntryForID(fid); - if (!fe) + if (fid.isInvalid()) return true; int lid = -1; IndexFile *db; - if (g_config->index.multiVersion && param.useMultiVersion(*fe)) { - db = param.consumeFile(*sm.getFileEntryForID(sm.getMainFileID())); + if (g_config->index.multiVersion && param.useMultiVersion(fid)) { + db = param.consumeFile(sm.getMainFileID()); if (!db) return true; - param.seenFile(*fe); + param.seenFile(fid); if (!sm.isWrittenInMainFile(r.getBegin())) - lid = getFileLID(db, sm, *fe); + lid = getFileLID(db, sm, fid); } else { - db = param.consumeFile(*fe); + db = param.consumeFile(fid); if (!db) return true; } @@ -775,13 +774,13 @@ public: if (is_def) { SourceRange sr = origD->getSourceRange(); entity->def.spell = {use, - fromTokenRangeDefaulted(sm, lang, sr, fe, loc)}; + fromTokenRangeDefaulted(sm, lang, sr, fid, loc)}; entity->def.parent_kind = SymbolKind::File; getKind(cast(sem_dc), entity->def.parent_kind); } else if (is_decl) { SourceRange sr = origD->getSourceRange(); entity->declarations.push_back( - {use, fromTokenRangeDefaulted(sm, lang, sr, fe, loc)}); + {use, fromTokenRangeDefaulted(sm, lang, sr, fid, loc)}); } else { entity->uses.push_back(use); return; @@ -1077,6 +1076,11 @@ class IndexPPCallbacks : public PPCallbacks { public: IndexPPCallbacks(SourceManager &sm, IndexParam ¶m) : sm(sm), param(param) {} + void FileChanged(SourceLocation sl, FileChangeReason reason, + SrcMgr::CharacteristicKind, FileID) override { + if (reason == FileChangeReason::EnterFile) + (void)param.consumeFile(sm.getFileID(sl)); + } void InclusionDirective(SourceLocation hashLoc, const Token &tok, StringRef included, bool isAngled, CharSourceRange filenameRange, const FileEntry *file, @@ -1087,11 +1091,8 @@ public: return; auto spell = fromCharSourceRange(sm, param.ctx->getLangOpts(), filenameRange, nullptr); - const FileEntry *fe = - sm.getFileEntryForID(sm.getFileID(filenameRange.getBegin())); - if (!fe) - return; - if (IndexFile *db = param.consumeFile(*fe)) { + FileID fid = sm.getFileID(filenameRange.getBegin()); + if (IndexFile *db = param.consumeFile(fid)) { std::string path = pathFromFileEntry(*file); if (path.size()) db->includes.push_back({spell.start.line, intern(path)}); @@ -1100,10 +1101,8 @@ public: void MacroDefined(const Token &tok, const MacroDirective *md) override { const LangOptions &lang = param.ctx->getLangOpts(); SourceLocation sl = md->getLocation(); - const FileEntry *fe = sm.getFileEntryForID(sm.getFileID(sl)); - if (!fe) - return; - if (IndexFile *db = param.consumeFile(*fe)) { + FileID fid = sm.getFileID(sl); + if (IndexFile *db = param.consumeFile(fid)) { auto [name, usr] = getMacro(tok); IndexVar &var = db->toVar(usr); Range range = fromTokenRange(sm, lang, {sl, sl}, nullptr); @@ -1128,15 +1127,12 @@ public: } void MacroExpands(const Token &tok, const MacroDefinition &, SourceRange sr, const MacroArgs *) override { - llvm::sys::fs::UniqueID uniqueID; SourceLocation sl = sm.getSpellingLoc(sr.getBegin()); - const FileEntry *fe = sm.getFileEntryForID(sm.getFileID(sl)); - if (!fe) - return; - if (IndexFile *db = param.consumeFile(*fe)) { + FileID fid = sm.getFileID(sl); + if (IndexFile *db = param.consumeFile(fid)) { IndexVar &var = db->toVar(getMacro(tok).second); var.uses.push_back( - {{fromTokenRange(sm, param.ctx->getLangOpts(), {sl, sl}, &uniqueID), + {{fromTokenRange(sm, param.ctx->getLangOpts(), {sl, sl}, nullptr), Role::Dynamic}}); } } @@ -1150,8 +1146,9 @@ public: void SourceRangeSkipped(SourceRange sr, SourceLocation) override { Range range = fromCharSourceRange(sm, param.ctx->getLangOpts(), CharSourceRange::getCharRange(sr)); - if (const FileEntry *fe = sm.getFileEntryForID(sm.getFileID(sr.getBegin()))) - if (IndexFile *db = param.consumeFile(*fe)) + FileID fid = sm.getFileID(sr.getBegin()); + if (fid.isValid()) + if (IndexFile *db = param.consumeFile(fid)) db->skipped_ranges.push_back(range); } }; @@ -1321,7 +1318,8 @@ index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, entry->import_file = main; entry->args = args; for (auto &[_, it] : entry->uid2lid_and_path) - entry->lid2path.emplace_back(it.first, std::move(it.second)); + if (it.first >= 0) + entry->lid2path.emplace_back(it.first, std::move(it.second)); entry->uid2lid_and_path.clear(); for (auto &it : entry->usr2func) { // e.g. declaration + out-of-line definition @@ -1341,6 +1339,8 @@ index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs, // Update dependencies for the file. for (auto &[_, file] : param.uid2file) { const std::string &path = file.path; + if (path.empty()) + continue; if (path == entry->path) entry->mtime = file.mtime; else if (path != entry->import_file) diff --git a/src/indexer.hh b/src/indexer.hh index 47aa1b30..cd4669a9 100644 --- a/src/indexer.hh +++ b/src/indexer.hh @@ -8,7 +8,7 @@ #include "serializer.hh" #include "utils.hh" -#include +#include #include #include #include @@ -19,12 +19,8 @@ #include namespace std { -template <> struct hash { - std::size_t operator()(llvm::sys::fs::UniqueID ID) const { - size_t ret = ID.getDevice(); - ccls::hash_combine(ret, ID.getFile()); - return ret; - } +template <> struct hash { + std::size_t operator()(clang::FileID fid) const { return fid.getHashValue(); } }; } // namespace std @@ -294,7 +290,7 @@ struct IndexFile { bool no_linkage; // uid2lid_and_path is used to generate lid2path, but not serialized. - std::unordered_map> + std::unordered_map> uid2lid_and_path; std::vector> lid2path;