Index: lib/Basic/VirtualFileSystem.cpp =================================================================== --- lib/Basic/VirtualFileSystem.cpp +++ lib/Basic/VirtualFileSystem.cpp @@ -25,9 +25,9 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Config/llvm-config.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Chrono.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -243,6 +244,10 @@ std::error_code setCurrentWorkingDirectory(const Twine &Path) override; std::error_code getRealPath(const Twine &Path, SmallVectorImpl &Output) const override; +private: + // Make sure `CWDCache` update is thread safe in `getCurrentWorkingDirectory`. + mutable std::mutex Mutex; + mutable std::string CWDCache; }; } // namespace @@ -265,10 +270,14 @@ } llvm::ErrorOr RealFileSystem::getCurrentWorkingDirectory() const { + std::lock_guard Lock(Mutex); + if (!CWDCache.empty()) + return CWDCache; SmallString<256> Dir; if (std::error_code EC = llvm::sys::fs::current_path(Dir)) return EC; - return Dir.str().str(); + CWDCache = Dir.str(); + return CWDCache; } std::error_code RealFileSystem::setCurrentWorkingDirectory(const Twine &Path) { @@ -279,7 +288,13 @@ // difference for example on network filesystems, where symlinks might be // switched during runtime of the tool. Fixing this depends on having a // file system abstraction that allows openat() style interactions. - return llvm::sys::fs::set_current_path(Path); + if (auto EC = llvm::sys::fs::set_current_path(Path)) + return EC; + + // Invalidate cache. + std::lock_guard Lock(Mutex); + CWDCache.clear(); + return std::error_code(); } std::error_code