brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · 62f5426 Raw
111 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements \c OutputFile class methods.11///12//===----------------------------------------------------------------------===//13 14#include "llvm/Support/VirtualOutputFile.h"15#include "llvm/Support/VirtualOutputError.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/Support/raw_ostream_proxy.h"18 19using namespace llvm;20using namespace llvm::vfs;21 22char OutputFileImpl::ID = 0;23char NullOutputFileImpl::ID = 0;24 25void OutputFileImpl::anchor() {}26void NullOutputFileImpl::anchor() {}27 28class OutputFile::TrackedProxy : public raw_pwrite_stream_proxy {29public:30  void resetProxy() {31    TrackingPointer = nullptr;32    resetProxiedOS();33  }34 35  explicit TrackedProxy(TrackedProxy *&TrackingPointer, raw_pwrite_stream &OS)36      : raw_pwrite_stream_proxy(OS), TrackingPointer(TrackingPointer) {37    assert(!TrackingPointer && "Expected to add a proxy");38    TrackingPointer = this;39  }40 41  ~TrackedProxy() override { resetProxy(); }42 43  TrackedProxy *&TrackingPointer;44};45 46Expected<std::unique_ptr<raw_pwrite_stream>> OutputFile::createProxy() {47  if (OpenProxy)48    return make_error<OutputError>(getPath(), OutputErrorCode::has_open_proxy);49 50  return std::make_unique<TrackedProxy>(OpenProxy, getOS());51}52 53Error OutputFile::keep() {54  // Catch double-closing logic bugs.55  if (LLVM_UNLIKELY(!Impl))56    report_fatal_error(57        make_error<OutputError>(getPath(), OutputErrorCode::already_closed));58 59  // Report a fatal error if there's an open proxy and the file is being kept.60  // This is safer than relying on clients to remember to flush(). Also call61  // OutputFile::discard() to give the backend a chance to clean up any62  // side effects (such as temporaries).63  if (LLVM_UNLIKELY(OpenProxy))64    report_fatal_error(joinErrors(65        make_error<OutputError>(getPath(), OutputErrorCode::has_open_proxy),66        discard()));67 68  Error E = Impl->keep();69  Impl = nullptr;70  DiscardOnDestroyHandler = nullptr;71  return E;72}73 74Error OutputFile::discard() {75  // Catch double-closing logic bugs.76  if (LLVM_UNLIKELY(!Impl))77    report_fatal_error(78        make_error<OutputError>(getPath(), OutputErrorCode::already_closed));79 80  // Be lenient about open proxies since client teardown paths won't81  // necessarily clean up in the right order. Reset the proxy to flush any82  // current content; if there is another write, there should be quick crash on83  // null dereference.84  if (OpenProxy)85    OpenProxy->resetProxy();86 87  Error E = Impl->discard();88  Impl = nullptr;89  DiscardOnDestroyHandler = nullptr;90  return E;91}92 93void OutputFile::destroy() {94  if (!Impl)95    return;96 97  // Clean up the file. Move the discard handler into a local since discard98  // will reset it.99  auto DiscardHandler = std::move(DiscardOnDestroyHandler);100  Error E = discard();101  assert(!Impl && "Expected discard to destroy Impl");102 103  // If there's no handler, report a fatal error.104  if (LLVM_UNLIKELY(!DiscardHandler))105    llvm::report_fatal_error(joinErrors(106        make_error<OutputError>(getPath(), OutputErrorCode::not_closed),107        std::move(E)));108  else if (E)109    DiscardHandler(std::move(E));110}111