arphaman created this revision.
arphaman added reviewers: jkorous, ioeric.
Herald added a subscriber: dexonsmith.
This patch extracts the code that searches for a file id from `translateFile`
to `findFileIDsForFile` to allow the users to map from one file entry to
multiple FileIDs.
Will be used as a basis for a clang-rename fix in
https://reviews.llvm.org/D50801.
Repository:
rC Clang
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,55 @@
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);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(MainBuf)));
+
+ const FileEntry *headerFile =
+ FileMgr.getVirtualFile("/test-header.h", HeaderBuf->getBufferSize(), 0);
+ SourceMgr.overrideFileContents(headerFile, std::move(HeaderBuf));
+
+ 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> Files;
+ SourceMgr.findFileIDsForFile(headerFile, [&](FileID F) -> bool {
+ Files.push_back(F);
+ return false;
+ });
+
+ 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,37 @@
return translateLineCol(FirstFID, Line, Col);
}
+bool SourceManager::findFileIDsForFile(
+ const FileEntry *SourceFile,
+ llvm::function_ref<bool(FileID)> Callback) const {
+ assert(SourceFile && "Null source 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 false;
+
+ if (SLoc.isFile() && SLoc.getFile().getContentCache() &&
+ SLoc.getFile().getContentCache()->OrigEntry == SourceFile) {
+ if (Callback(FileID::get(I)))
+ return true;
+ }
+ }
+
+ // 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;
+}
+
/// Get the FileID for the given file.
///
/// If the source file is included multiple times, the FileID will be the
@@ -1650,35 +1681,16 @@
}
}
- 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, [&](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
Index: include/clang/Basic/SourceManager.h
===================================================================
--- include/clang/Basic/SourceManager.h
+++ include/clang/Basic/SourceManager.h
@@ -1530,6 +1530,15 @@
SourceLocation translateLineCol(FileID FID,
unsigned Line, unsigned Col) const;
+ /// Looks through all the local and imported source locations to find the set
+ /// of FileIDs that correspond to the given entry.
+ ///
+ /// \param Callback should return true to exit the search.
+ ///
+ /// \returns true if the callback returned true, false otherwise.
+ bool findFileIDsForFile(const FileEntry *SourceFile,
+ llvm::function_ref<bool(FileID)> Callback) const;
+
/// If \p Loc points inside a function macro argument, the returned
/// location will be the macro location in which the argument was expanded.
/// If a macro argument is used multiple times, the expanded location will
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits