lawrence_danna updated this revision to Diff 221431.
lawrence_danna edited the summary of this revision.
lawrence_danna added a comment.

converted many uses of shared_ptr<File> into unique_ptr


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67891/new/

https://reviews.llvm.org/D67891

Files:
  lldb/include/lldb/Core/Debugger.h
  lldb/include/lldb/Core/IOHandler.h
  lldb/include/lldb/Core/StreamFile.h
  lldb/include/lldb/Host/File.h
  lldb/include/lldb/Host/FileCache.h
  lldb/include/lldb/Host/FileSystem.h
  lldb/include/lldb/lldb-forward.h
  lldb/scripts/Python/python-typemaps.swig
  lldb/source/API/SBDebugger.cpp
  lldb/source/API/SBStream.cpp
  lldb/source/Commands/CommandObjectBreakpointCommand.cpp
  lldb/source/Commands/CommandObjectCommands.cpp
  lldb/source/Commands/CommandObjectExpression.cpp
  lldb/source/Commands/CommandObjectGUI.cpp
  lldb/source/Commands/CommandObjectMemory.cpp
  lldb/source/Commands/CommandObjectTarget.cpp
  lldb/source/Commands/CommandObjectType.cpp
  lldb/source/Commands/CommandObjectWatchpointCommand.cpp
  lldb/source/Core/Debugger.cpp
  lldb/source/Core/IOHandler.cpp
  lldb/source/Core/StreamFile.cpp
  lldb/source/Expression/REPL.cpp
  lldb/source/Host/common/File.cpp
  lldb/source/Host/common/FileCache.cpp
  lldb/source/Host/common/FileSystem.cpp
  lldb/source/Host/windows/Host.cpp
  lldb/source/Interpreter/CommandInterpreter.cpp
  lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
  lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
  lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
  lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
  lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
  
lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
  
lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
  lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
  
lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
  lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
  lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
  lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
  lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
  lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
  lldb/source/Target/ModuleCache.cpp
  lldb/source/Target/Platform.cpp
  lldb/source/Target/Process.cpp
  lldb/source/Target/Target.cpp
  lldb/source/Target/ThreadPlanTracer.cpp
  lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp

Index: lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
===================================================================
--- lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ lldb/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -581,11 +581,14 @@
 }
 
 TEST_F(PythonDataObjectsTest, TestPythonFile) {
-  File file;
+  lldb::FileUP file;
   FileSystem::Instance().Open(file, FileSpec(FileSystem::DEV_NULL),
                               File::eOpenOptionRead);
-  PythonFile py_file(file, "r");
-  EXPECT_TRUE(PythonFile::Check(py_file.get()));
+  EXPECT_TRUE(file);
+  if (file) {
+    PythonFile py_file(*file, "r");
+    EXPECT_TRUE(PythonFile::Check(py_file.get()));
+  }
 }
 
 TEST_F(PythonDataObjectsTest, TestObjectAttributes) {
Index: lldb/source/Target/ThreadPlanTracer.cpp
===================================================================
--- lldb/source/Target/ThreadPlanTracer.cpp
+++ lldb/source/Target/ThreadPlanTracer.cpp
@@ -46,7 +46,7 @@
   else {
     TargetSP target_sp(m_thread.CalculateTarget());
     if (target_sp)
-      return target_sp->GetDebugger().GetOutputFile().get();
+      return &(target_sp->GetDebugger().GetOutputStream());
   }
   return nullptr;
 }
Index: lldb/source/Target/Target.cpp
===================================================================
--- lldb/source/Target/Target.cpp
+++ lldb/source/Target/Target.cpp
@@ -1358,15 +1358,15 @@
   if (module_sp && !module_sp->LoadScriptingResourceInTarget(
                        target, error, &feedback_stream)) {
     if (error.AsCString())
-      target->GetDebugger().GetErrorFile()->Printf(
+      target->GetDebugger().GetErrorStream().Printf(
           "unable to load scripting data for module %s - error reported was "
           "%s\n",
           module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
           error.AsCString());
   }
   if (feedback_stream.GetSize())
-    target->GetDebugger().GetErrorFile()->Printf("%s\n",
-                                                 feedback_stream.GetData());
+    target->GetDebugger().GetErrorStream().Printf("%s\n",
+                                                  feedback_stream.GetData());
 }
 
 void Target::ClearModules(bool delete_locations) {
Index: lldb/source/Target/Process.cpp
===================================================================
--- lldb/source/Target/Process.cpp
+++ lldb/source/Target/Process.cpp
@@ -1649,7 +1649,7 @@
       Address symbol_address = symbol->GetAddress();
       load_addr = ResolveIndirectFunction(&symbol_address, error);
       if (!error.Success() && show_error) {
-        GetTarget().GetDebugger().GetErrorFile()->Printf(
+        GetTarget().GetDebugger().GetErrorStream().Printf(
             "warning: failed to resolve indirect function at 0x%" PRIx64
             " for breakpoint %i.%i: %s\n",
             symbol->GetLoadAddress(&GetTarget()),
@@ -1688,7 +1688,7 @@
         } else {
           if (show_error || use_hardware) {
             // Report error for setting breakpoint...
-            GetTarget().GetDebugger().GetErrorFile()->Printf(
+            GetTarget().GetDebugger().GetErrorStream().Printf(
                 "warning: failed to set breakpoint site at 0x%" PRIx64
                 " for breakpoint %i.%i: %s\n",
                 load_addr, owner->GetBreakpoint().GetID(), owner->GetID(),
@@ -4300,9 +4300,9 @@
       : IOHandler(process->GetTarget().GetDebugger(),
                   IOHandler::Type::ProcessIO),
         m_process(process),
+        m_read_file(GetInputFD(), File::eOpenOptionRead, false),
         m_write_file(write_fd, File::eOpenOptionWrite, false) {
     m_pipe.CreateNew(false);
-    m_read_file.SetDescriptor(GetInputFD(), File::eOpenOptionRead, false);
   }
 
   ~IOHandlerProcessSTDIO() override = default;
Index: lldb/source/Target/Platform.cpp
===================================================================
--- lldb/source/Target/Platform.cpp
+++ lldb/source/Target/Platform.cpp
@@ -1226,15 +1226,15 @@
   if (fs::is_symlink_file(source.GetPath()))
     source_open_options |= File::eOpenOptionDontFollowSymlinks;
 
-  File source_file;
-  Status error = FileSystem::Instance().Open(
-      source_file, source, source_open_options, lldb::eFilePermissionsUserRW);
-  uint32_t permissions = source_file.GetPermissions(error);
+  FileUP source_file = FileSystem::Instance().Open(
+      source, source_open_options, lldb::eFilePermissionsUserRW);
+  if (!source_file || !source_file->IsValid())
+    return Status("PutFile: unable to open source file");
+  Status error;
+  uint32_t permissions = source_file->GetPermissions(error);
   if (permissions == 0)
     permissions = lldb::eFilePermissionsFileDefault;
 
-  if (!source_file.IsValid())
-    return Status("PutFile: unable to open source file");
   lldb::user_id_t dest_file = OpenFile(
       destination, File::eOpenOptionCanCreate | File::eOpenOptionWrite |
                        File::eOpenOptionTruncate | File::eOpenOptionCloseOnExec,
@@ -1249,7 +1249,7 @@
   uint64_t offset = 0;
   for (;;) {
     size_t bytes_read = buffer_sp->GetByteSize();
-    error = source_file.Read(buffer_sp->GetBytes(), bytes_read);
+    error = source_file->Read(buffer_sp->GetBytes(), bytes_read);
     if (error.Fail() || bytes_read == 0)
       break;
 
@@ -1262,7 +1262,7 @@
     if (bytes_written != bytes_read) {
       // We didn't write the correct number of bytes, so adjust the file
       // position in the source file we are reading from...
-      source_file.SeekFromStart(offset);
+      source_file->SeekFromStart(offset);
     }
   }
   CloseFile(dest_file, error);
@@ -1796,8 +1796,7 @@
   if (!process_sp)
     return nullptr;
 
-  error =
-      process_sp->ConnectRemote(debugger.GetOutputFile().get(), connect_url);
+  error = process_sp->ConnectRemote(&debugger.GetOutputStream(), connect_url);
   if (error.Fail())
     return nullptr;
 
Index: lldb/source/Target/ModuleCache.cpp
===================================================================
--- lldb/source/Target/ModuleCache.cpp
+++ lldb/source/Target/ModuleCache.cpp
@@ -48,7 +48,7 @@
 
 class ModuleLock {
 private:
-  File m_file;
+  FileUP m_file_up;
   std::unique_ptr<lldb_private::LockFile> m_lock;
   FileSpec m_file_spec;
 
@@ -157,16 +157,16 @@
     return;
 
   m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
-  FileSystem::Instance().Open(m_file, m_file_spec,
+  FileSystem::Instance().Open(m_file_up, m_file_spec,
                               File::eOpenOptionWrite |
                                   File::eOpenOptionCanCreate |
                                   File::eOpenOptionCloseOnExec);
-  if (!m_file) {
+  if (!m_file_up) {
     error.SetErrorToErrno();
     return;
   }
 
-  m_lock.reset(new lldb_private::LockFile(m_file.GetDescriptor()));
+  m_lock.reset(new lldb_private::LockFile(m_file_up->GetDescriptor()));
   error = m_lock->WriteLock(0, 1);
   if (error.Fail())
     error.SetErrorStringWithFormat("Failed to lock file: %s",
@@ -174,10 +174,11 @@
 }
 
 void ModuleLock::Delete() {
-  if (!m_file)
+  if (!m_file_up)
     return;
 
-  m_file.Close();
+  m_file_up->Close();
+  m_file_up.reset();
   llvm::sys::fs::remove(m_file_spec.GetPath());
 }
 
Index: lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -535,7 +535,7 @@
   }
 
   if (instructions) {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(instructions);
       output_sp->Flush();
@@ -571,7 +571,7 @@
         bp_options->SetCallback(
             ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
       } else if (!batch_mode) {
-        StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+        StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
         if (error_sp) {
           error_sp->Printf("Warning: No command attached to breakpoint.\n");
           error_sp->Flush();
@@ -593,7 +593,7 @@
       wp_options->SetCallback(
           ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
     } else if (!batch_mode) {
-      StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+      StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
       if (error_sp) {
         error_sp->Printf("Warning: No command attached to breakpoint.\n");
         error_sp->Flush();
@@ -724,7 +724,7 @@
     File out_file(out, false);
     File err_file(err, false);
 
-    lldb::StreamFileSP in_sp;
+    lldb::FileSP in_sp;
     lldb::StreamFileSP out_sp;
     lldb::StreamFileSP err_sp;
     if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
@@ -735,7 +735,7 @@
     } else {
       if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) {
         if (in_sp)
-          SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r");
+          SetStdHandle(*in_sp, "stdin", m_saved_stdin, "r");
       }
     }
 
@@ -854,7 +854,7 @@
     // directly down to Python.
     Debugger &debugger = m_debugger;
 
-    StreamFileSP input_file_sp;
+    FileSP input_file_sp;
     StreamFileSP output_file_sp;
     StreamFileSP error_file_sp;
     Communication output_comm(
@@ -862,7 +862,7 @@
     bool join_read_thread = false;
     if (options.GetEnableIO()) {
       if (result) {
-        input_file_sp = debugger.GetInputFile();
+        input_file_sp = debugger.GetInputFileSP();
         // Set output to a temporary file so we can forward the results on to
         // the result object
 
@@ -893,9 +893,8 @@
               ::setbuf(outfile_handle, nullptr);
 
             result->SetImmediateOutputFile(
-                debugger.GetOutputFile()->GetFile().GetStream());
-            result->SetImmediateErrorFile(
-                debugger.GetErrorFile()->GetFile().GetStream());
+                debugger.GetOutputFile().GetStream());
+            result->SetImmediateErrorFile(debugger.GetErrorFile().GetStream());
           }
         }
       }
@@ -903,20 +902,16 @@
         debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp,
                                                  error_file_sp);
     } else {
-      input_file_sp = std::make_shared<StreamFile>();
-      FileSystem::Instance().Open(input_file_sp->GetFile(),
-                                  FileSpec(FileSystem::DEV_NULL),
-                                  File::eOpenOptionRead);
 
-      output_file_sp = std::make_shared<StreamFile>();
-      FileSystem::Instance().Open(output_file_sp->GetFile(),
-                                  FileSpec(FileSystem::DEV_NULL),
-                                  File::eOpenOptionWrite);
+      input_file_sp = FileSystem::Instance().Open(
+          FileSpec(FileSystem::DEV_NULL), File::eOpenOptionRead);
 
-      error_file_sp = output_file_sp;
+      FileSP f = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL),
+                                             File::eOpenOptionWrite);
+      error_file_sp = output_file_sp = std::make_shared<StreamFile>(f);
     }
 
-    FILE *in_file = input_file_sp->GetFile().GetStream();
+    FILE *in_file = input_file_sp->GetStream();
     FILE *out_file = output_file_sp->GetFile().GetStream();
     FILE *err_file = error_file_sp->GetFile().GetStream();
     bool success = false;
@@ -1007,7 +1002,7 @@
   // a running interpreter loop inside the already running Python interpreter
   // loop, so we won't do it.
 
-  if (!debugger.GetInputFile()->GetFile().IsValid())
+  if (!debugger.GetInputFile().IsValid())
     return;
 
   IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -469,7 +469,7 @@
 
   static uint32_t GetOptionsFromMode(llvm::StringRef mode);
 
-  bool GetUnderlyingFile(File &file) const;
+  bool GetUnderlyingFile(lldb::FileSP &file) const;
 };
 
 } // namespace lldb_private
Index: lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -950,9 +950,12 @@
 PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
 
 PythonFile::PythonFile(const char *path, const char *mode) {
-  lldb_private::File file;
-  FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode));
-  Reset(file, mode);
+  lldb::FileUP file =
+      FileSystem::Instance().Open(FileSpec(path), GetOptionsFromMode(mode));
+  if (file)
+    Reset(*file, mode);
+  else
+    Reset();
 }
 
 PythonFile::PythonFile(PyRefType type, PyObject *o) { Reset(type, o); }
@@ -1036,17 +1039,20 @@
       .Default(0);
 }
 
-bool PythonFile::GetUnderlyingFile(File &file) const {
+bool PythonFile::GetUnderlyingFile(FileSP &file) const {
   if (!IsValid())
     return false;
 
-  file.Close();
+  if (file)
+    file->Close();
+
   // We don't own the file descriptor returned by this function, make sure the
   // File object knows about that.
   PythonString py_mode = GetAttributeValue("mode").AsType<PythonString>();
   auto options = PythonFile::GetOptionsFromMode(py_mode.GetString());
-  file.SetDescriptor(PyObject_AsFileDescriptor(m_py_obj), options, false);
-  return file.IsValid();
+  file = std::make_shared<File>(PyObject_AsFileDescriptor(m_py_obj), options,
+                                false);
+  return file->IsValid();
 }
 
 #endif
Index: lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
===================================================================
--- lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
+++ lldb/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.cpp
@@ -28,13 +28,13 @@
 bool ScriptInterpreterNone::ExecuteOneLine(llvm::StringRef command,
                                            CommandReturnObject *,
                                            const ExecuteScriptOptions &) {
-  m_debugger.GetErrorFile()->PutCString(
+  m_debugger.GetErrorStream().PutCString(
       "error: there is no embedded script interpreter in this mode.\n");
   return false;
 }
 
 void ScriptInterpreterNone::ExecuteInterpreterLoop() {
-  m_debugger.GetErrorFile()->PutCString(
+  m_debugger.GetErrorStream().PutCString(
       "error: there is no embedded script interpreter in this mode.\n");
 }
 
Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -99,12 +99,12 @@
 // namespace. This allows you to attach with a debugger and call this function
 // and get the packet history dumped to a file.
 void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
-  StreamFile strm;
-  Status error = FileSystem::Instance().Open(strm.GetFile(), FileSpec(path),
-                                             File::eOpenOptionWrite |
-                                                 File::eOpenOptionCanCreate);
-  if (error.Success())
-    ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
+  FileUP file = FileSystem::Instance().Open(
+      FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate);
+  if (file) {
+    StreamFile stream(std::move(file));
+    ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(stream);
+  }
 }
 } // namespace lldb
 
Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
===================================================================
--- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -512,14 +512,15 @@
         mode_t mode = packet.GetHexMaxU32(false, 0600);
         FileSpec path_spec(path);
         FileSystem::Instance().Resolve(path_spec);
-        File file;
+        FileUP file;
         // Do not close fd.
         Status error =
             FileSystem::Instance().Open(file, path_spec, flags, mode, false);
         const int save_errno = error.GetError();
         StreamString response;
         response.PutChar('F');
-        response.Printf("%i", file.GetDescriptor());
+        response.Printf("%i", file ? file->GetDescriptor()
+                                   : File::kInvalidDescriptor);
         if (save_errno)
           response.Printf(",%i", save_errno);
         return SendPacketNoLock(response.GetString());
Index: lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
===================================================================
--- lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
+++ lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -382,7 +382,7 @@
 
 static Status HandleFileAction(ProcessLaunchInfo &launch_info,
                                NSMutableDictionary *options, NSString *key,
-                               const int fd, File &file) {
+                               const int fd, lldb::FileSP &file) {
   Status error;
   const FileAction *file_action = launch_info.GetFileActionForFD(fd);
   if (file_action) {
@@ -434,7 +434,7 @@
             file_options |= File::eOpenOptionRead;
           if ((oflag & O_RDWR) || (oflag & O_RDONLY))
             file_options |= File::eOpenOptionWrite;
-          file.SetDescriptor(created_fd, file_options, true);
+          file = std::make_shared<File>(created_fd, file_options, true);
           [options setValue:[NSNumber numberWithInteger:created_fd] forKey:key];
           return error; // Success
         } else {
@@ -494,9 +494,9 @@
   [options setObject:env_dict forKey:kSimDeviceSpawnEnvironment];
 
   Status error;
-  File stdin_file;
-  File stdout_file;
-  File stderr_file;
+  lldb::FileSP stdin_file;
+  lldb::FileSP stdout_file;
+  lldb::FileSP stderr_file;
   error = HandleFileAction(launch_info, options, kSimDeviceSpawnStdin,
                            STDIN_FILENO, stdin_file);
 
Index: lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
===================================================================
--- lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -6271,22 +6271,22 @@
             buffer.PutHex32(segment.flags);
           }
 
-          File core_file;
+          FileUP core_file;
           std::string core_file_path(outfile.GetPath());
           error = FileSystem::Instance().Open(core_file, outfile,
                                               File::eOpenOptionWrite |
                                                   File::eOpenOptionTruncate |
                                                   File::eOpenOptionCanCreate);
-          if (error.Success()) {
+          if (error.Success() && core_file) {
             // Read 1 page at a time
             uint8_t bytes[0x1000];
             // Write the mach header and load commands out to the core file
             size_t bytes_written = buffer.GetString().size();
-            error = core_file.Write(buffer.GetString().data(), bytes_written);
+            error = core_file->Write(buffer.GetString().data(), bytes_written);
             if (error.Success()) {
               // Now write the file data for all memory segments in the process
               for (const auto &segment : segment_load_commands) {
-                if (core_file.SeekFromStart(segment.fileoff) == -1) {
+                if (core_file->SeekFromStart(segment.fileoff) == -1) {
                   error.SetErrorStringWithFormat(
                       "unable to seek to offset 0x%" PRIx64 " in '%s'",
                       segment.fileoff, core_file_path.c_str());
@@ -6311,7 +6311,7 @@
 
                   if (bytes_read == bytes_to_read) {
                     size_t bytes_written = bytes_read;
-                    error = core_file.Write(bytes, bytes_written);
+                    error = core_file->Write(bytes, bytes_written);
                     bytes_left -= bytes_read;
                     addr += bytes_read;
                   } else {
@@ -6319,7 +6319,7 @@
                     // be zero filled
                     memset(bytes, 0, bytes_to_read);
                     size_t bytes_written = bytes_to_read;
-                    error = core_file.Write(bytes, bytes_written);
+                    error = core_file->Write(bytes, bytes_written);
                     bytes_left -= bytes_to_read;
                     addr += bytes_to_read;
                   }
Index: lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
===================================================================
--- lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -2651,11 +2651,9 @@
   // Check we can create writable file
   FileSpec file_spec(path);
   FileSystem::Instance().Resolve(file_spec);
-  File file;
-  FileSystem::Instance().Open(file, file_spec,
-                              File::eOpenOptionWrite |
-                                  File::eOpenOptionCanCreate |
-                                  File::eOpenOptionTruncate);
+  FileUP file = FileSystem::Instance().Open(
+      file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
+                     File::eOpenOptionTruncate);
 
   if (!file) {
     strm.Printf("Error: Failed to open '%s' for writing", path);
@@ -2690,7 +2688,7 @@
   LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
             (uint64_t)num_bytes);
 
-  Status err = file.Write(&head, num_bytes);
+  Status err = file->Write(&head, num_bytes);
   if (!err.Success()) {
     strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
     strm.EOL();
@@ -2715,7 +2713,7 @@
   LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.",
             __FUNCTION__, (uint64_t)num_bytes);
 
-  err = file.Write(element_header_buffer.get(), num_bytes);
+  err = file->Write(element_header_buffer.get(), num_bytes);
   if (!err.Success()) {
     strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
     strm.EOL();
@@ -2727,7 +2725,7 @@
   LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
             (uint64_t)num_bytes);
 
-  err = file.Write(buffer.get(), num_bytes);
+  err = file->Write(buffer.get(), num_bytes);
   if (!err.Success()) {
     strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
     strm.EOL();
@@ -4585,10 +4583,10 @@
     if (outfile_spec) {
       // Open output file
       std::string path = outfile_spec.GetPath();
-      auto error = FileSystem::Instance().Open(
-          outfile_stream.GetFile(), outfile_spec,
-          File::eOpenOptionWrite | File::eOpenOptionCanCreate);
-      if (error.Success()) {
+      FileUP file = FileSystem::Instance().Open(
+          outfile_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate);
+      outfile_stream.SetFile(std::move(file));
+      if (outfile_stream.GetFile()) {
         output_strm = &outfile_stream;
         result.GetOutputStream().Printf("Results written to '%s'",
                                         path.c_str());
Index: lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
===================================================================
--- lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -704,7 +704,7 @@
     // step through any method dispatches.  Warn to that effect and get out of
     // here.
     if (process_sp->CanJIT()) {
-      process_sp->GetTarget().GetDebugger().GetErrorFile()->Printf(
+      process_sp->GetTarget().GetDebugger().GetErrorStream().Printf(
           "Could not find implementation lookup function \"%s\""
           " step in through ObjC method dispatch will not work.\n",
           get_impl_name.AsCString());
Index: lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
===================================================================
--- lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
+++ lldb/source/Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.cpp
@@ -124,7 +124,7 @@
   if (!frame_sp)
     return StructuredData::ObjectSP();
 
-  StreamFileSP Stream(target.GetDebugger().GetOutputFile());
+  StreamFileSP Stream = target.GetDebugger().GetOutputStreamSP();
 
   EvaluateExpressionOptions options;
   options.SetUnwindOnError(true);
Index: lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
===================================================================
--- lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
+++ lldb/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.cpp
@@ -863,13 +863,11 @@
               CreateStopReasonWithInstrumentationData(
                   *thread_sp, stop_reason_description, report));
 
-    StreamFileSP stream_sp(
-        process_sp->GetTarget().GetDebugger().GetOutputFile());
-    if (stream_sp) {
-      stream_sp->Printf("ThreadSanitizer report breakpoint hit. Use 'thread "
-                        "info -s' to get extended information about the "
-                        "report.\n");
-    }
+    StreamFile &s = process_sp->GetTarget().GetDebugger().GetOutputStream();
+    s.Printf("ThreadSanitizer report breakpoint hit. Use 'thread "
+             "info -s' to get extended information about the "
+             "report.\n");
+
     return true; // Return true to stop the target
   } else
     return false; // Let target run
Index: lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
===================================================================
--- lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
+++ lldb/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.cpp
@@ -264,7 +264,7 @@
                                      *thread_sp, description, report));
 
     StreamFileSP stream_sp(
-        process_sp->GetTarget().GetDebugger().GetOutputFile());
+        process_sp->GetTarget().GetDebugger().GetOutputStreamSP());
     if (stream_sp) {
       stream_sp->Printf("AddressSanitizer report breakpoint hit. Use 'thread "
                         "info -s' to get extended information about the "
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1228,12 +1228,10 @@
       type_system_helper->DeclMap(); // result can be NULL
 
   if (decl_map) {
-    Stream *error_stream = nullptr;
     Target *target = exe_ctx.GetTargetPtr();
-    error_stream = target->GetDebugger().GetErrorFile().get();
-
+    auto &error_stream = target->GetDebugger().GetErrorStream();
     IRForTarget ir_for_target(decl_map, m_expr.NeedsVariableResolution(),
-                              *execution_unit_sp, *error_stream,
+                              *execution_unit_sp, error_stream,
                               function_name.AsCString());
 
     bool ir_can_run =
Index: lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
===================================================================
--- lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -773,12 +773,9 @@
   }
 
   if (IsKernel() && m_uuid.IsValid()) {
-    Stream *s = target.GetDebugger().GetOutputFile().get();
-    if (s) {
-      s->Printf("Kernel UUID: %s\n",
-                m_uuid.GetAsString().c_str());
-      s->Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
-    }
+    Stream &s = target.GetDebugger().GetOutputStream();
+    s.Printf("Kernel UUID: %s\n", m_uuid.GetAsString().c_str());
+    s.Printf("Load Address: 0x%" PRIx64 "\n", m_load_address);
   }
 
   if (!m_module_sp) {
@@ -839,11 +836,9 @@
       }
 
       if (IsKernel() && !m_module_sp) {
-        Stream *s = target.GetDebugger().GetOutputFile().get();
-        if (s) {
-          s->Printf("WARNING: Unable to locate kernel binary on the debugger "
-                    "system.\n");
-        }
+        Stream &s = target.GetDebugger().GetOutputStream();
+        s.Printf("WARNING: Unable to locate kernel binary on the debugger "
+                 "system.\n");
       }
     }
 
@@ -932,25 +927,24 @@
   bool is_loaded = IsLoaded();
 
   if (is_loaded && m_module_sp && IsKernel()) {
-    Stream *s = target.GetDebugger().GetOutputFile().get();
-    if (s) {
-      ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
-      if (kernel_object_file) {
-        addr_t file_address =
-            kernel_object_file->GetBaseAddress().GetFileAddress();
-        if (m_load_address != LLDB_INVALID_ADDRESS &&
-            file_address != LLDB_INVALID_ADDRESS) {
-          s->Printf("Kernel slid 0x%" PRIx64 " in memory.\n",
-                    m_load_address - file_address);
-        }
+    Stream &s = target.GetDebugger().GetOutputStream();
+    ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
+    if (kernel_object_file) {
+      addr_t file_address =
+          kernel_object_file->GetBaseAddress().GetFileAddress();
+      if (m_load_address != LLDB_INVALID_ADDRESS &&
+          file_address != LLDB_INVALID_ADDRESS) {
+        s.Printf("Kernel slid 0x%" PRIx64 " in memory.\n",
+                 m_load_address - file_address);
       }
-      {
-        s->Printf("Loaded kernel file %s\n",
-                  m_module_sp->GetFileSpec().GetPath().c_str());
-      }
-      s->Flush();
     }
+    {
+      s.Printf("Loaded kernel file %s\n",
+               m_module_sp->GetFileSpec().GetPath().c_str());
+    }
+    s.Flush();
   }
+
   return is_loaded;
 }
 
@@ -1109,11 +1103,10 @@
           lldb::offset_t offset = 0;
           m_kext_summary_header.version = data.GetU32(&offset);
           if (m_kext_summary_header.version > 128) {
-            Stream *s =
-                m_process->GetTarget().GetDebugger().GetOutputFile().get();
-            s->Printf("WARNING: Unable to read kext summary header, got "
-                      "improbable version number %u\n",
-                      m_kext_summary_header.version);
+            Stream &s = m_process->GetTarget().GetDebugger().GetOutputStream();
+            s.Printf("WARNING: Unable to read kext summary header, got "
+                     "improbable version number %u\n",
+                     m_kext_summary_header.version);
             // If we get an improbably large version number, we're probably
             // getting bad memory.
             m_kext_summary_header_addr.Clear();
@@ -1124,11 +1117,11 @@
             if (m_kext_summary_header.entry_size > 4096) {
               // If we get an improbably large entry_size, we're probably
               // getting bad memory.
-              Stream *s =
-                  m_process->GetTarget().GetDebugger().GetOutputFile().get();
-              s->Printf("WARNING: Unable to read kext summary header, got "
-                        "improbable entry_size %u\n",
-                        m_kext_summary_header.entry_size);
+              Stream &s =
+                  m_process->GetTarget().GetDebugger().GetOutputStream();
+              s.Printf("WARNING: Unable to read kext summary header, got "
+                       "improbable entry_size %u\n",
+                       m_kext_summary_header.entry_size);
               m_kext_summary_header_addr.Clear();
               return false;
             }
@@ -1142,11 +1135,10 @@
           if (m_kext_summary_header.entry_count > 10000) {
             // If we get an improbably large number of kexts, we're probably
             // getting bad memory.
-            Stream *s =
-                m_process->GetTarget().GetDebugger().GetOutputFile().get();
-            s->Printf("WARNING: Unable to read kext summary header, got "
-                      "improbable number of kexts %u\n",
-                      m_kext_summary_header.entry_count);
+            Stream &s = m_process->GetTarget().GetDebugger().GetOutputStream();
+            s.Printf("WARNING: Unable to read kext summary header, got "
+                     "improbable number of kexts %u\n",
+                     m_kext_summary_header.entry_count);
             m_kext_summary_header_addr.Clear();
             return false;
           }
@@ -1247,18 +1239,17 @@
       number_of_old_kexts_being_removed == 0)
     return true;
 
-  Stream *s = m_process->GetTarget().GetDebugger().GetOutputFile().get();
-  if (s && load_kexts) {
+  Stream &s = m_process->GetTarget().GetDebugger().GetOutputStream();
+  if (load_kexts) {
     if (number_of_new_kexts_being_added > 0 &&
         number_of_old_kexts_being_removed > 0) {
-      s->Printf("Loading %d kext modules and unloading %d kext modules ",
-                number_of_new_kexts_being_added,
-                number_of_old_kexts_being_removed);
+      s.Printf("Loading %d kext modules and unloading %d kext modules ",
+               number_of_new_kexts_being_added,
+               number_of_old_kexts_being_removed);
     } else if (number_of_new_kexts_being_added > 0) {
-      s->Printf("Loading %d kext modules ", number_of_new_kexts_being_added);
+      s.Printf("Loading %d kext modules ", number_of_new_kexts_being_added);
     } else if (number_of_old_kexts_being_removed > 0) {
-      s->Printf("Unloading %d kext modules ",
-                number_of_old_kexts_being_removed);
+      s.Printf("Unloading %d kext modules ", number_of_old_kexts_being_removed);
     }
   }
 
@@ -1304,11 +1295,11 @@
             m_process->GetStopID() == image_info.GetProcessStopId())
           loaded_module_list.AppendIfNeeded(image_info.GetModule());
 
-        if (s && load_kexts) {
+        if (load_kexts) {
           if (kext_successfully_added)
-            s->Printf(".");
+            s.Printf(".");
           else
-            s->Printf("-");
+            s.Printf("-");
         }
 
         if (log)
@@ -1330,8 +1321,7 @@
           if (image_info.GetModule()) {
             unloaded_module_list.AppendIfNeeded(image_info.GetModule());
           }
-          if (s)
-            s->Printf(".");
+          s.Printf(".");
           image_info.Clear();
           // should pull it out of the KextImageInfos vector but that would
           // mutate the list and invalidate the to_be_removed bool vector;
@@ -1342,12 +1332,12 @@
     }
   }
 
-  if (s && load_kexts) {
-    s->Printf(" done.\n");
+  if (load_kexts) {
+    s.Printf(" done.\n");
     if (kexts_failed_to_load.size() > 0 && number_of_new_kexts_being_added > 0) {
-      s->Printf("Failed to load %d of %d kexts:\n",
-                (int)kexts_failed_to_load.size(),
-                number_of_new_kexts_being_added);
+      s.Printf("Failed to load %d of %d kexts:\n",
+               (int)kexts_failed_to_load.size(),
+               number_of_new_kexts_being_added);
       // print a sorted list of <kext-name, uuid> kexts which failed to load
       unsigned longest_name = 0;
       std::sort(kexts_failed_to_load.begin(), kexts_failed_to_load.end());
@@ -1359,10 +1349,10 @@
         std::string uuid;
         if (ku.second.IsValid())
           uuid = ku.second.GetAsString();
-        s->Printf (" %-*s %s\n", longest_name, ku.first.c_str(), uuid.c_str());
+        s.Printf(" %-*s %s\n", longest_name, ku.first.c_str(), uuid.c_str());
       }
     }
-    s->Flush();
+    s.Flush();
   }
 
   return true;
Index: lldb/source/Interpreter/CommandInterpreter.cpp
===================================================================
--- lldb/source/Interpreter/CommandInterpreter.cpp
+++ lldb/source/Interpreter/CommandInterpreter.cpp
@@ -2315,18 +2315,18 @@
     return;
   }
 
-  StreamFileSP input_file_sp(new StreamFile());
   std::string cmd_file_path = cmd_file.GetPath();
-  Status error = FileSystem::Instance().Open(input_file_sp->GetFile(), cmd_file,
+  FileUP input_file_p;
+  Status error = FileSystem::Instance().Open(input_file_p, cmd_file,
                                              File::eOpenOptionRead);
-
-  if (error.Fail()) {
+  if (!input_file_p || error.Fail()) {
     result.AppendErrorWithFormat(
         "error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(),
         error.AsCString());
     result.SetStatus(eReturnStatusFailed);
     return;
   }
+  FileSP input_file_sp = FileSP(std::move(input_file_p));
 
   Debugger &debugger = GetDebugger();
 
@@ -2412,8 +2412,8 @@
   }
 
   if (flags & eHandleCommandFlagPrintResult) {
-    debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n",
-                                     cmd_file_path.c_str());
+    debugger.GetOutputFile().Printf("Executing commands in '%s'.\n",
+                                    cmd_file_path.c_str());
   }
 
   // Used for inheriting the right settings when "command source" might
@@ -2713,8 +2713,8 @@
     // from a file) we need to echo the command out so we don't just see the
     // command output and no command...
     if (EchoCommandNonInteractive(line, io_handler.GetFlags()))
-      io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(),
-                                               line.c_str());
+      io_handler.GetOutputStreamFileSP()->Printf(
+          "%s%s\n", io_handler.GetPrompt(), line.c_str());
   }
 
   StartHandlingCommand();
@@ -2731,13 +2731,13 @@
 
     if (!result.GetImmediateOutputStream()) {
       llvm::StringRef output = result.GetOutputData();
-      PrintCommandOutput(*io_handler.GetOutputStreamFile(), output);
+      PrintCommandOutput(*io_handler.GetOutputStreamFileSP(), output);
     }
 
     // Now emit the command error text from the command we just executed
     if (!result.GetImmediateErrorStream()) {
       llvm::StringRef error = result.GetErrorData();
-      PrintCommandOutput(*io_handler.GetErrorStreamFile(), error);
+      PrintCommandOutput(*io_handler.GetErrorStreamFileSP(), error);
     }
   }
 
@@ -2904,8 +2904,8 @@
 
     m_command_io_handler_sp = std::make_shared<IOHandlerEditline>(
         m_debugger, IOHandler::Type::CommandInterpreter,
-        m_debugger.GetInputFile(), m_debugger.GetOutputFile(),
-        m_debugger.GetErrorFile(), flags, "lldb", m_debugger.GetPrompt(),
+        m_debugger.GetInputFileSP(), m_debugger.GetOutputStreamSP(),
+        m_debugger.GetErrorStreamSP(), flags, "lldb", m_debugger.GetPrompt(),
         llvm::StringRef(), // Continuation prompt
         false, // Don't enable multiple line input, just single line commands
         m_debugger.GetUseColor(),
Index: lldb/source/Host/windows/Host.cpp
===================================================================
--- lldb/source/Host/windows/Host.cpp
+++ lldb/source/Host/windows/Host.cpp
@@ -34,9 +34,11 @@
 bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) {
   // Open the PE File as a binary file, and parse just enough information to
   // determine the machine type.
-  File imageBinary;
-  FileSystem::Instance().Open(imageBinary, executable, File::eOpenOptionRead,
-                              lldb::eFilePermissionsUserRead);
+  FileUP imageBinaryP = FileSystem::Instance().Open(
+      executable, File::eOpenOptionRead, lldb::eFilePermissionsUserRead);
+  if (!imageBinaryP)
+    return false;
+  File &imageBinary = *imageBinaryP;
   imageBinary.SeekFromStart(0x3c);
   int32_t peOffset = 0;
   uint32_t peHead = 0;
Index: lldb/source/Host/common/FileSystem.cpp
===================================================================
--- lldb/source/Host/common/FileSystem.cpp
+++ lldb/source/Host/common/FileSystem.cpp
@@ -415,13 +415,13 @@
   return mode;
 }
 
-Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options,
-                        uint32_t permissions, bool should_close_fd) {
+Status FileSystem::Open(lldb::FileUP &fileup, const FileSpec &file_spec,
+                        uint32_t options, uint32_t permissions,
+                        bool should_close_fd) {
   if (m_collector)
     m_collector->addFile(file_spec.GetPath());
 
-  if (File.IsValid())
-    File.Close();
+  fileup.reset();
 
   const int open_flags = GetOpenFlags(options);
   const mode_t open_mode =
@@ -436,11 +436,13 @@
 
   Status error;
   if (!File::DescriptorIsValid(descriptor)) {
-    File.SetDescriptor(-1, options, false);
+    errno = EINVAL;
     error.SetErrorToErrno();
   } else {
-    File.SetDescriptor(descriptor, options, should_close_fd);
+    fileup = std::make_unique<File>(descriptor, options, should_close_fd);
   }
+  if (fileup && !fileup->IsValid())
+    fileup.reset();
   return error;
 }
 
Index: lldb/source/Host/common/FileCache.cpp
===================================================================
--- lldb/source/Host/common/FileCache.cpp
+++ lldb/source/Host/common/FileCache.cpp
@@ -29,12 +29,12 @@
     error.SetErrorString("empty path");
     return UINT64_MAX;
   }
-  FileSP file_sp(new File());
-  error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode);
-  if (!file_sp->IsValid())
+  FileUP file_up;
+  error = FileSystem::Instance().Open(file_up, file_spec, flags, mode);
+  if (!file_up)
     return UINT64_MAX;
-  lldb::user_id_t fd = file_sp->GetDescriptor();
-  m_cache[fd] = file_sp;
+  lldb::user_id_t fd = file_up->GetDescriptor();
+  m_cache[fd] = std::move(file_up);
   return fd;
 }
 
@@ -48,12 +48,12 @@
     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
     return false;
   }
-  FileSP file_sp = pos->second;
-  if (!file_sp) {
+  FileUP &file_up = pos->second;
+  if (!file_up) {
     error.SetErrorString("invalid host backing file");
     return false;
   }
-  error = file_sp->Close();
+  error = file_up->Close();
   m_cache.erase(pos);
   return error.Success();
 }
@@ -70,16 +70,16 @@
     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
     return false;
   }
-  FileSP file_sp = pos->second;
-  if (!file_sp) {
+  FileUP &file_up = pos->second;
+  if (!file_up) {
     error.SetErrorString("invalid host backing file");
     return UINT64_MAX;
   }
-  if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
+  if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
       error.Fail())
     return UINT64_MAX;
   size_t bytes_written = src_len;
-  error = file_sp->Write(src, bytes_written);
+  error = file_up->Write(src, bytes_written);
   if (error.Fail())
     return UINT64_MAX;
   return bytes_written;
@@ -96,16 +96,16 @@
     error.SetErrorStringWithFormat("invalid host file descriptor %" PRIu64, fd);
     return false;
   }
-  FileSP file_sp = pos->second;
-  if (!file_sp) {
+  FileUP &file_up = pos->second;
+  if (!file_up) {
     error.SetErrorString("invalid host backing file");
     return UINT64_MAX;
   }
-  if (static_cast<uint64_t>(file_sp->SeekFromStart(offset, &error)) != offset ||
+  if (static_cast<uint64_t>(file_up->SeekFromStart(offset, &error)) != offset ||
       error.Fail())
     return UINT64_MAX;
   size_t bytes_read = dst_len;
-  error = file_sp->Read(dst, bytes_read);
+  error = file_up->Read(dst, bytes_read);
   if (error.Fail())
     return UINT64_MAX;
   return bytes_read;
Index: lldb/source/Host/common/File.cpp
===================================================================
--- lldb/source/Host/common/File.cpp
+++ lldb/source/Host/common/File.cpp
@@ -93,14 +93,6 @@
 
 IOObject::WaitableHandle File::GetWaitableHandle() { return GetDescriptor(); }
 
-void File::SetDescriptor(int fd, uint32_t options, bool transfer_ownership) {
-  if (IsValid())
-    Close();
-  m_descriptor = fd;
-  m_should_close_fd = transfer_ownership;
-  m_options = options;
-}
-
 FILE *File::GetStream() {
   if (!StreamIsValid()) {
     if (DescriptorIsValid()) {
@@ -133,13 +125,6 @@
   return m_stream;
 }
 
-void File::SetStream(FILE *fh, bool transfer_ownership) {
-  if (IsValid())
-    Close();
-  m_stream = fh;
-  m_own_stream = transfer_ownership;
-}
-
 uint32_t File::GetPermissions(Status &error) const {
   int fd = GetDescriptor();
   if (fd != kInvalidDescriptor) {
Index: lldb/source/Expression/REPL.cpp
===================================================================
--- lldb/source/Expression/REPL.cpp
+++ lldb/source/Expression/REPL.cpp
@@ -96,7 +96,7 @@
   lldb::ProcessSP process_sp = m_target.GetProcessSP();
   if (process_sp && process_sp->IsAlive())
     return;
-  lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+  lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
   error_sp->Printf("REPL requires a running target process.\n");
   io_handler.SetIsDone(true);
 }
@@ -180,8 +180,8 @@
 }
 
 void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
-  lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFile());
-  lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+  lldb::StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
+  lldb::StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
   bool extra_line = false;
   bool did_quit = false;
 
@@ -398,17 +398,18 @@
 
           // Update our code on disk
           if (!m_repl_source_path.empty()) {
-            lldb_private::File file;
-            FileSystem::Instance().Open(file, FileSpec(m_repl_source_path),
-                                        File::eOpenOptionWrite |
-                                            File::eOpenOptionTruncate |
-                                            File::eOpenOptionCanCreate,
-                                        lldb::eFilePermissionsFileDefault);
-            std::string code(m_code.CopyList());
-            code.append(1, '\n');
-            size_t bytes_written = code.size();
-            file.Write(code.c_str(), bytes_written);
-            file.Close();
+            lldb::FileUP file = FileSystem::Instance().Open(
+                FileSpec(m_repl_source_path),
+                File::eOpenOptionWrite | File::eOpenOptionTruncate |
+                    File::eOpenOptionCanCreate,
+                lldb::eFilePermissionsFileDefault);
+            if (file) {
+              std::string code(m_code.CopyList());
+              code.append(1, '\n');
+              size_t bytes_written = code.size();
+              file->Write(code.c_str(), bytes_written);
+              file->Close();
+            }
 
             // Now set the default file and line to the REPL source file
             m_target.GetSourceManager().SetDefaultFileAndLine(
Index: lldb/source/Core/StreamFile.cpp
===================================================================
--- lldb/source/Core/StreamFile.cpp
+++ lldb/source/Core/StreamFile.cpp
@@ -15,35 +15,42 @@
 using namespace lldb_private;
 
 // StreamFile constructor
-StreamFile::StreamFile() : Stream(), m_file() {}
+StreamFile::StreamFile() : Stream() { m_file_sp = std::make_shared<File>(); }
 
 StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
-    : Stream(flags, addr_size, byte_order), m_file() {}
+    : Stream(flags, addr_size, byte_order) {
+  m_file_sp = std::make_shared<File>();
+}
 
-StreamFile::StreamFile(int fd, bool transfer_ownership)
-    : Stream(), m_file(fd, File::eOpenOptionWrite, transfer_ownership) {}
+StreamFile::StreamFile(int fd, bool transfer_ownership) : Stream() {
+  m_file_sp =
+      std::make_shared<File>(fd, File::eOpenOptionWrite, transfer_ownership);
+}
 
-StreamFile::StreamFile(FILE *fh, bool transfer_ownership)
-    : Stream(), m_file(fh, transfer_ownership) {}
+StreamFile::StreamFile(FILE *fh, bool transfer_ownership) : Stream() {
+  m_file_sp = std::make_shared<File>(fh, transfer_ownership);
+}
 
-StreamFile::StreamFile(const char *path) : Stream(), m_file() {
-  FileSystem::Instance().Open(m_file, FileSpec(path),
-                              File::eOpenOptionWrite |
-                                  File::eOpenOptionCanCreate |
-                                  File::eOpenOptionCloseOnExec);
+StreamFile::StreamFile(const char *path) : Stream() {
+  m_file_sp = FileSystem::Instance().Open(
+      FileSpec(path), File::eOpenOptionWrite | File::eOpenOptionCanCreate |
+                          File::eOpenOptionCloseOnExec);
+  if (!m_file_sp)
+    m_file_sp = std::make_shared<File>();
 }
 
 StreamFile::StreamFile(const char *path, uint32_t options, uint32_t permissions)
-    : Stream(), m_file() {
-
-  FileSystem::Instance().Open(m_file, FileSpec(path), options, permissions);
+    : Stream() {
+  m_file_sp = FileSystem::Instance().Open(FileSpec(path), options, permissions);
+  if (!m_file_sp)
+    m_file_sp = std::make_shared<File>();
 }
 
 StreamFile::~StreamFile() {}
 
-void StreamFile::Flush() { m_file.Flush(); }
+void StreamFile::Flush() { m_file_sp->Flush(); }
 
 size_t StreamFile::WriteImpl(const void *s, size_t length) {
-  m_file.Write(s, length);
+  m_file_sp->Write(s, length);
   return length;
 }
Index: lldb/source/Core/IOHandler.cpp
===================================================================
--- lldb/source/Core/IOHandler.cpp
+++ lldb/source/Core/IOHandler.cpp
@@ -73,7 +73,7 @@
 
 IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type)
     : IOHandler(debugger, type,
-                StreamFileSP(), // Adopt STDIN from top input reader
+                FileSP(),       // Adopt STDIN from top input reader
                 StreamFileSP(), // Adopt STDOUT from top input reader
                 StreamFileSP(), // Adopt STDERR from top input reader
                 0,              // Flags
@@ -81,7 +81,7 @@
       ) {}
 
 IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type,
-                     const lldb::StreamFileSP &input_sp,
+                     const lldb::FileSP &input_sp,
                      const lldb::StreamFileSP &output_sp,
                      const lldb::StreamFileSP &error_sp, uint32_t flags,
                      repro::DataRecorder *data_recorder)
@@ -98,7 +98,7 @@
 IOHandler::~IOHandler() = default;
 
 int IOHandler::GetInputFD() {
-  return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1);
+  return (m_input_sp ? m_input_sp->GetDescriptor() : -1);
 }
 
 int IOHandler::GetOutputFD() {
@@ -110,7 +110,7 @@
 }
 
 FILE *IOHandler::GetInputFILE() {
-  return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr);
+  return (m_input_sp ? m_input_sp->GetStream() : nullptr);
 }
 
 FILE *IOHandler::GetOutputFILE() {
@@ -121,18 +121,18 @@
   return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr);
 }
 
-StreamFileSP &IOHandler::GetInputStreamFile() { return m_input_sp; }
+FileSP &IOHandler::GetInputFileSP() { return m_input_sp; }
 
-StreamFileSP &IOHandler::GetOutputStreamFile() { return m_output_sp; }
+StreamFileSP &IOHandler::GetOutputStreamFileSP() { return m_output_sp; }
 
-StreamFileSP &IOHandler::GetErrorStreamFile() { return m_error_sp; }
+StreamFileSP &IOHandler::GetErrorStreamFileSP() { return m_error_sp; }
 
 bool IOHandler::GetIsInteractive() {
-  return GetInputStreamFile()->GetFile().GetIsInteractive();
+  return GetInputFileSP() ? GetInputFileSP()->GetIsInteractive() : false;
 }
 
 bool IOHandler::GetIsRealTerminal() {
-  return GetInputStreamFile()->GetFile().GetIsRealTerminal();
+  return GetInputFileSP() ? GetInputFileSP()->GetIsRealTerminal() : false;
 }
 
 void IOHandler::SetPopped(bool b) { m_popped.SetValue(b, eBroadcastOnChange); }
@@ -235,7 +235,7 @@
     bool multi_line, bool color_prompts, uint32_t line_number_start,
     IOHandlerDelegate &delegate, repro::DataRecorder *data_recorder)
     : IOHandlerEditline(debugger, type,
-                        StreamFileSP(), // Inherit input from top input reader
+                        FileSP(),       // Inherit input from top input reader
                         StreamFileSP(), // Inherit output from top input reader
                         StreamFileSP(), // Inherit error from top input reader
                         0,              // Flags
@@ -244,9 +244,9 @@
                         line_number_start, delegate, data_recorder) {}
 
 IOHandlerEditline::IOHandlerEditline(
-    Debugger &debugger, IOHandler::Type type,
-    const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp,
-    const lldb::StreamFileSP &error_sp, uint32_t flags,
+    Debugger &debugger, IOHandler::Type type, const lldb::FileSP &input_sp,
+    const lldb::StreamFileSP &output_sp, const lldb::StreamFileSP &error_sp,
+    uint32_t flags,
     const char *editline_name, // Used for saving history files
     llvm::StringRef prompt, llvm::StringRef continuation_prompt,
     bool multi_line, bool color_prompts, uint32_t line_number_start,
@@ -266,7 +266,7 @@
 #ifndef LLDB_DISABLE_LIBEDIT
   bool use_editline = false;
 
-  use_editline = m_input_sp->GetFile().GetIsRealTerminal();
+  use_editline = m_input_sp && m_input_sp->GetIsRealTerminal();
 
   if (use_editline) {
     m_editline_up.reset(new Editline(editline_name, GetInputFILE(),
@@ -596,7 +596,7 @@
     IOHandler::PrintAsync(stream, s, len);
 #ifdef _MSC_VER
     if (prompt)
-      IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt,
+      IOHandler::PrintAsync(GetOutputStreamFileSP().get(), prompt,
                             strlen(prompt));
 #endif
   }
Index: lldb/source/Core/Debugger.cpp
===================================================================
--- lldb/source/Core/Debugger.cpp
+++ lldb/source/Core/Debugger.cpp
@@ -297,14 +297,12 @@
         std::list<Status> errors;
         StreamString feedback_stream;
         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
-          StreamFileSP stream_sp(GetErrorFile());
-          if (stream_sp) {
-            for (auto error : errors) {
-              stream_sp->Printf("%s\n", error.AsCString());
-            }
-            if (feedback_stream.GetSize())
-              stream_sp->PutCString(feedback_stream.GetString());
+          Stream &s = GetErrorStream();
+          for (auto error : errors) {
+            s.Printf("%s\n", error.AsCString());
           }
+          if (feedback_stream.GetSize())
+            s.PutCString(feedback_stream.GetString());
         }
       }
     }
@@ -700,9 +698,9 @@
 Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
     : UserID(g_unique_id++),
       Properties(std::make_shared<OptionValueProperties>()),
-      m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
-      m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
-      m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
+      m_input_file_sp(std::make_shared<File>(stdin, false)),
+      m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)),
+      m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)),
       m_input_recorder(nullptr),
       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
       m_terminal_state(), m_target_list(*this), m_platform_list(),
@@ -757,7 +755,7 @@
   if (term && !strcmp(term, "dumb"))
     SetUseColor(false);
   // Turn off use-color if we don't write to a terminal with color support.
-  if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
+  if (!GetOutputFile().GetIsTerminalWithColors())
     SetUseColor(false);
 
 #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
@@ -798,8 +796,7 @@
     // Close the input file _before_ we close the input read communications
     // class as it does NOT own the input file, our m_input_file does.
     m_terminal_state.Clear();
-    if (m_input_file_sp)
-      m_input_file_sp->GetFile().Close();
+    GetInputFile().Close();
 
     m_command_interpreter_up->Clear();
   });
