diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -814,15 +814,18 @@ TempPath += OutputExtension; TempPath += ".tmp"; int fd; - std::error_code EC = - llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath); + std::error_code EC = llvm::sys::fs::createUniqueFile( + TempPath, fd, TempPath, + Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text); if (CreateMissingDirectories && EC == llvm::errc::no_such_file_or_directory) { StringRef Parent = llvm::sys::path::parent_path(OutputPath); EC = llvm::sys::fs::create_directories(Parent); if (!EC) { - EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath); + EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath, + Binary ? llvm::sys::fs::OF_None + : llvm::sys::fs::OF_Text); } } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -795,7 +795,7 @@ void PrintPreprocessedAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); // Output file may need to be set to 'Binary', to avoid converting Unix style - // line feeds () to Microsoft style line feeds (). + // line feeds () to Microsoft style line feeds () on Windows. // // Look to see what type of line endings the file uses. If there's a // CRLF, then we won't open the file up in binary mode. If there is @@ -807,30 +807,35 @@ // all of their source code on a single line. However, that is still a // concern, so if we scan for too long, we'll just assume the file should // be opened in binary mode. - bool BinaryMode = true; - const SourceManager& SM = CI.getSourceManager(); - if (llvm::Optional Buffer = - SM.getBufferOrNone(SM.getMainFileID())) { - const char *cur = Buffer->getBufferStart(); - const char *end = Buffer->getBufferEnd(); - const char *next = (cur != end) ? cur + 1 : end; - - // Limit ourselves to only scanning 256 characters into the source - // file. This is mostly a sanity check in case the file has no - // newlines whatsoever. - if (end - cur > 256) end = cur + 256; - - while (next < end) { - if (*cur == 0x0D) { // CR - if (*next == 0x0A) // CRLF - BinaryMode = false; - - break; - } else if (*cur == 0x0A) // LF - break; - - ++cur; - ++next; + + bool BinaryMode = false; + if (llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows()) { + BinaryMode = true; + const SourceManager &SM = CI.getSourceManager(); + if (llvm::Optional Buffer = + SM.getBufferOrNone(SM.getMainFileID())) { + const char *cur = Buffer->getBufferStart(); + const char *end = Buffer->getBufferEnd(); + const char *next = (cur != end) ? cur + 1 : end; + + // Limit ourselves to only scanning 256 characters into the source + // file. This is mostly a sanity check in case the file has no + // newlines whatsoever. + if (end - cur > 256) + end = cur + 256; + + while (next < end) { + if (*cur == 0x0D) { // CR + if (*next == 0x0A) // CRLF + BinaryMode = false; + + break; + } else if (*cur == 0x0A) // LF + break; + + ++cur; + ++next; + } } } diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -275,11 +275,11 @@ << "' absolute: " << EC.message() << '\n'; return; } - if (std::error_code EC = - llvm::sys::fs::createUniqueFile(Model, FD, ResultPath)) { - llvm::errs() << "warning: could not create file in '" << Directory - << "': " << EC.message() << '\n'; - return; + if (std::error_code EC = llvm::sys::fs::createUniqueFile( + Model, FD, ResultPath, llvm::sys::fs::OF_Text)) { + llvm::errs() << "warning: could not create file in '" << Directory + << "': " << EC.message() << '\n'; + return; } } else { int i = 1; diff --git a/clang/tools/arcmt-test/arcmt-test.cpp b/clang/tools/arcmt-test/arcmt-test.cpp --- a/clang/tools/arcmt-test/arcmt-test.cpp +++ b/clang/tools/arcmt-test/arcmt-test.cpp @@ -207,11 +207,15 @@ static bool filesCompareEqual(StringRef fname1, StringRef fname2) { using namespace llvm; - ErrorOr> file1 = MemoryBuffer::getFile(fname1); + ErrorOr> file1 = MemoryBuffer::getFile( + fname1, /*FileSize*/ -1, /*RequiresNullTerminator*/ true, + /*IsVolatile*/ false, /*IsText*/ true); if (!file1) return false; - ErrorOr> file2 = MemoryBuffer::getFile(fname2); + ErrorOr> file2 = MemoryBuffer::getFile( + fname2, /*FileSize*/ -1, /*RequiresNullTerminator*/ true, + /*IsVolatile*/ false, /*IsText*/ true); if (!file2) return false; @@ -240,7 +244,9 @@ if (RemappingsFile.empty()) inputBuf = MemoryBuffer::getSTDIN(); else - inputBuf = MemoryBuffer::getFile(RemappingsFile); + inputBuf = MemoryBuffer::getFile(RemappingsFile, /*FileSize*/ -1, + /*RequiresNullTerminator*/ true, + /*IsVolatile*/ false, /*IsText*/ true); if (!inputBuf) { errs() << "error: could not read remappings input\n"; return true; diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h --- a/llvm/include/llvm/Support/FileSystem.h +++ b/llvm/include/llvm/Support/FileSystem.h @@ -802,10 +802,13 @@ /// @param Model Name to base unique path off of. /// @param ResultFD Set to the opened file's file descriptor. /// @param ResultPath Set to the opened file's absolute path. +/// @param Flags Set to the opened file's flags. +/// @param Mode Set to the opened file's permissions. /// @returns errc::success if Result{FD,Path} have been successfully set, /// otherwise a platform-specific error_code. std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl &ResultPath, + OpenFlags Flags = OF_None, unsigned Mode = all_read | all_write); /// Simpler version for clients that don't want an open file. An empty @@ -862,12 +865,14 @@ /// running the assembler. std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - SmallVectorImpl &ResultPath); + SmallVectorImpl &ResultPath, + OpenFlags Flags = OF_None); /// Simpler version for clients that don't want an open file. An empty /// file will still be created. std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - SmallVectorImpl &ResultPath); + SmallVectorImpl &ResultPath, + OpenFlags Flags = OF_None); std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl &ResultPath); diff --git a/llvm/include/llvm/Support/MemoryBuffer.h b/llvm/include/llvm/Support/MemoryBuffer.h --- a/llvm/include/llvm/Support/MemoryBuffer.h +++ b/llvm/include/llvm/Support/MemoryBuffer.h @@ -82,9 +82,13 @@ /// \param IsVolatile Set to true to indicate that the contents of the file /// can change outside the user's control, e.g. when libclang tries to parse /// while the user is editing/updating the file or if the file is on an NFS. + /// + /// \param IsText Set to true to indicate that the file should be read in + /// text mode. static ErrorOr> getFile(const Twine &Filename, int64_t FileSize = -1, - bool RequiresNullTerminator = true, bool IsVolatile = false); + bool RequiresNullTerminator = true, bool IsVolatile = false, + bool IsText = false); /// Read all of the specified file into a MemoryBuffer as a stream /// (i.e. until EOF reached). This is useful for special files that @@ -130,7 +134,7 @@ /// is "-". static ErrorOr> getFileOrSTDIN(const Twine &Filename, int64_t FileSize = -1, - bool RequiresNullTerminator = true); + bool RequiresNullTerminator = true, bool IsText = false); /// Map a subrange of the specified file as a MemoryBuffer. static ErrorOr> diff --git a/llvm/lib/IRReader/IRReader.cpp b/llvm/lib/IRReader/IRReader.cpp --- a/llvm/lib/IRReader/IRReader.cpp +++ b/llvm/lib/IRReader/IRReader.cpp @@ -92,7 +92,9 @@ llvm::parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context, DataLayoutCallbackTy DataLayoutCallback) { ErrorOr> FileOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); + MemoryBuffer::getFileOrSTDIN(Filename, /*FileSize*/ -1, + /*RequiresNullTerminator*/ true, + /*IsText*/ true); if (std::error_code EC = FileOrErr.getError()) { Err = SMDiagnostic(Filename, SourceMgr::DK_Error, "Could not open input file: " + EC.message()); diff --git a/llvm/lib/Support/MemoryBuffer.cpp b/llvm/lib/Support/MemoryBuffer.cpp --- a/llvm/lib/Support/MemoryBuffer.cpp +++ b/llvm/lib/Support/MemoryBuffer.cpp @@ -106,7 +106,8 @@ template static ErrorOr> getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, - uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile); + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile, + bool IsText); std::unique_ptr MemoryBuffer::getMemBuffer(StringRef InputData, StringRef BufferName, @@ -141,20 +142,20 @@ ErrorOr> MemoryBuffer::getFileOrSTDIN(const Twine &Filename, int64_t FileSize, - bool RequiresNullTerminator) { + bool RequiresNullTerminator, bool IsText) { SmallString<256> NameBuf; StringRef NameRef = Filename.toStringRef(NameBuf); if (NameRef == "-") return getSTDIN(); - return getFile(Filename, FileSize, RequiresNullTerminator); + return getFile(Filename, FileSize, RequiresNullTerminator, false, IsText); } ErrorOr> MemoryBuffer::getFileSlice(const Twine &FilePath, uint64_t MapSize, uint64_t Offset, bool IsVolatile) { return getFileAux(FilePath, -1, MapSize, Offset, false, - IsVolatile); + IsVolatile, false); } //===----------------------------------------------------------------------===// @@ -240,12 +241,12 @@ return getMemBufferCopyImpl(Buffer, BufferName); } - ErrorOr> MemoryBuffer::getFile(const Twine &Filename, int64_t FileSize, - bool RequiresNullTerminator, bool IsVolatile) { + bool RequiresNullTerminator, bool IsVolatile, + bool IsText) { return getFileAux(Filename, FileSize, FileSize, 0, - RequiresNullTerminator, IsVolatile); + RequiresNullTerminator, IsVolatile, IsText); } template @@ -257,9 +258,10 @@ template static ErrorOr> getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize, - uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile) { - Expected FDOrErr = - sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None); + uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile, + bool IsText) { + Expected FDOrErr = sys::fs::openNativeFileForRead( + Filename, IsText ? sys::fs::OF_Text : sys::fs::OF_None); if (!FDOrErr) return errorToErrorCode(FDOrErr.takeError()); sys::fs::file_t FD = *FDOrErr; @@ -274,14 +276,14 @@ bool IsVolatile) { return getFileAux(Filename, FileSize, FileSize, 0, /*RequiresNullTerminator*/ false, - IsVolatile); + IsVolatile, false); } ErrorOr> WritableMemoryBuffer::getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile) { return getFileAux(Filename, -1, MapSize, Offset, false, - IsVolatile); + IsVolatile, false); } std::unique_ptr diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp --- a/llvm/lib/Support/Path.cpp +++ b/llvm/lib/Support/Path.cpp @@ -167,8 +167,8 @@ static std::error_code createUniqueEntity(const Twine &Model, int &ResultFD, SmallVectorImpl &ResultPath, bool MakeAbsolute, - unsigned Mode, FSEntity Type, - sys::fs::OpenFlags Flags = sys::fs::OF_None) { + FSEntity Type, sys::fs::OpenFlags Flags = sys::fs::OF_None, + unsigned Mode = 0) { // Limit the number of attempts we make, so that we don't infinite loop. E.g. // "permission denied" could be for a specific file (so we retry with a @@ -816,22 +816,16 @@ std::error_code createUniqueFile(const Twine &Model, int &ResultFd, SmallVectorImpl &ResultPath, - unsigned Mode) { - return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File); -} - -static std::error_code createUniqueFile(const Twine &Model, int &ResultFd, - SmallVectorImpl &ResultPath, - unsigned Mode, OpenFlags Flags) { - return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File, - Flags); + OpenFlags Flags, unsigned Mode) { + return createUniqueEntity(Model, ResultFd, ResultPath, false, FS_File, Flags, + Mode); } std::error_code createUniqueFile(const Twine &Model, SmallVectorImpl &ResultPath, unsigned Mode) { int FD; - auto EC = createUniqueFile(Model, FD, ResultPath, Mode); + auto EC = createUniqueFile(Model, FD, ResultPath, OF_None, Mode); if (EC) return EC; // FD is only needed to avoid race conditions. Close it right away. @@ -841,34 +835,39 @@ static std::error_code createTemporaryFile(const Twine &Model, int &ResultFD, - llvm::SmallVectorImpl &ResultPath, FSEntity Type) { + llvm::SmallVectorImpl &ResultPath, FSEntity Type, + sys::fs::OpenFlags Flags = sys::fs::OF_None) { SmallString<128> Storage; StringRef P = Model.toNullTerminatedStringRef(Storage); assert(P.find_first_of(separators(Style::native)) == StringRef::npos && "Model must be a simple filename."); // Use P.begin() so that createUniqueEntity doesn't need to recreate Storage. - return createUniqueEntity(P.begin(), ResultFD, ResultPath, true, - owner_read | owner_write, Type); + return createUniqueEntity(P.begin(), ResultFD, ResultPath, true, Type, Flags, + owner_read | owner_write); } static std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - llvm::SmallVectorImpl &ResultPath, FSEntity Type) { + llvm::SmallVectorImpl &ResultPath, FSEntity Type, + sys::fs::OpenFlags Flags = sys::fs::OF_None) { const char *Middle = Suffix.empty() ? "-%%%%%%" : "-%%%%%%."; return createTemporaryFile(Prefix + Middle + Suffix, ResultFD, ResultPath, - Type); + Type, Flags); } std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, - SmallVectorImpl &ResultPath) { - return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File); + SmallVectorImpl &ResultPath, + sys::fs::OpenFlags Flags) { + return createTemporaryFile(Prefix, Suffix, ResultFD, ResultPath, FS_File, + Flags); } std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, - SmallVectorImpl &ResultPath) { + SmallVectorImpl &ResultPath, + sys::fs::OpenFlags Flags) { int FD; - auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath); + auto EC = createTemporaryFile(Prefix, Suffix, FD, ResultPath, Flags); if (EC) return EC; // FD is only needed to avoid race conditions. Close it right away. @@ -876,13 +875,12 @@ return EC; } - // This is a mkdtemp with a different pattern. We use createUniqueEntity mostly // for consistency. We should try using mkdtemp. std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl &ResultPath) { int Dummy; - return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, 0, + return createUniqueEntity(Prefix + "-%%%%%%", Dummy, ResultPath, true, FS_Dir); } @@ -890,7 +888,7 @@ getPotentiallyUniqueFileName(const Twine &Model, SmallVectorImpl &ResultPath) { int Dummy; - return createUniqueEntity(Model, Dummy, ResultPath, false, 0, FS_Name); + return createUniqueEntity(Model, Dummy, ResultPath, false, FS_Name); } std::error_code @@ -1279,7 +1277,7 @@ int FD; SmallString<128> ResultPath; if (std::error_code EC = - createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete)) + createUniqueFile(Model, FD, ResultPath, OF_Delete, Mode)) return errorCodeToError(EC); TempFile Ret(ResultPath, FD); diff --git a/llvm/lib/Support/ToolOutputFile.cpp b/llvm/lib/Support/ToolOutputFile.cpp --- a/llvm/lib/Support/ToolOutputFile.cpp +++ b/llvm/lib/Support/ToolOutputFile.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ToolOutputFile.h" +#include "llvm/ADT/Triple.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Signals.h" using namespace llvm; @@ -45,7 +46,12 @@ EC = std::error_code(); return; } - OSHolder.emplace(Filename, EC, Flags); + + // On Windows, we set the OF_None flag even for text files to avoid + // CRLF translation. + OSHolder.emplace( + Filename, EC, + llvm::Triple(LLVM_HOST_TRIPLE).isOSWindows() ? sys::fs::OF_None : Flags); OS = OSHolder.getPointer(); // If open fails, no cleanup is needed. if (EC) diff --git a/llvm/lib/TableGen/Main.cpp b/llvm/lib/TableGen/Main.cpp --- a/llvm/lib/TableGen/Main.cpp +++ b/llvm/lib/TableGen/Main.cpp @@ -70,7 +70,7 @@ return reportError(argv0, "the option -d must be used together with -o\n"); std::error_code EC; - ToolOutputFile DepOut(DependFilename, EC, sys::fs::OF_None); + ToolOutputFile DepOut(DependFilename, EC, sys::fs::OF_Text); if (EC) return reportError(argv0, "error opening " + DependFilename + ":" + EC.message() + "\n"); @@ -93,7 +93,7 @@ Records.startTimer("Parse, build records"); ErrorOr> FileOrErr = - MemoryBuffer::getFileOrSTDIN(InputFilename); + MemoryBuffer::getFileOrSTDIN(InputFilename, -1, true, true); if (std::error_code EC = FileOrErr.getError()) return reportError(argv0, "Could not open input file '" + InputFilename + "': " + EC.message() + "\n"); @@ -137,13 +137,14 @@ // Only updates the real output file if there are any differences. // This prevents recompilation of all the files depending on it if there // aren't any. - if (auto ExistingOrErr = MemoryBuffer::getFile(OutputFilename)) + if (auto ExistingOrErr = + MemoryBuffer::getFile(OutputFilename, -1, true, false, true)) if (std::move(ExistingOrErr.get())->getBuffer() == Out.str()) WriteFile = false; } if (WriteFile) { std::error_code EC; - ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None); + ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_Text); if (EC) return reportError(argv0, "error opening " + OutputFilename + ": " + EC.message() + "\n"); diff --git a/llvm/utils/FileCheck/FileCheck.cpp b/llvm/utils/FileCheck/FileCheck.cpp --- a/llvm/utils/FileCheck/FileCheck.cpp +++ b/llvm/utils/FileCheck/FileCheck.cpp @@ -821,7 +821,9 @@ // Read the expected strings from the check file. ErrorOr> CheckFileOrErr = - MemoryBuffer::getFileOrSTDIN(CheckFilename); + MemoryBuffer::getFileOrSTDIN(CheckFilename, /*FileSize*/ -1, + /*RequiresNullTerminator*/ true, + /*IsText*/ true); if (std::error_code EC = CheckFileOrErr.getError()) { errs() << "Could not open check file '" << CheckFilename << "': " << EC.message() << '\n'; @@ -843,7 +845,9 @@ // Open the file to check and add it to SourceMgr. ErrorOr> InputFileOrErr = - MemoryBuffer::getFileOrSTDIN(InputFilename); + MemoryBuffer::getFileOrSTDIN(InputFilename, /*FileSize*/ -1, + /*RequiresNullTerminator*/ true, + /*IsText*/ true); if (InputFilename == "-") InputFilename = ""; // Overwrite for improved diagnostic messages if (std::error_code EC = InputFileOrErr.getError()) {