Skip to content

Commit 0e17e27

Browse files
akyrtzibenlangmuir
authored andcommitted
[clang/HeaderSearch] Make sure loadSubdirectoryModuleMaps doesn't cause loading of regular files
`HeaderSearch::loadSubdirectoryModuleMaps` `stat`s all the files in a directory which causes the dependency scanning service to load and cache their contents. This is problematic because a file may be in the process of being generated and could be cached by the dep-scan service while it is still incomplete. To address this change `loadSubdirectoryModuleMaps` to ignore regular files. Differential Revision: https://reviews.llvm.org/D153670 (cherry picked from commit 03a0f4b)
1 parent 7bacdf8 commit 0e17e27

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

clang/lib/Lex/HeaderSearch.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,6 +1868,8 @@ void HeaderSearch::loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir) {
18681868
llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
18691869
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
18701870
Dir != DirEnd && !EC; Dir.increment(EC)) {
1871+
if (Dir->type() == llvm::sys::fs::file_type::regular_file)
1872+
continue;
18711873
bool IsFramework = llvm::sys::path::extension(Dir->path()) == ".framework";
18721874
if (IsFramework == SearchDir.isFramework())
18731875
loadModuleMapFile(Dir->path(), SearchDir.isSystemHeaderDirectory(),

clang/unittests/Tooling/DependencyScannerTest.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,66 @@ TEST(DependencyScanner, DepScanFSWithCASProvider) {
291291
EXPECT_EQ(BlobContents->getData(), Contents);
292292
}
293293
}
294+
295+
TEST(DependencyScanner, ScanDepsWithModuleLookup) {
296+
std::vector<std::string> CommandLine = {
297+
"clang",
298+
"-target",
299+
"x86_64-apple-macosx10.7",
300+
"-c",
301+
"test.m",
302+
"-o"
303+
"test.m.o",
304+
"-fmodules",
305+
"-I/root/SomeSources",
306+
};
307+
StringRef CWD = "/root";
308+
309+
auto VFS = new llvm::vfs::InMemoryFileSystem();
310+
VFS->setCurrentWorkingDirectory(CWD);
311+
auto Sept = llvm::sys::path::get_separator();
312+
std::string OtherPath =
313+
std::string(llvm::formatv("{0}root{0}SomeSources{0}other.h", Sept));
314+
std::string TestPath = std::string(llvm::formatv("{0}root{0}test.m", Sept));
315+
316+
VFS->addFile(OtherPath, 0, llvm::MemoryBuffer::getMemBuffer("\n"));
317+
VFS->addFile(TestPath, 0, llvm::MemoryBuffer::getMemBuffer("@import Foo;\n"));
318+
319+
struct InterceptorFS : llvm::vfs::ProxyFileSystem {
320+
std::vector<std::string> StatPaths;
321+
std::vector<std::string> ReadFiles;
322+
323+
InterceptorFS(IntrusiveRefCntPtr<FileSystem> UnderlyingFS)
324+
: ProxyFileSystem(UnderlyingFS) {}
325+
326+
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
327+
StatPaths.push_back(Path.str());
328+
return ProxyFileSystem::status(Path);
329+
}
330+
331+
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
332+
openFileForRead(const Twine &Path) override {
333+
ReadFiles.push_back(Path.str());
334+
return ProxyFileSystem::openFileForRead(Path);
335+
}
336+
};
337+
338+
auto InterceptFS = llvm::makeIntrusiveRefCnt<InterceptorFS>(VFS);
339+
340+
DependencyScanningService Service(ScanningMode::DependencyDirectivesScan,
341+
ScanningOutputFormat::Make, CASOptions(),
342+
nullptr, nullptr, nullptr);
343+
DependencyScanningTool ScanTool(Service, InterceptFS);
344+
345+
// This will fail with "fatal error: module 'Foo' not found" but it doesn't
346+
// matter, the point of the test is to check that files are not read
347+
// unnecessarily.
348+
std::string DepFile;
349+
ASSERT_THAT_ERROR(
350+
ScanTool.getDependencyFile(CommandLine, CWD).moveInto(DepFile),
351+
llvm::Failed());
352+
353+
EXPECT_TRUE(llvm::find(InterceptFS->StatPaths, OtherPath) ==
354+
InterceptFS->StatPaths.end());
355+
EXPECT_EQ(InterceptFS->ReadFiles, std::vector<std::string>{"/root/test.m"});
356+
}

0 commit comments

Comments
 (0)