@@ -827,14 +824,10 @@
 void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership,
                                   repro::DataRecorder *recorder) {
   m_input_recorder = recorder;
-  if (m_input_file_sp)
-    m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
-  else
-    m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
 
-  File &in_file = m_input_file_sp->GetFile();
-  if (!in_file.IsValid())
-    in_file.SetStream(stdin, true);
+  m_input_file_sp = std::make_shared<File>(fh, tranfer_ownership);
+  if (!m_input_file_sp->IsValid())
+    m_input_file_sp = std::make_shared<File>(stdin, false);
 
   // Save away the terminal state if that is relevant, so that we can restore
   // it in RestoreInputState.
@@ -842,14 +835,10 @@
 }
 
 void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
-  if (m_output_file_sp)
-    m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
-  else
-    m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
 
-  File &out_file = m_output_file_sp->GetFile();
-  if (!out_file.IsValid())
-    out_file.SetStream(stdout, false);
+  GetOutputStream().SetFile(std::make_shared<File>(fh, tranfer_ownership));
+  if (!GetOutputFile())
+    GetOutputStream().SetFile(std::make_shared<File>(stdout, false));
 
   // Do not create the ScriptInterpreter just for setting the output file
   // handle as the constructor will know how to do the right thing on its own.
@@ -859,22 +848,15 @@
 }
 
 void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
-  if (m_error_file_sp)
-    m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
-  else
-    m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
-
-  File &err_file = m_error_file_sp->GetFile();
-  if (!err_file.IsValid())
-    err_file.SetStream(stderr, false);
+  GetErrorStream().SetFile(std::make_shared<File>(fh, tranfer_ownership));
+  if (!GetErrorFile())
+    GetErrorStream().SetFile(std::make_shared<File>(stderr, false));
 }
 
 void Debugger::SaveInputTerminalState() {
-  if (m_input_file_sp) {
-    File &in_file = m_input_file_sp->GetFile();
-    if (in_file.GetDescriptor() != File::kInvalidDescriptor)
-      m_terminal_state.Save(in_file.GetDescriptor(), true);
-  }
+  int fd = GetInputFile().GetDescriptor();
+  if (fd != File::kInvalidDescriptor)
+    m_terminal_state.Save(fd, true);
 }
 
 void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
@@ -955,8 +937,9 @@
 }
 
 void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
-  lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
-  m_input_reader_stack.PrintAsync(stream.get(), s, len);
+  lldb_private::StreamFile &stream =
+      is_stdout ? GetOutputStream() : GetErrorStream();
+  m_input_reader_stack.PrintAsync(&stream, s, len);
 }
 
 ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
@@ -993,8 +976,7 @@
   }
 }
 
