diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #define LLVM_SUPPORT_COMMANDLINE_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -40,6 +41,12 @@ #include namespace llvm { +namespace vfs { + +class FileSystem; +IntrusiveRefCntPtr getRealFileSystem(); + +} // namespace vfs class StringSaver; class raw_ostream; @@ -1964,10 +1971,13 @@ /// with nullptrs in the Argv vector. /// \param [in] RelativeNames true if names of nested response files must be /// resolved relative to including file. +/// \param [in] FS File system used for all file access when running the tool. /// \return true if all @files were expanded successfully or there were none. -bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl &Argv, - bool MarkEOLs = false, bool RelativeNames = false); +bool ExpandResponseFiles( + StringSaver &Saver, TokenizerCallback Tokenizer, + SmallVectorImpl &Argv, bool MarkEOLs = false, + bool RelativeNames = false, + llvm::vfs::FileSystem &FS = *llvm::vfs::getRealFileSystem()); /// Mark all options not part of this category as cl::ReallyHidden. /// diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -37,6 +37,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/StringSaver.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -1046,9 +1047,10 @@ static bool ExpandResponseFile(StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl &NewArgv, - bool MarkEOLs, bool RelativeNames) { + bool MarkEOLs, bool RelativeNames, + llvm::vfs::FileSystem &FS) { ErrorOr> MemBufOrErr = - MemoryBuffer::getFile(FName); + FS.getBufferForFile(FName); if (!MemBufOrErr) return false; MemoryBuffer &MemBuf = *MemBufOrErr.get(); @@ -1068,6 +1070,9 @@ else if (hasUTF8ByteOrderMark(BufRef)) Str = StringRef(BufRef.data() + 3, BufRef.size() - 3); + llvm::ErrorOr CurrDir = FS.getCurrentWorkingDirectory(); + if (!CurrDir) + return false; // Tokenize the contents into NewArgv. Tokenizer(Str, Saver, NewArgv, MarkEOLs); @@ -1084,9 +1089,7 @@ SmallString<128> ResponseFile; ResponseFile.append(1, '@'); if (llvm::sys::path::is_relative(FName)) { - SmallString<128> curr_dir; - llvm::sys::fs::current_path(curr_dir); - ResponseFile.append(curr_dir.str()); + ResponseFile.append(CurrDir.get()); } llvm::sys::path::append( ResponseFile, llvm::sys::path::parent_path(FName), FileName); @@ -1101,8 +1104,8 @@ /// Expand response files on a command line recursively using the given /// StringSaver and tokenization strategy. bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, - SmallVectorImpl &Argv, - bool MarkEOLs, bool RelativeNames) { + SmallVectorImpl &Argv, bool MarkEOLs, + bool RelativeNames, llvm::vfs::FileSystem &FS) { bool AllExpanded = true; struct ResponseFileRecord { const char *File; @@ -1139,8 +1142,13 @@ } const char *FName = Arg + 1; - auto IsEquivalent = [FName](const ResponseFileRecord &RFile) { - return sys::fs::equivalent(RFile.File, FName); + auto IsEquivalent = [FName, &FS](const ResponseFileRecord &RFile) { + SmallVector LHSPath; + SmallVector RHSPath; + if (FS.getRealPath(FName, LHSPath) || FS.getRealPath(RFile.File, RHSPath)) { + return false; + } + return LHSPath == RHSPath; }; // Check for recursive response files. @@ -1156,7 +1164,7 @@ // contents. Nested response files are expanded in subsequent iterations. SmallVector ExpandedArgv; if (!ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs, - RelativeNames)) { + RelativeNames, FS)) { // We couldn't read this file, so we leave it in the argument stream and // move on. AllExpanded = false; @@ -1187,7 +1195,8 @@ bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver, SmallVectorImpl &Argv) { if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv, - /*MarkEOLs*/ false, /*RelativeNames*/ true)) + /*MarkEOLs*/ false, /*RelativeNames*/ true, + *llvm::vfs::getRealFileSystem())) return false; return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv, /*MarkEOLs*/ false, /*RelativeNames*/ true);