[PATCH] D81525: [Support] Initialize outs() errs() nulls() once

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 19:20:38 PDT 2020


MaskRay created this revision.
MaskRay added reviewers: dblaikie, JDevlieghere, jhenderson, ikudrin, labath, probinson.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.
MaskRay edited the summary of this revision.

This makes the streams more efficient and avoid a gotcha:

- if errs() is constructed before outs()
- and if errs() is changed to a buffered state
- when destructing errs() (outs() has been destructed), the tied-to pointer to outs() is dangling.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D81525

Files:
  llvm/lib/Support/raw_ostream.cpp


Index: llvm/lib/Support/raw_ostream.cpp
===================================================================
--- llvm/lib/Support/raw_ostream.cpp
+++ llvm/lib/Support/raw_ostream.cpp
@@ -867,25 +867,39 @@
 //  outs(), errs(), nulls()
 //===----------------------------------------------------------------------===//
 
+alignas(raw_fd_ostream) static char out[sizeof(raw_fd_ostream)];
+alignas(raw_fd_ostream) static char err[sizeof(raw_fd_ostream)];
+alignas(raw_null_ostream) static char null[sizeof(raw_null_ostream)];
+
+namespace {
+struct ostream_init {
+  ostream_init() {
+    // Set buffer settings to model stdout behavior.
+    std::error_code EC;
+    auto *out_ptr = ::new (out) raw_fd_ostream("-", EC, sys::fs::OF_None);
+    assert(!EC);
+
+    // Set standard error to be unbuffered and tied to outs() by default.
+    auto *err_ptr = ::new (err) raw_fd_ostream(STDERR_FILENO, false, true);
+    err_ptr->tie(out_ptr);
+
+    ::new (null) raw_null_ostream();
+  }
+  ~ostream_init() { reinterpret_cast<raw_fd_ostream *>(out)->flush(); }
+} initializer;
+} // namespace
+
 raw_fd_ostream &llvm::outs() {
-  // Set buffer settings to model stdout behavior.
-  std::error_code EC;
-  static raw_fd_ostream S("-", EC, sys::fs::OF_None);
-  assert(!EC);
-  return S;
+  return *reinterpret_cast<raw_fd_ostream *>(out);
 }
 
 raw_fd_ostream &llvm::errs() {
-  // Set standard error to be unbuffered and tied to outs() by default.
-  static raw_fd_ostream S(STDERR_FILENO, false, true);
-  S.tie(&outs());
-  return S;
+  return *reinterpret_cast<raw_fd_ostream *>(err);
 }
 
 /// nulls() - This returns a reference to a raw_ostream which discards output.
 raw_ostream &llvm::nulls() {
-  static raw_null_ostream S;
-  return S;
+  return *reinterpret_cast<raw_null_ostream *>(null);
 }
 
 //===----------------------------------------------------------------------===//


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D81525.269720.patch
Type: text/x-patch
Size: 1878 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200610/5c128e59/attachment.bin>


More information about the llvm-commits mailing list