-void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
-                                               StreamFileSP &out,
+void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out,
                                                StreamFileSP &err) {
   // Before an IOHandler runs, it must have in/out/err streams. This function
   // is called when one ore more of the streams are nullptr. We use the top
@@ -1006,20 +988,20 @@
   // If no STDIN has been set, then set it appropriately
   if (!in) {
     if (top_reader_sp)
-      in = top_reader_sp->GetInputStreamFile();
+      in = top_reader_sp->GetInputFileSP();
     else
-      in = GetInputFile();
+      in = GetInputFileSP();
 
     // If there is nothing, use stdin
     if (!in)
-      in = std::make_shared<StreamFile>(stdin, false);
+      in = std::make_shared<File>(stdin, false);
   }
   // If no STDOUT has been set, then set it appropriately
   if (!out) {
     if (top_reader_sp)
-      out = top_reader_sp->GetOutputStreamFile();
+      out = top_reader_sp->GetOutputStreamFileSP();
     else
-      out = GetOutputFile();
+      out = GetOutputStreamSP();
 
     // If there is nothing, use stdout
     if (!out)
@@ -1028,13 +1010,13 @@
   // If no STDERR has been set, then set it appropriately
   if (!err) {
     if (top_reader_sp)
-      err = top_reader_sp->GetErrorStreamFile();
+      err = top_reader_sp->GetErrorStreamFileSP();
     else
-      err = GetErrorFile();
+      err = GetErrorStreamSP();
 
     // If there is nothing, use stderr
     if (!err)
-      err = std::make_shared<StreamFile>(stdout, false);
+      err = std::make_shared<StreamFile>(stderr, false);
   }
 }
 
@@ -1202,7 +1184,7 @@
         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
   } else if (log_file.empty()) {
     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
-        GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
+        GetOutputFile().GetDescriptor(), !should_close, unbuffered);
   } else {
     auto pos = m_log_streams.find(log_file);
     if (pos != m_log_streams.end())
@@ -1597,8 +1579,7 @@
 
 void Debugger::StopIOHandlerThread() {
   if (m_io_handler_thread.IsJoinable()) {
-    if (m_input_file_sp)
-      m_input_file_sp->GetFile().Close();
+    GetInputFile().Close();
     m_io_handler_thread.Join(nullptr);
   }
 }
Index: lldb/source/Commands/CommandObjectWatchpointCommand.cpp
===================================================================
--- lldb/source/Commands/CommandObjectWatchpointCommand.cpp
+++ lldb/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -207,7 +207,7 @@
   Options *GetOptions() override { return &m_options; }
 
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(
           "Enter your debugger command(s).  Type 'DONE' to end.\n");
Index: lldb/source/Commands/CommandObjectType.cpp
===================================================================
--- lldb/source/Commands/CommandObjectType.cpp
+++ lldb/source/Commands/CommandObjectType.cpp
@@ -151,7 +151,7 @@
         "for\n"
         "        internal_dict: an LLDB support object not to be used\"\"\"\n";
 
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(g_summary_addreader_instructions);
       output_sp->Flush();
@@ -160,7 +160,7 @@
 
   void IOHandlerInputComplete(IOHandler &io_handler,
                               std::string &data) override {
-    StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
 
 #ifndef LLDB_DISABLE_PYTHON
     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
@@ -383,7 +383,7 @@
   }
 
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(g_synth_addreader_instructions);
       output_sp->Flush();
@@ -392,7 +392,7 @@
 
   void IOHandlerInputComplete(IOHandler &io_handler,
                               std::string &data) override {
-    StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
 
 #ifndef LLDB_DISABLE_PYTHON
     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
Index: lldb/source/Commands/CommandObjectTarget.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTarget.cpp
+++ lldb/source/Commands/CommandObjectTarget.cpp
@@ -4555,7 +4555,7 @@
 
 protected:
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(
           "Enter your stop hook command(s).  Type 'DONE' to end.\n");
@@ -4567,7 +4567,7 @@
                               std::string &line) override {
     if (m_stop_hook_sp) {
       if (line.empty()) {
-        StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+        StreamFileSP error_sp(io_handler.GetErrorStreamFileSP());
         if (error_sp) {
           error_sp->Printf("error: stop hook #%" PRIu64
                            " aborted, no commands.\n",
@@ -4579,7 +4579,7 @@
           target->RemoveStopHookByID(m_stop_hook_sp->GetID());
       } else {
         m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line);
-        StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+        StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
         if (output_sp) {
           output_sp->Printf("Stop hook #%" PRIu64 " added.\n",
                             m_stop_hook_sp->GetID());
Index: lldb/source/Commands/CommandObjectMemory.cpp
===================================================================
--- lldb/source/Commands/CommandObjectMemory.cpp
+++ lldb/source/Commands/CommandObjectMemory.cpp
@@ -779,9 +779,10 @@
       if (append)
         open_options |= File::eOpenOptionAppend;
 
-      Status error = FileSystem::Instance().Open(outfile_stream.GetFile(),
-                                                 outfile_spec, open_options);
-      if (error.Success()) {
+      outfile_stream.SetFile(
+          FileSystem::Instance().Open(outfile_spec, open_options));
+
+      if (outfile_stream.GetFile()) {
         if (m_memory_options.m_output_as_binary) {
           const size_t bytes_written =
               outfile_stream.Write(data_sp->GetBytes(), bytes_read);
Index: lldb/source/Commands/CommandObjectGUI.cpp
===================================================================
--- lldb/source/Commands/CommandObjectGUI.cpp
+++ lldb/source/Commands/CommandObjectGUI.cpp
@@ -28,9 +28,9 @@
   if (args.GetArgumentCount() == 0) {
     Debugger &debugger = GetDebugger();
 
-    lldb::StreamFileSP input_sp = debugger.GetInputFile();
-    if (input_sp && input_sp->GetFile().GetIsRealTerminal() &&
-        input_sp->GetFile().GetIsInteractive()) {
+    File &input = debugger.GetInputFile();
+    if (input.GetIsRealTerminal() &&
+        input.GetIsInteractive()) {
       IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger));
       if (io_handler_sp)
         debugger.PushIOHandler(io_handler_sp);
Index: lldb/source/Commands/CommandObjectExpression.cpp
===================================================================
--- lldb/source/Commands/CommandObjectExpression.cpp
+++ lldb/source/Commands/CommandObjectExpression.cpp
@@ -498,8 +498,8 @@
   //    StreamSP output_stream =
   //    io_handler.GetDebugger().GetAsyncOutputStream();
   //    StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream();
-  StreamFileSP output_sp(io_handler.GetOutputStreamFile());
-  StreamFileSP error_sp(io_handler.GetErrorStreamFile());
+  StreamFileSP output_sp = io_handler.GetOutputStreamFileSP();
+  StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
 
   EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get());
   if (output_sp)
@@ -537,7 +537,7 @@
                             1, // Show line numbers starting at 1
                             *this, nullptr));
 
-  StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile());
+  StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP();
   if (output_sp) {
     output_sp->PutCString(
         "Enter expressions, then terminate with an empty line to evaluate:\n");
Index: lldb/source/Commands/CommandObjectCommands.cpp
===================================================================
--- lldb/source/Commands/CommandObjectCommands.cpp
+++ lldb/source/Commands/CommandObjectCommands.cpp
@@ -945,7 +945,7 @@
 
 protected:
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString("Enter one or more sed substitution commands in "
                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
@@ -1585,7 +1585,7 @@
   };
 
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(g_python_command_instructions);
       output_sp->Flush();
@@ -1594,7 +1594,7 @@
 
   void IOHandlerInputComplete(IOHandler &io_handler,
                               std::string &data) override {
-    StreamFileSP error_sp = io_handler.GetErrorStreamFile();
+    StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
 
     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
     if (interpreter) {
Index: lldb/source/Commands/CommandObjectBreakpointCommand.cpp
===================================================================
--- lldb/source/Commands/CommandObjectBreakpointCommand.cpp
+++ lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -221,7 +221,7 @@
   Options *GetOptions() override { return &m_options; }
 
   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
-    StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+    StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
     if (output_sp && interactive) {
       output_sp->PutCString(g_reader_instructions);
       output_sp->Flush();
Index: lldb/source/API/SBStream.cpp
===================================================================
--- lldb/source/API/SBStream.cpp
+++ lldb/source/API/SBStream.cpp
@@ -89,8 +89,8 @@
   else
     open_options |= File::eOpenOptionTruncate;
 
-  FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path),
-                              open_options);
+  stream_file->SetFile(
+      FileSystem::Instance().Open(FileSpec(path), open_options));
   m_opaque_up.reset(stream_file);
 
   if (m_opaque_up) {
Index: lldb/source/API/SBDebugger.cpp
===================================================================
--- lldb/source/API/SBDebugger.cpp
+++ lldb/source/API/SBDebugger.cpp
@@ -329,9 +329,8 @@
   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetInputFileHandle);
 
   if (m_opaque_sp) {
-    StreamFileSP stream_file_sp(m_opaque_sp->GetInputFile());
-    if (stream_file_sp)
-      return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream());
+    File &file_sp = m_opaque_sp->GetInputFile();
+    return LLDB_RECORD_RESULT(file_sp.GetStream());
   }
   return nullptr;
 }
@@ -340,9 +339,8 @@
   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetOutputFileHandle);
 
   if (m_opaque_sp) {
-    StreamFileSP stream_file_sp(m_opaque_sp->GetOutputFile());
-    if (stream_file_sp)
-      return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream());
+    StreamFile &stream_file = m_opaque_sp->GetOutputStream();
+    return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream());
   }
   return nullptr;
 }
@@ -351,9 +349,8 @@
   LLDB_RECORD_METHOD_NO_ARGS(FILE *, SBDebugger, GetErrorFileHandle);
 
   if (m_opaque_sp) {
-    StreamFileSP stream_file_sp(m_opaque_sp->GetErrorFile());
-    if (stream_file_sp)
-      return LLDB_RECORD_RESULT(stream_file_sp->GetFile().GetStream());
+    StreamFile &stream_file = m_opaque_sp->GetErrorStream();
+    return LLDB_RECORD_RESULT(stream_file.GetFile().GetStream());
   }
   return nullptr;
 }
Index: lldb/scripts/Python/python-typemaps.swig
===================================================================
--- lldb/scripts/Python/python-typemaps.swig
+++ lldb/scripts/Python/python-typemaps.swig
@@ -395,13 +395,13 @@
    else
    {
       PythonFile py_file(PyRefType::Borrowed, $input);
-      File file;
+      lldb::FileSP file;
       if (!py_file.GetUnderlyingFile(file))
          return nullptr;
 
-      $1 = file.GetStream();
+      $1 = file->GetStream();
       if ($1)
-         file.Clear();
+         file->Clear();
     }
 }
 
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -331,6 +331,7 @@
 typedef std::shared_ptr<lldb_private::ExecutionContextRef>
     ExecutionContextRefSP;
 typedef std::shared_ptr<lldb_private::ExpressionVariable> ExpressionVariableSP;
