arphaman updated this revision to Diff 162106.
arphaman added a comment.
Address review comments.
https://reviews.llvm.org/D50926
Files:
include/clang/Basic/SourceManager.h
lib/Basic/SourceManager.cpp
unittests/Basic/SourceManagerTest.cpp
Index: unittests/Basic/SourceManagerTest.cpp
===================================================================
--- unittests/Basic/SourceManagerTest.cpp
+++ unittests/Basic/SourceManagerTest.cpp
@@ -377,6 +377,60 @@
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
}
+TEST_F(SourceManagerTest, findFileIDsForFile) {
+ const char *header = "int x;";
+
+ const char *main = "#include </test-header.h>\n"
+ "#include </test-header.h>\n";
+
+ std::unique_ptr<llvm::MemoryBuffer> HeaderBuf =
+ llvm::MemoryBuffer::getMemBuffer(header);
+ std::unique_ptr<llvm::MemoryBuffer> MainBuf =
+ llvm::MemoryBuffer::getMemBuffer(main);
+
+ const FileEntry *HeaderFile =
+ FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(HeaderFile, std::move(HeaderBuf));
+ const FileEntry *MainFile =
+ FileMgr.getVirtualFile("main.cpp", MainBuf->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(MainFile, std::move(MainBuf));
+ SourceMgr.setMainFileID(
+ SourceMgr.createFileID(MainFile, SourceLocation(), SrcMgr::C_User));
+
+ TrivialModuleLoader ModLoader;
+ MemoryBufferCache PCMCache;
+ HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+ Diags, LangOpts, &*Target);
+ Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+ SourceMgr, PCMCache, HeaderInfo, ModLoader,
+ /*IILookup =*/nullptr,
+ /*OwnsHeaderSearch =*/false);
+ PP.Initialize(*Target);
+
+ PP.EnterMainSourceFile();
+
+ while (1) {
+ Token tok;
+ PP.Lex(tok);
+ if (tok.is(tok::eof))
+ break;
+ }
+
+ llvm::SmallVector<FileID, 2> MainFileID =
+ SourceMgr.findFileIDsForFile(MainFile);
+ ASSERT_EQ(1U, MainFileID.size());
+ ASSERT_EQ(MainFileID[0], SourceMgr.getMainFileID());
+
+ llvm::SmallVector<FileID, 2> Files = SourceMgr.findFileIDsForFile(HeaderFile);
+
+ ASSERT_EQ(2U, Files.size());
+ ASSERT_NE(Files[0], Files[1]);
+ SourceLocation Loc1 = SourceMgr.translateLineCol(Files[0], 1, 1);
+ SourceLocation Loc2 = SourceMgr.translateLineCol(Files[1], 1, 1);
+ ASSERT_NE(Loc1, Loc2);
+ ASSERT_TRUE(SourceMgr.isBeforeInTranslationUnit(Loc1, Loc2));
+}
+
#endif
} // anonymous namespace
Index: lib/Basic/SourceManager.cpp
===================================================================
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1602,6 +1602,70 @@
return translateLineCol(FirstFID, Line, Col);
}
+bool SourceManager::findFileIDsForFile(
+ const FileEntry *SourceFile, bool LookForFilesystemUpdates,
+ llvm::function_ref<bool(FileID)> Callback) const {
+ assert(SourceFile && "Null source file!");
+
+ Optional<llvm::sys::fs::UniqueID> SourceFileUID;
+ Optional<StringRef> SourceFileName;
+
+ // Look through all of the local source locations.
+ for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
+ bool Invalid = false;
+ const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid);
+ if (Invalid)
+ return false;
+ if (!SLoc.isFile())
+ continue;
+ const ContentCache *FileContentCache = SLoc.getFile().getContentCache();
+ if (!FileContentCache || !FileContentCache->OrigEntry)
+ continue;
+
+ if (FileContentCache->OrigEntry == SourceFile) {
+ if (Callback(FileID::get(I)))
+ return true;
+ } else if (LookForFilesystemUpdates &&
+ (SourceFileName || (SourceFileName = llvm::sys::path::filename(
+ SourceFile->getName()))) &&
+ *SourceFileName == llvm::sys::path::filename(
+ FileContentCache->OrigEntry->getName()) &&
+ (SourceFileUID ||
+ (SourceFileUID = getActualFileUID(SourceFile)))) {
+ if (Optional<llvm::sys::fs::UniqueID> EntryUID =
+ getActualFileUID(FileContentCache->OrigEntry)) {
+ if (*SourceFileUID == *EntryUID) {
+ if (Callback(FileID::get(I)))
+ return true;
+ SourceFile = FileContentCache->OrigEntry;
+ }
+ }
+ }
+ }
+
+ // If that still didn't help, try the modules.
+ for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
+ const SLocEntry &SLoc = getLoadedSLocEntry(I);
+ if (SLoc.isFile() && SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
+ if (Callback(FileID::get(-int(I) - 2)))
+ return true;
+ }
+ }
+ return false;
+}
+
+llvm::SmallVector<FileID, 2>
+SourceManager::findFileIDsForFile(const FileEntry *SourceFile) const {
+ llvm::SmallVector<FileID, 2> Result;
+ findFileIDsForFile(SourceFile, /*LookForFilesystemUpdates=*/true,
+ [&](FileID F) {
+ Result.push_back(F);
+ return false;
+ });
+ return Result;
+}
+
/// Get the FileID for the given file.
///
/// If the source file is included multiple times, the FileID will be the
@@ -1650,72 +1714,27 @@
}
}
- if (FirstFID.isInvalid()) {
- // The location we're looking for isn't in the main file; look
- // through all of the local source locations.
- for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
- bool Invalid = false;
- const SLocEntry &SLoc = getLocalSLocEntry(I, &Invalid);
- if (Invalid)
- return FileID();
+ if (FirstFID.isValid())
+ return FirstFID;
- if (SLoc.isFile() &&
- SLoc.getFile().getContentCache() &&
- SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
- FirstFID = FileID::get(I);
- break;
- }
- }
- // If that still didn't help, try the modules.
- if (FirstFID.isInvalid()) {
- for (unsigned I = 0, N = loaded_sloc_entry_size(); I != N; ++I) {
- const SLocEntry &SLoc = getLoadedSLocEntry(I);
- if (SLoc.isFile() &&
- SLoc.getFile().getContentCache() &&
- SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
- FirstFID = FileID::get(-int(I) - 2);
- break;
- }
- }
- }
- }
+ // The location we're looking for isn't in the main file; look
+ // through all of the local and the imported source locations.
+ if (findFileIDsForFile(SourceFile, /*LookForFilesystemUpdates=*/false,
+ [&](FileID F) {
+ FirstFID = F;
+ return true;
+ }))
+ return FirstFID;
// If we haven't found what we want yet, try again, but this time stat()
// each of the files in case the files have changed since we originally
// parsed the file.
- if (FirstFID.isInvalid() &&
- (SourceFileName ||
- (SourceFileName = llvm::sys::path::filename(SourceFile->getName()))) &&
- (SourceFileUID || (SourceFileUID = getActualFileUID(SourceFile)))) {
- bool Invalid = false;
- for (unsigned I = 0, N = local_sloc_entry_size(); I != N; ++I) {
- FileID IFileID;
- IFileID.ID = I;
- const SLocEntry &SLoc = getSLocEntry(IFileID, &Invalid);
- if (Invalid)
- return FileID();
-
- if (SLoc.isFile()) {
- const ContentCache *FileContentCache
- = SLoc.getFile().getContentCache();
- const FileEntry *Entry = FileContentCache ? FileContentCache->OrigEntry
- : nullptr;
- if (Entry &&
- *SourceFileName == llvm::sys::path::filename(Entry->getName())) {
- if (Optional<llvm::sys::fs::UniqueID> EntryUID =
- getActualFileUID(Entry)) {
- if (*SourceFileUID == *EntryUID) {
- FirstFID = FileID::get(I);
- SourceFile = Entry;
- break;
- }
- }
- }
- }
- }
- }
+ findFileIDsForFile(SourceFile, /*LookForFilesystemUpdates=*/true,
+ [&](FileID F) {
+ FirstFID = F;
+ return true;
+ });
- (void) SourceFile;
return FirstFID;
}
Index: include/clang/Basic/SourceManager.h
===================================================================
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -1525,6 +1525,32 @@
/// first inclusion.
FileID translateFile(const FileEntry *SourceFile) const;
+ /// Looks through all the local and imported source locations to find the set
+ /// of FileIDs that correspond to the given entry.
+ ///
+ /// When the given FileEntry is different to the entry of a file with the same
+ /// filepath, this function will stat the filepath to check if the entry
+ /// changed because of an on-disk update.
+ ///
+ /// \returns the set of FileIDs for the given file, in the order of inclusion.
+ llvm::SmallVector<FileID, 2>
+ findFileIDsForFile(const FileEntry *SourceFile) const;
+
+private:
+ /// Looks through all the local and imported source locations to find the set
+ /// of FileIDs that correspond to the given entry.
+ ///
+ /// \param LookForFilesystemUpdates check for disk updates if entries don't
+ /// match.
+ ///
+ /// \param Callback should return true to exit the search.
+ ///
+ /// \returns true if the callback returned true, false otherwise.
+ bool findFileIDsForFile(const FileEntry *SourceFile,
+ bool LookForFilesystemUpdates,
+ llvm::function_ref<bool(FileID)> Callback) const;
+
+public:
/// Get the source location in \p FID for the given line:col.
/// Returns null location if \p FID is not a file SLocEntry.
SourceLocation translateLineCol(FileID FID,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits