diff options
Diffstat (limited to 'clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp')
-rw-r--r-- | clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp | 42 |
1 files changed, 38 insertions, 4 deletions
diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp index 7436c7256327..b4d5a29ca695 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningFilesystem.cpp @@ -122,6 +122,32 @@ DependencyScanningFilesystemSharedCache::get(StringRef Key) { return It.first->getValue(); } +/// Whitelist file extensions that should be minimized, treating no extension as +/// a source file that should be minimized. +/// +/// This is kinda hacky, it would be better if we knew what kind of file Clang +/// was expecting instead. +static bool shouldMinimize(StringRef Filename) { + StringRef Ext = llvm::sys::path::extension(Filename); + if (Ext.empty()) + return true; // C++ standard library + return llvm::StringSwitch<bool>(Ext) + .CasesLower(".c", ".cc", ".cpp", ".c++", ".cxx", true) + .CasesLower(".h", ".hh", ".hpp", ".h++", ".hxx", true) + .CasesLower(".m", ".mm", true) + .CasesLower(".i", ".ii", ".mi", ".mmi", true) + .CasesLower(".def", ".inc", true) + .Default(false); +} + + +static bool shouldCacheStatFailures(StringRef Filename) { + StringRef Ext = llvm::sys::path::extension(Filename); + if (Ext.empty()) + return false; // This may be the module cache directory. + return shouldMinimize(Filename); // Only cache stat failures on source files. +} + llvm::ErrorOr<const CachedFileSystemEntry *> DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( const StringRef Filename) { @@ -132,7 +158,8 @@ DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( // FIXME: Handle PCM/PCH files. // FIXME: Handle module map files. - bool KeepOriginalSource = IgnoredFiles.count(Filename); + bool KeepOriginalSource = IgnoredFiles.count(Filename) || + !shouldMinimize(Filename); DependencyScanningFilesystemSharedCache::SharedFileSystemEntry &SharedCacheEntry = SharedCache.get(Filename); const CachedFileSystemEntry *Result; @@ -143,9 +170,16 @@ DependencyScanningWorkerFilesystem::getOrCreateFileSystemEntry( if (!CacheEntry.isValid()) { llvm::vfs::FileSystem &FS = getUnderlyingFS(); auto MaybeStatus = FS.status(Filename); - if (!MaybeStatus) - CacheEntry = CachedFileSystemEntry(MaybeStatus.getError()); - else if (MaybeStatus->isDirectory()) + if (!MaybeStatus) { + if (!shouldCacheStatFailures(Filename)) + // HACK: We need to always restat non source files if the stat fails. + // This is because Clang first looks up the module cache and module + // files before building them, and then looks for them again. If we + // cache the stat failure, it won't see them the second time. + return MaybeStatus.getError(); + else + CacheEntry = CachedFileSystemEntry(MaybeStatus.getError()); + } else if (MaybeStatus->isDirectory()) CacheEntry = CachedFileSystemEntry::createDirectoryEntry( std::move(*MaybeStatus)); else |