+typedef std::unique_ptr<lldb_private::File> FileUP;
 typedef std::shared_ptr<lldb_private::File> FileSP;
 typedef std::shared_ptr<lldb_private::Function> FunctionSP;
 typedef std::shared_ptr<lldb_private::FunctionCaller> FunctionCallerSP;
Index: lldb/include/lldb/Host/FileSystem.h
===================================================================
--- lldb/include/lldb/Host/FileSystem.h
+++ lldb/include/lldb/Host/FileSystem.h
@@ -63,10 +63,21 @@
   /// Wraps ::open in a platform-independent way.
   int Open(const char *path, int flags, int mode);
 
-  Status Open(File &File, const FileSpec &file_spec, uint32_t options,
+  // file will be set to null if there's an error.
+  Status Open(std::unique_ptr<File> &file, const FileSpec &file_spec,
+              uint32_t options,
               uint32_t permissions = lldb::eFilePermissionsFileDefault,
               bool should_close_fd = true);
 
+  std::unique_ptr<File>
+  Open(const FileSpec &file_spec, uint32_t options,
+       uint32_t permissions = lldb::eFilePermissionsFileDefault,
+       bool should_close_fd = true) {
+    std::unique_ptr<File> p;
+    Open(p, file_spec, options, permissions, should_close_fd);
+    return p;
+  }
+
   /// Get a directory iterator.
   /// \{
   llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec,
Index: lldb/include/lldb/Host/FileCache.h
===================================================================
--- lldb/include/lldb/Host/FileCache.h
+++ lldb/include/lldb/Host/FileCache.h
@@ -22,7 +22,7 @@
 private:
   FileCache() {}
 
-  typedef std::map<lldb::user_id_t, lldb::FileSP> FDToFileMap;
+  typedef std::map<lldb::user_id_t, lldb::FileUP> FDToFileMap;
 
 public:
   static FileCache &GetInstance();
Index: lldb/include/lldb/Host/File.h
===================================================================
--- lldb/include/lldb/Host/File.h
+++ lldb/include/lldb/Host/File.h
@@ -125,12 +125,8 @@
 
   WaitableHandle GetWaitableHandle() override;
 
-  void SetDescriptor(int fd, uint32_t options, bool transfer_ownership);
-
   FILE *GetStream();
 
-  void SetStream(FILE *fh, bool transfer_ownership);
-
   /// Read bytes from a file from the current file position.
   ///
   /// NOTE: This function is NOT thread safe. Use the read function
Index: lldb/include/lldb/Core/StreamFile.h
===================================================================
--- lldb/include/lldb/Core/StreamFile.h
+++ lldb/include/lldb/Core/StreamFile.h
@@ -35,18 +35,29 @@
 
   StreamFile(FILE *fh, bool transfer_ownership);
 
+  StreamFile(std::shared_ptr<File> file) : StreamFile() { SetFile(file); }
+
   ~StreamFile() override;
 
-  File &GetFile() { return m_file; }
+  File &GetFile() { return *m_file_sp; }
+
+  const File &GetFile() const { return *m_file_sp; }
+
+  std::shared_ptr<File> GetFileSP() { return m_file_sp; }
 
-  const File &GetFile() const { return m_file; }
+  void SetFile(std::shared_ptr<File> file) {
+    if (file)
+      m_file_sp = file;
+    else
+      m_file_sp = std::make_shared<File>();
+  }
 
   void Flush() override;
 
 
 protected:
   // Classes that inherit from StreamFile can see and modify these
-  File m_file;
+  std::shared_ptr<File> m_file_sp; // never NULL
   size_t WriteImpl(const void *s, size_t length) override;
 
 private:
Index: lldb/include/lldb/Core/IOHandler.h
===================================================================
--- lldb/include/lldb/Core/IOHandler.h
+++ lldb/include/lldb/Core/IOHandler.h
@@ -58,8 +58,7 @@
   IOHandler(Debugger &debugger, IOHandler::Type type);
 
   IOHandler(Debugger &debugger, IOHandler::Type type,
-            const lldb::StreamFileSP &input_sp,
-            const lldb::StreamFileSP &output_sp,
+            const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp,
             const lldb::StreamFileSP &error_sp, uint32_t flags,
             repro::DataRecorder *data_recorder);
 
@@ -123,11 +122,11 @@
 
   FILE *GetErrorFILE();
 
-  lldb::StreamFileSP &GetInputStreamFile();
+  lldb::FileSP &GetInputFileSP();
 
-  lldb::StreamFileSP &GetOutputStreamFile();
+  lldb::StreamFileSP &GetOutputStreamFileSP();
 
-  lldb::StreamFileSP &GetErrorStreamFile();
+  lldb::StreamFileSP &GetErrorStreamFileSP();
 
   Debugger &GetDebugger() { return m_debugger; }
 
@@ -165,7 +164,7 @@
 
 protected:
   Debugger &m_debugger;
-  lldb::StreamFileSP m_input_sp;
+  lldb::FileSP m_input_sp;
   lldb::StreamFileSP m_output_sp;
   lldb::StreamFileSP m_error_sp;
   repro::DataRecorder *m_data_recorder;
@@ -333,7 +332,7 @@
                     repro::DataRecorder *data_recorder);
 
   IOHandlerEditline(Debugger &debugger, IOHandler::Type type,
-                    const lldb::StreamFileSP &input_sp,
+                    const lldb::FileSP &input_sp,
                     const lldb::StreamFileSP &output_sp,
                     const lldb::StreamFileSP &error_sp, uint32_t flags,
                     const char *editline_name, // Used for saving history files
@@ -349,7 +348,7 @@
                     const char *, bool, bool, uint32_t,
                     IOHandlerDelegate &) = delete;
 
