aboutsummaryrefslogtreecommitdiff
path: root/lib/Support/raw_ostream.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2010-09-17 15:48:55 +0000
committerDimitry Andric <dim@FreeBSD.org>2010-09-17 15:48:55 +0000
commitd39c594d39df7f283c2fb8a704a3f31c501180d9 (patch)
tree36453626c792cccd91f783a38a169d610a6b9db9 /lib/Support/raw_ostream.cpp
parent6144c1de6a7674dad94290650e4e14f24d42e421 (diff)
downloadsrc-d39c594d39df7f283c2fb8a704a3f31c501180d9.tar.gz
src-d39c594d39df7f283c2fb8a704a3f31c501180d9.zip
Vendor import of llvm r114020 (from the release_28 branch):vendor/llvm/llvm-r114020
Notes
Notes: svn path=/vendor/llvm/dist/; revision=212793 svn path=/vendor/llvm/llvm-r114020/; revision=212794; tag=vendor/llvm/llvm-r114020
Diffstat (limited to 'lib/Support/raw_ostream.cpp')
-rw-r--r--lib/Support/raw_ostream.cpp97
1 files changed, 64 insertions, 33 deletions
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index 8054ae63688c..dba46df36256 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -19,6 +19,7 @@
#include "llvm/Config/config.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/System/Signals.h"
#include "llvm/ADT/STLExtras.h"
#include <cctype>
#include <cerrno>
@@ -56,13 +57,6 @@ raw_ostream::~raw_ostream() {
if (BufferMode == InternalBuffer)
delete [] OutBufStart;
-
- // If there are any pending errors, report them now. Clients wishing
- // to avoid report_fatal_error calls should check for errors with
- // has_error() and clear the error flag with clear_error() before
- // destructing raw_ostream objects which may have errors.
- if (Error)
- report_fatal_error("IO failure on output stream.");
}
// An out of line virtual method to provide a home for the class vtable.
@@ -143,9 +137,10 @@ raw_ostream &raw_ostream::operator<<(unsigned long long N) {
}
raw_ostream &raw_ostream::operator<<(long long N) {
- if (N < 0) {
+ if (N < 0) {
*this << '-';
- N = -N;
+ // Avoid undefined behavior on INT64_MIN with a cast.
+ N = -(unsigned long long)N;
}
return this->operator<<(static_cast<unsigned long long>(N));
@@ -368,7 +363,7 @@ void format_object_base::home() {
/// stream should be immediately destroyed; the string will be empty
/// if no error occurred.
raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
- unsigned Flags) : pos(0) {
+ unsigned Flags) : Error(false), pos(0) {
assert(Filename != 0 && "Filename is null");
// Verify that we don't have both "append" and "excl".
assert((!(Flags & F_Excl) || !(Flags & F_Append)) &&
@@ -376,14 +371,17 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
ErrorInfo.clear();
- // Handle "-" as stdout.
+ // Handle "-" as stdout. Note that when we do this, we consider ourself
+ // the owner of stdout. This means that we can do things like close the
+ // file descriptor when we're done and set the "binary" flag globally.
if (Filename[0] == '-' && Filename[1] == 0) {
FD = STDOUT_FILENO;
// If user requested binary then put stdout into binary mode if
// possible.
if (Flags & F_Binary)
sys::Program::ChangeStdoutToBinary();
- ShouldClose = false;
+ // Close stdout when we're done, to detect any output errors.
+ ShouldClose = true;
return;
}
@@ -413,14 +411,22 @@ raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo,
}
raw_fd_ostream::~raw_fd_ostream() {
- if (FD < 0) return;
- flush();
- if (ShouldClose)
- while (::close(FD) != 0)
- if (errno != EINTR) {
- error_detected();
- break;
- }
+ if (FD >= 0) {
+ flush();
+ if (ShouldClose)
+ while (::close(FD) != 0)
+ if (errno != EINTR) {
+ error_detected();
+ break;
+ }
+ }
+
+ // If there are any pending errors, report them now. Clients wishing
+ // to avoid report_fatal_error calls should check for errors with
+ // has_error() and clear the error flag with clear_error() before
+ // destructing raw_ostream objects which may have errors.
+ if (has_error())
+ report_fatal_error("IO failure on output stream.");
}
@@ -534,30 +540,24 @@ bool raw_fd_ostream::is_displayed() const {
}
//===----------------------------------------------------------------------===//
-// raw_stdout/err_ostream
+// outs(), errs(), nulls()
//===----------------------------------------------------------------------===//
-// Set buffer settings to model stdout and stderr behavior.
-// Set standard error to be unbuffered by default.
-raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
-raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false,
- true) {}
-
-// An out of line virtual method to provide a home for the class vtable.
-void raw_stdout_ostream::handle() {}
-void raw_stderr_ostream::handle() {}
-
/// outs() - This returns a reference to a raw_ostream for standard output.
/// Use it like: outs() << "foo" << "bar";
raw_ostream &llvm::outs() {
- static raw_stdout_ostream S;
+ // Set buffer settings to model stdout behavior.
+ // Delete the file descriptor when the program exists, forcing error
+ // detection. If you don't want this behavior, don't use outs().
+ static raw_fd_ostream S(STDOUT_FILENO, true);
return S;
}
/// errs() - This returns a reference to a raw_ostream for standard error.
/// Use it like: errs() << "foo" << "bar";
raw_ostream &llvm::errs() {
- static raw_stderr_ostream S;
+ // Set standard error to be unbuffered by default.
+ static raw_fd_ostream S(STDERR_FILENO, false, true);
return S;
}
@@ -665,3 +665,34 @@ void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
uint64_t raw_null_ostream::current_pos() const {
return 0;
}
+
+//===----------------------------------------------------------------------===//
+// tool_output_file
+//===----------------------------------------------------------------------===//
+
+tool_output_file::CleanupInstaller::CleanupInstaller(const char *filename)
+ : Filename(filename), Keep(false) {
+ // Arrange for the file to be deleted if the process is killed.
+ if (Filename != "-")
+ sys::RemoveFileOnSignal(sys::Path(Filename));
+}
+
+tool_output_file::CleanupInstaller::~CleanupInstaller() {
+ // Delete the file if the client hasn't told us not to.
+ if (!Keep && Filename != "-")
+ sys::Path(Filename).eraseFromDisk();
+
+ // Ok, the file is successfully written and closed, or deleted. There's no
+ // further need to clean it up on signals.
+ if (Filename != "-")
+ sys::DontRemoveFileOnSignal(sys::Path(Filename));
+}
+
+tool_output_file::tool_output_file(const char *filename, std::string &ErrorInfo,
+ unsigned Flags)
+ : Installer(filename),
+ OS(filename, ErrorInfo, Flags) {
+ // If open fails, no cleanup is needed.
+ if (!ErrorInfo.empty())
+ Installer.Keep = true;
+}