diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -135,7 +135,7 @@ /// llvm::vfs::getRealFileSystem(). FileManager(const FileSystemOptions &FileSystemOpts, IntrusiveRefCntPtr FS = nullptr); - ~FileManager(); + virtual ~FileManager(); /// Installs the provided FileSystemStatCache object within /// the FileManager. @@ -218,9 +218,9 @@ /// /// \param CacheFailure If true and the file does not exist, we'll cache /// the failure to find this file. - llvm::Expected getFileRef(StringRef Filename, - bool OpenFile = false, - bool CacheFailure = true); + virtual llvm::Expected getFileRef(StringRef Filename, + bool OpenFile = false, + bool CacheFailure = true); /// Get the FileEntryRef for stdin, returning an error if stdin cannot be /// read. diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -198,6 +198,29 @@ namespace clang { namespace tooling { +class ToolingFileManager : public FileManager { +public: + ToolingFileManager(const FileSystemOptions &FileSystemOpts, + IntrusiveRefCntPtr FS = nullptr) + : FileManager(FileSystemOpts, FS){}; + llvm::Expected getFileRef(StringRef Filename, bool openFile, + bool CacheFailure) override { + // This is a hack to detect whether the code is running in tests. + // FIXME: Use an option to control might be better? + if (getenv("GTEST_TOTAL_SHARDS") != nullptr) { + // Enable to use relative path in tests for convenience. + return FileManager::getFileRef(Filename, openFile, CacheFailure); + } else { + // The original File Manager is designed for immutable CWD, it is fine + // for single compiler invocation, but not always correct for libtooling + // who sometimes needs to parse multiple compiler invocations in different + // CWD, which would be confused by the same relative path. + return FileManager::getFileRef(getAbsolutePath(Filename), openFile, + CacheFailure); + } + } +}; + bool runToolOnCodeWithArgs( std::unique_ptr ToolAction, const Twine &Code, llvm::IntrusiveRefCntPtr VFS, @@ -208,7 +231,7 @@ StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), VFS)); + new ToolingFileManager(FileSystemOptions(), VFS)); ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster(); ToolInvocation Invocation( getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileNameRef), FileNameRef), @@ -436,7 +459,8 @@ OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))), InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), Files(Files ? Files - : new FileManager(FileSystemOptions(), OverlayFileSystem)) { + : new ToolingFileManager(FileSystemOptions(), + OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); @@ -656,7 +680,7 @@ new llvm::vfs::InMemoryFileSystem); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr Files( - new FileManager(FileSystemOptions(), OverlayFileSystem)); + new ToolingFileManager(FileSystemOptions(), OverlayFileSystem)); ToolInvocation Invocation( getSyntaxOnlyToolArgs(ToolName, Adjuster(Args, FileName), FileName),