-  IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::StreamFileSP &,
+  IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &,
                     const lldb::StreamFileSP &, const lldb::StreamFileSP &,
                     uint32_t, const char *, const char *, const char *, bool,
                     bool, uint32_t, IOHandlerDelegate &) = delete;
Index: lldb/include/lldb/Core/Debugger.h
===================================================================
--- lldb/include/lldb/Core/Debugger.h
+++ lldb/include/lldb/Core/Debugger.h
@@ -17,6 +17,7 @@
 #include "lldb/Core/FormatEntity.h"
 #include "lldb/Core/IOHandler.h"
 #include "lldb/Core/SourceManager.h"
+#include "lldb/Core/StreamFile.h"
 #include "lldb/Core/UserSettingsController.h"
 #include "lldb/Host/HostThread.h"
 #include "lldb/Host/Terminal.h"
@@ -113,11 +114,21 @@
 
   void SetAsyncExecution(bool async);
 
-  lldb::StreamFileSP GetInputFile() { return m_input_file_sp; }
+  lldb::FileSP GetInputFileSP() { return m_input_file_sp; }
 
-  lldb::StreamFileSP GetOutputFile() { return m_output_file_sp; }
+  lldb::StreamFileSP GetOutputStreamSP() { return m_output_stream_sp; }
 
