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 @@ -29,6 +29,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -1964,10 +1965,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 @@ -29,6 +29,7 @@ #include "llvm/Config/config.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -37,6 +38,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 @@ -1043,14 +1045,18 @@ return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf'); } -static bool ExpandResponseFile(StringRef FName, StringSaver &Saver, +static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl &NewArgv, - bool MarkEOLs, bool RelativeNames) { - ErrorOr> MemBufOrErr = - MemoryBuffer::getFile(FName); + bool MarkEOLs, bool RelativeNames, + llvm::vfs::FileSystem &FS) { + llvm::ErrorOr CurrDirOrErr = FS.getCurrentWorkingDirectory(); + if (!CurrDirOrErr) + return llvm::errorCodeToError(CurrDirOrErr.getError()); + llvm::ErrorOr> MemBufOrErr = + FS.getBufferForFile(FName); if (!MemBufOrErr) - return false; + return llvm::errorCodeToError(MemBufOrErr.getError()); MemoryBuffer &MemBuf = *MemBufOrErr.get(); StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize()); @@ -1059,7 +1065,9 @@ std::string UTF8Buf; if (hasUTF16ByteOrderMark(BufRef)) { if (!convertUTF16ToUTF8String(BufRef, UTF8Buf)) - return false; + return llvm::createStringError( + std::make_error_code(std::errc::illegal_byte_sequence), + "Could not convert UTF16 To UTF8"); Str = StringRef(UTF8Buf); } // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove @@ -1084,9 +1092,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(CurrDirOrErr.get()); } llvm::sys::path::append( ResponseFile, llvm::sys::path::parent_path(FName), FileName); @@ -1095,14 +1101,14 @@ } } - return true; + return Error::success(); } /// 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 +1145,20 @@ } 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) { + llvm::ErrorOr LHS = FS.status(FName); + if (!LHS) { + // TODO: The error should be propagated up the stack. + llvm::consumeError(llvm::errorCodeToError(LHS.getError())); + return false; + } + llvm::ErrorOr RHS = FS.status(RFile.File); + if (!RHS) { + // TODO: The error should be propagated up the stack. + llvm::consumeError(llvm::errorCodeToError(RHS.getError())); + return false; + } + return LHS->equivalent(*RHS); }; // Check for recursive response files. @@ -1155,10 +1173,13 @@ // Replace this response file argument with the tokenization of its // contents. Nested response files are expanded in subsequent iterations. SmallVector ExpandedArgv; - if (!ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs, - RelativeNames)) { + if (llvm::Error Err = + ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs, + RelativeNames, FS)) { // We couldn't read this file, so we leave it in the argument stream and // move on. + // TODO: The error should be propagated up the stack. + llvm::consumeError(std::move(Err)); AllExpanded = false; ++I; continue; @@ -1186,9 +1207,14 @@ bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver, SmallVectorImpl &Argv) { - if (!ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv, - /*MarkEOLs*/ false, /*RelativeNames*/ true)) + if (llvm::Error Err = + ExpandResponseFile(CfgFile, Saver, cl::tokenizeConfigFile, Argv, + /*MarkEOLs*/ false, /*RelativeNames*/ true, + *llvm::vfs::getRealFileSystem())) { + // TODO: The error should be propagated up the stack. + llvm::consumeError(std::move(Err)); return false; + } return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv, /*MarkEOLs*/ false, /*RelativeNames*/ true); }