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 @@ -766,15 +766,20 @@ 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, + llvm::sys::fs::all_read | llvm::sys::fs::all_write, + 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, + llvm::sys::fs::all_read | llvm::sys::fs::all_write, + 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,36 @@ // 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; + llvm::Triple HostTriple(LLVM_HOST_TRIPLE); + if (HostTriple.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 @@ -254,11 +254,13 @@ << "' 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, + /* Mode */ llvm::sys::fs::all_read | llvm::sys::fs::all_write, + /* Flags */ 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,11 +802,14 @@ /// @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 Mode Set to the opened file's permissions. +/// @param Flags Set to the opened file's flags. /// @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, - unsigned Mode = all_read | all_write); + unsigned Mode = all_read | all_write, + OpenFlags Flags = OF_None); /// Simpler version for clients that don't want an open file. An empty /// file will still be created. @@ -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); } //===----------------------------------------------------------------------===// @@ -243,9 +244,10 @@ 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 +259,11 @@ 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) { Expected FDOrErr = - sys::fs::openNativeFileForRead(Filename, sys::fs::OF_None); + 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 +278,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 @@ -816,13 +816,7 @@ 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) { + unsigned Mode, OpenFlags Flags) { return createUniqueEntity(Model, ResultFd, ResultPath, false, Mode, FS_File, Flags); } @@ -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); + owner_read | owner_write, Type, Flags); } 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. 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); + + llvm::Triple HostTriple(LLVM_HOST_TRIPLE); + // On Windows, we set the OF_None flag even for text files to avoid + // CRLF translation. + OSHolder.emplace(Filename, EC, + HostTriple.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 @@ -803,7 +803,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'; @@ -825,7 +827,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()) {