-  lldb::StreamFileSP GetErrorFile() { return m_error_file_sp; }
+  lldb::StreamFileSP GetErrorStreamSP() { return m_error_stream_sp; }
+
+  lldb_private::File &GetInputFile() { return *m_input_file_sp; }
+
+  lldb_private::File &GetOutputFile() { return m_output_stream_sp->GetFile(); }
+
+  lldb_private::File &GetErrorFile() { return m_error_stream_sp->GetFile(); }
+
+  lldb_private::StreamFile &GetOutputStream() { return *m_output_stream_sp; }
+
+  lldb_private::StreamFile &GetErrorStream() { return *m_error_stream_sp; }
 
   repro::DataRecorder *GetInputRecorder();
 
@@ -174,7 +185,7 @@
 
   // If any of the streams are not set, set them to the in/out/err stream of
   // the top most input reader to ensure they at least have something
-  void AdoptTopIOHandlerFilesIfInvalid(lldb::StreamFileSP &in,
+  void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in,
                                        lldb::StreamFileSP &out,
                                        lldb::StreamFileSP &err);
 
@@ -356,9 +367,10 @@
 
   void InstanceInitialize();
 
-  lldb::StreamFileSP m_input_file_sp;
-  lldb::StreamFileSP m_output_file_sp;
-  lldb::StreamFileSP m_error_file_sp;
+  // these should never be NULL
+  lldb::FileSP m_input_file_sp;
+  lldb::StreamFileSP m_output_stream_sp;
+  lldb::StreamFileSP m_error_stream_sp;
 
   /// Used for shadowing the input file when capturing a reproducer.
   repro::DataRecorder *m_input_recorder;
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to