Skip to content

[lldb] Change the implementation of Status to store an llvm::Error (NFC) #106774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 18, 2024

Conversation

adrian-prantl
Copy link
Collaborator

(based on a conversation I had with @labath yesterday in #106442)

Most APIs that currently vend a Status would be better served by returning llvm::Expected<> instead. If possibles APIs should be refactored to avoid Status. The only legitimate long-term uses of Status are objects that need to store an error for a long time (which should be questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the places that cannot switch to llvm::Error explicit: They are marked with a call to Status::clone(). Every other API can and should be refactored to use llvm::Expected. In the end Status should only be used in very few places.

Whenever an unchecked Error is dropped by Status it logs this to the verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new llvm::Error types. Here is the mapping of lldb::ErrorType to llvm::Errors:

   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error

@llvmbot
Copy link
Member

llvmbot commented Aug 30, 2024

@llvm/pr-subscribers-lldb

Author: Adrian Prantl (adrian-prantl)

Changes

(based on a conversation I had with @labath yesterday in #106442)

Most APIs that currently vend a Status would be better served by returning llvm::Expected<> instead. If possibles APIs should be refactored to avoid Status. The only legitimate long-term uses of Status are objects that need to store an error for a long time (which should be questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the places that cannot switch to llvm::Error explicit: They are marked with a call to Status::clone(). Every other API can and should be refactored to use llvm::Expected. In the end Status should only be used in very few places.

Whenever an unchecked Error is dropped by Status it logs this to the verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new llvm::Error types. Here is the mapping of lldb::ErrorType to llvm::Errors:

   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList&lt;ExpressionError&gt;
   eErrorTypeWin32        Win32Error

Patch is 96.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/106774.diff

81 Files Affected:

  • (modified) lldb/bindings/python/python-swigsafecast.swig (+1-1)
  • (modified) lldb/include/lldb/API/SBError.h (+2-2)
  • (modified) lldb/include/lldb/API/SBValueList.h (+1-1)
  • (modified) lldb/include/lldb/Core/ValueObjectConstResult.h (+2-2)
  • (modified) lldb/include/lldb/Target/Process.h (-2)
  • (modified) lldb/include/lldb/Utility/Status.h (+61-10)
  • (modified) lldb/source/API/SBBreakpoint.cpp (+3-3)
  • (modified) lldb/source/API/SBBreakpointLocation.cpp (+2-2)
  • (modified) lldb/source/API/SBBreakpointName.cpp (+8-9)
  • (modified) lldb/source/API/SBDebugger.cpp (+2-2)
  • (modified) lldb/source/API/SBError.cpp (+9-6)
  • (modified) lldb/source/API/SBFile.cpp (+5-10)
  • (modified) lldb/source/API/SBFormat.cpp (+1-1)
  • (modified) lldb/source/API/SBFrame.cpp (+5-4)
  • (modified) lldb/source/API/SBPlatform.cpp (+2-2)
  • (modified) lldb/source/API/SBProcess.cpp (+1-1)
  • (modified) lldb/source/API/SBSaveCoreOptions.cpp (+1-2)
  • (modified) lldb/source/API/SBStructuredData.cpp (+1-1)
  • (modified) lldb/source/API/SBTarget.cpp (+4-3)
  • (modified) lldb/source/API/SBThread.cpp (+1-1)
  • (modified) lldb/source/API/SBValue.cpp (+2-2)
  • (modified) lldb/source/API/SBValueList.cpp (+7-6)
  • (modified) lldb/source/API/SBWatchpoint.cpp (+1-1)
  • (modified) lldb/source/Commands/CommandObjectCommands.cpp (+2-2)
  • (modified) lldb/source/Commands/CommandObjectMemoryTag.cpp (+5-5)
  • (modified) lldb/source/Core/Debugger.cpp (+1-1)
  • (modified) lldb/source/Core/ModuleList.cpp (+2-3)
  • (modified) lldb/source/Core/PluginManager.cpp (+1-1)
  • (modified) lldb/source/Core/ThreadedCommunication.cpp (+1-1)
  • (modified) lldb/source/Core/ValueObject.cpp (+2-2)
  • (modified) lldb/source/Core/ValueObjectCast.cpp (+1-1)
  • (modified) lldb/source/Core/ValueObjectConstResult.cpp (+5-4)
  • (modified) lldb/source/Core/ValueObjectDynamicValue.cpp (+1-1)
  • (modified) lldb/source/Core/ValueObjectSyntheticFilter.cpp (+1-1)
  • (modified) lldb/source/DataFormatters/VectorType.cpp (+1-1)
  • (modified) lldb/source/Expression/FunctionCaller.cpp (+1-2)
  • (modified) lldb/source/Expression/LLVMUserExpression.cpp (+3-3)
  • (modified) lldb/source/Expression/Materializer.cpp (+1-1)
  • (modified) lldb/source/Expression/UserExpression.cpp (+4-4)
  • (modified) lldb/source/Host/common/LockFileBase.cpp (+2-2)
  • (modified) lldb/source/Host/common/NativeProcessProtocol.cpp (+5-5)
  • (modified) lldb/source/Host/common/TCPSocket.cpp (+2-2)
  • (modified) lldb/source/Host/macosx/objcxx/Host.mm (+1-1)
  • (modified) lldb/source/Host/posix/ConnectionFileDescriptorPosix.cpp (+6-6)
  • (modified) lldb/source/Interpreter/CommandInterpreter.cpp (+1-1)
  • (modified) lldb/source/Interpreter/OptionValueRegex.cpp (+1-1)
  • (modified) lldb/source/Interpreter/ScriptInterpreter.cpp (+1-1)
  • (modified) lldb/source/Plugins/Language/CPlusPlus/BlockPointer.cpp (+1-1)
  • (modified) lldb/source/Plugins/Platform/Android/AdbClient.cpp (+4-4)
  • (modified) lldb/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp (+2-2)
  • (modified) lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h (+1-1)
  • (modified) lldb/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm (+7-7)
  • (modified) lldb/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp (+2-2)
  • (modified) lldb/source/Plugins/Platform/Windows/PlatformWindows.cpp (+2-2)
  • (modified) lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg_arm64.cpp (+5-5)
  • (modified) lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp (+1-1)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp (+1-1)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (+1-1)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp (+1-1)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (+4-4)
  • (modified) lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp (+1-1)
  • (modified) lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp (+1-1)
  • (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedProcessPythonInterface.cpp (+3-3)
  • (modified) lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h (+7-3)
  • (modified) lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp (+11-11)
  • (modified) lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp (+2-2)
  • (modified) lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp (+1-1)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h (+1-1)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (+1-1)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp (+1-1)
  • (modified) lldb/source/Target/ModuleCache.cpp (+2-2)
  • (modified) lldb/source/Target/Platform.cpp (+3-3)
  • (modified) lldb/source/Target/Process.cpp (+4-41)
  • (modified) lldb/source/Target/StackFrame.cpp (+1-1)
  • (modified) lldb/source/Target/Target.cpp (+5-7)
  • (modified) lldb/source/Target/Thread.cpp (+2-1)
  • (modified) lldb/source/Utility/Status.cpp (+172-66)
  • (modified) lldb/source/Utility/StructuredData.cpp (+1-1)
  • (modified) lldb/unittests/Target/RemoteAwarePlatformTest.cpp (+5-4)
  • (modified) lldb/unittests/TestingSupport/Host/NativeProcessTestUtils.h (+2-2)
  • (modified) lldb/unittests/Utility/StatusTest.cpp (+3-3)
diff --git a/lldb/bindings/python/python-swigsafecast.swig b/lldb/bindings/python/python-swigsafecast.swig
index 34f8c6f0ff8d35..c46c247da87278 100644
--- a/lldb/bindings/python/python-swigsafecast.swig
+++ b/lldb/bindings/python/python-swigsafecast.swig
@@ -34,7 +34,7 @@ PythonObject SWIGBridge::ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp) {
 }
 
 PythonObject SWIGBridge::ToSWIGWrapper(const Status& status) {
-  return ToSWIGHelper(new lldb::SBError(status), SWIGTYPE_p_lldb__SBError);
+  return ToSWIGHelper(new lldb::SBError(status.clone()), SWIGTYPE_p_lldb__SBError);
 }
 
 PythonObject SWIGBridge::ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb) {
diff --git a/lldb/include/lldb/API/SBError.h b/lldb/include/lldb/API/SBError.h
index 17f2c6c3027af7..9f55f92131c06e 100644
--- a/lldb/include/lldb/API/SBError.h
+++ b/lldb/include/lldb/API/SBError.h
@@ -97,7 +97,7 @@ class LLDB_API SBError {
   friend class lldb_private::ScriptInterpreter;
   friend class lldb_private::python::SWIGBridge;
 
-  SBError(const lldb_private::Status &error);
+  SBError(lldb_private::Status &&error);
 
   lldb_private::Status *get();
 
@@ -107,7 +107,7 @@ class LLDB_API SBError {
 
   lldb_private::Status &ref();
 
-  void SetError(const lldb_private::Status &lldb_error);
+  void SetError(lldb_private::Status &&lldb_error);
 
 private:
   std::unique_ptr<lldb_private::Status> m_opaque_up;
diff --git a/lldb/include/lldb/API/SBValueList.h b/lldb/include/lldb/API/SBValueList.h
index a5017bccc50533..52a86f989e153a 100644
--- a/lldb/include/lldb/API/SBValueList.h
+++ b/lldb/include/lldb/API/SBValueList.h
@@ -96,7 +96,7 @@ class LLDB_API SBValueList {
 
   std::unique_ptr<ValueListImpl> m_opaque_up;
 
-  void SetError(const lldb_private::Status &status);
+  void SetError(lldb_private::Status &&status);
 };
 
 } // namespace lldb
diff --git a/lldb/include/lldb/Core/ValueObjectConstResult.h b/lldb/include/lldb/Core/ValueObjectConstResult.h
index d3b3362bd0e9ec..9c34617af71d0d 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResult.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResult.h
@@ -61,7 +61,7 @@ class ValueObjectConstResult : public ValueObject {
 
   // When an expression fails to evaluate, we return an error
   static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope,
-                                    const Status &error);
+                                    Status &&error);
 
   std::optional<uint64_t> GetByteSize() override;
 
@@ -146,7 +146,7 @@ class ValueObjectConstResult : public ValueObject {
                          ConstString name, Module *module = nullptr);
 
   ValueObjectConstResult(ExecutionContextScope *exe_scope,
-                         ValueObjectManager &manager, const Status &error);
+                         ValueObjectManager &manager, Status &&error);
 
   ValueObject *CreateChildAtIndex(size_t idx) override {
     return m_impl.CreateChildAtIndex(idx);
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index a7de991104434d..c66cfb2c245efd 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1296,8 +1296,6 @@ class Process : public std::enable_shared_from_this<Process>,
                 const EvaluateExpressionOptions &options,
                 DiagnosticManager &diagnostic_manager);
 
-  static const char *ExecutionResultAsCString(lldb::ExpressionResults result);
-
   void GetStatus(Stream &ostrm);
 
   size_t GetThreadStatus(Stream &ostrm, bool only_threads_with_stop_reason,
diff --git a/lldb/include/lldb/Utility/Status.h b/lldb/include/lldb/Utility/Status.h
index b304291ffae00e..bd60fcf2885e07 100644
--- a/lldb/include/lldb/Utility/Status.h
+++ b/lldb/include/lldb/Utility/Status.h
@@ -26,6 +26,34 @@ class raw_ostream;
 
 namespace lldb_private {
 
+class MachKernelError
+    : public llvm::ErrorInfo<MachKernelError, llvm::StringError> {
+public:
+  using llvm::ErrorInfo<MachKernelError, llvm::StringError>::ErrorInfo;
+  MachKernelError(std::error_code ec, const llvm::Twine &msg = {})
+      : ErrorInfo(msg, ec) {}
+  static char ID;
+};
+
+class Win32Error : public llvm::ErrorInfo<Win32Error, llvm::StringError> {
+public:
+  using llvm::ErrorInfo<Win32Error, llvm::StringError>::ErrorInfo;
+  Win32Error(std::error_code ec, const llvm::Twine &msg = {})
+      : ErrorInfo(msg, ec) {}
+  static char ID;
+};
+
+class ExpressionError
+    : public llvm::ErrorInfo<ExpressionError, llvm::StringError> {
+public:
+  using llvm::ErrorInfo<ExpressionError, llvm::StringError>::ErrorInfo;
+  ExpressionError(std::error_code ec, std::string msg = {})
+      : ErrorInfo(msg, ec) {}
+  static char ID;
+};
+
+const char *ExecutionResultAsCString(lldb::ExpressionResults result);
+
 /// \class Status Status.h "lldb/Utility/Status.h" An error handling class.
 ///
 /// This class is designed to be able to hold any error code that can be
@@ -41,13 +69,32 @@ namespace lldb_private {
 /// of themselves for printing results and error codes. The string value will
 /// be fetched on demand and its string value will be cached until the error
 /// is cleared of the value of the error changes.
+///
+/// API design notes:
+///
+/// Most APIs that currently vend a Status would be better served by
+/// returning llvm::Expected<> instead. If possibles APIs should be
+/// refactored to avoid Status. The only legitimate long-term uses of
+/// Status are objects that need to store an error for a long time
+/// (which should be questioned as a design decision, too).
+///
+/// Implementation notes:
+///
+/// Internally, Status stores an llvm::Error.
+///   eErrorTypeInvalid
+///   eErrorTypeGeneric      llvm::StringError
+///   eErrorTypePOSIX        llvm::ECError
+///   eErrorTypeMachKernel   MachKernelError
+///   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
+///   eErrorTypeWin32        Win32Error
+
 class Status {
 public:
-  /// Every error value that this object can contain needs to be able to fit
   /// into ValueType.
   typedef uint32_t ValueType;
 
   Status();
+  Status(Status &&other) = default;
 
   /// Initialize the error object with a generic success value.
   ///
@@ -79,9 +126,7 @@ class Status {
   }
 
   static Status FromExpressionError(lldb::ExpressionResults result,
-                                    std::string msg) {
-    return Status(result, lldb::eErrorTypeExpression, msg);
-  }
+                                    std::string msg);
 
   /// Set the current error to errno.
   ///
@@ -91,10 +136,14 @@ class Status {
 
   ~Status();
 
-  // llvm::Error support
-  explicit Status(llvm::Error error) { *this = std::move(error); }
+  /// Try not to use this in new code. Migrate APIs to llvm::Expected instead.
+  static Status FromError(llvm::Error &&error);
   const Status &operator=(llvm::Error error);
+  Status &operator=(Status &&);
+  /// FIXME: Replace this with a takeError() method.
   llvm::Error ToError() const;
+  /// Don't call this function in new code. Redesign the API instead.
+  Status clone() const { return Status(ToError()); }
 
   /// Get the error string associated with the current error.
   //
@@ -145,10 +194,12 @@ class Status {
   bool Success() const;
 
 protected:
-  /// Status code as an integer value.
-  ValueType m_code = 0;
-  /// The type of the above error code.
-  lldb::ErrorType m_type = lldb::eErrorTypeInvalid;
+  Status(llvm::Error &&error) : m_error(std::move(error)) {}
+  mutable llvm::Error m_error;
+  //  /// Status code as an integer value.
+  //  ValueType m_code = 0;
+  //  /// The type of the above error code.
+  //  lldb::ErrorType m_type = lldb::eErrorTypeInvalid;
   /// A string representation of the error code.
   mutable std::string m_string;
 };
diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp
index 3e9c01080588e5..b2ed034d19983c 100644
--- a/lldb/source/API/SBBreakpoint.cpp
+++ b/lldb/source/API/SBBreakpoint.cpp
@@ -622,7 +622,7 @@ SBError SBBreakpoint::SetScriptCallbackFunction(
                                                callback_function_name,
                                                extra_args.m_impl_up
                                                    ->GetObjectSP());
-    sb_error.SetError(error);
+    sb_error.SetError(std::move(error));
   } else
     sb_error = Status::FromErrorString("invalid breakpoint");
 
@@ -645,7 +645,7 @@ SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) {
             .GetScriptInterpreter()
             ->SetBreakpointCommandCallback(bp_options, callback_body_text,
                                            /*is_callback=*/false);
-    sb_error.SetError(error);
+    sb_error.SetError(std::move(error));
   } else
     sb_error = Status::FromErrorString("invalid breakpoint");
 
@@ -670,7 +670,7 @@ SBError SBBreakpoint::AddNameWithErrorHandling(const char *new_name) {
         bkpt_sp->GetTarget().GetAPIMutex());
     Status error;
     bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error);
-    status.SetError(error);
+    status.SetError(std::move(error));
   } else {
     status = Status::FromErrorString("invalid breakpoint");
   }
diff --git a/lldb/source/API/SBBreakpointLocation.cpp b/lldb/source/API/SBBreakpointLocation.cpp
index e5c96b81e80904..b2d1da3927c6ea 100644
--- a/lldb/source/API/SBBreakpointLocation.cpp
+++ b/lldb/source/API/SBBreakpointLocation.cpp
@@ -239,7 +239,7 @@ SBError SBBreakpointLocation::SetScriptCallbackFunction(
                                                callback_function_name,
                                                extra_args.m_impl_up
                                                    ->GetObjectSP());
-      sb_error.SetError(error);
+    sb_error.SetError(std::move(error));
     } else
       sb_error = Status::FromErrorString("invalid breakpoint");
 
@@ -264,7 +264,7 @@ SBBreakpointLocation::SetScriptCallbackBody(const char *callback_body_text) {
             .GetScriptInterpreter()
             ->SetBreakpointCommandCallback(bp_options, callback_body_text,
                                            /*is_callback=*/false);
-    sb_error.SetError(error);
+    sb_error.SetError(std::move(error));
   } else
     sb_error = Status::FromErrorString("invalid breakpoint");
 
diff --git a/lldb/source/API/SBBreakpointName.cpp b/lldb/source/API/SBBreakpointName.cpp
index 7dc8dee19f43d2..831260d44e8e7f 100644
--- a/lldb/source/API/SBBreakpointName.cpp
+++ b/lldb/source/API/SBBreakpointName.cpp
@@ -570,14 +570,13 @@ SBError SBBreakpointName::SetScriptCallbackFunction(
         m_impl_up->GetTarget()->GetAPIMutex());
 
   BreakpointOptions &bp_options = bp_name->GetOptions();
-  Status error;
-  error = m_impl_up->GetTarget()
-              ->GetDebugger()
-              .GetScriptInterpreter()
-              ->SetBreakpointCommandCallbackFunction(
-                  bp_options, callback_function_name,
-                  extra_args.m_impl_up->GetObjectSP());
-  sb_error.SetError(error);
+  Status error = m_impl_up->GetTarget()
+                     ->GetDebugger()
+                     .GetScriptInterpreter()
+                     ->SetBreakpointCommandCallbackFunction(
+                         bp_options, callback_function_name,
+                         extra_args.m_impl_up->GetObjectSP());
+  sb_error.SetError(std::move(error));
   UpdateName(*bp_name);
   return sb_error;
 }
@@ -600,7 +599,7 @@ SBBreakpointName::SetScriptCallbackBody(const char *callback_body_text) {
                      .GetScriptInterpreter()
                      ->SetBreakpointCommandCallback(
                          bp_options, callback_body_text, /*is_callback=*/false);
-  sb_error.SetError(error);
+  sb_error.SetError(std::move(error));
   if (!sb_error.Fail())
     UpdateName(*bp_name);
 
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 72501570320d57..b21d7e67290073 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -220,7 +220,7 @@ lldb::SBError SBDebugger::InitializeWithErrorHandling() {
   SBError error;
   if (auto e = g_debugger_lifetime->Initialize(
           std::make_unique<SystemInitializerFull>(), LoadPlugin)) {
-    error.SetError(Status(std::move(e)));
+    error.SetError(Status::FromError(std::move(e)));
   }
   return error;
 }
@@ -1360,7 +1360,7 @@ SBError SBDebugger::SetInternalVariable(const char *var_name, const char *value,
         "invalid debugger instance name '%s'", debugger_instance_name);
   }
   if (error.Fail())
-    sb_error.SetError(error);
+    sb_error.SetError(std::move(error));
   return sb_error;
 }
 
diff --git a/lldb/source/API/SBError.cpp b/lldb/source/API/SBError.cpp
index 30d9ccc78ee376..287fa6c499dd2f 100644
--- a/lldb/source/API/SBError.cpp
+++ b/lldb/source/API/SBError.cpp
@@ -23,7 +23,8 @@ SBError::SBError() { LLDB_INSTRUMENT_VA(this); }
 SBError::SBError(const SBError &rhs) {
   LLDB_INSTRUMENT_VA(this, rhs);
 
-  m_opaque_up = clone(rhs.m_opaque_up);
+  if (rhs.m_opaque_up)
+    m_opaque_up = std::make_unique<Status>(rhs.m_opaque_up->clone());
 }
 
 SBError::SBError(const char *message) {
@@ -32,8 +33,8 @@ SBError::SBError(const char *message) {
   SetErrorString(message);
 }
 
-SBError::SBError(const lldb_private::Status &status)
-    : m_opaque_up(new Status(status)) {
+SBError::SBError(lldb_private::Status &&status)
+    : m_opaque_up(new Status(std::move(status))) {
   LLDB_INSTRUMENT_VA(this, status);
 }
 
@@ -43,7 +44,9 @@ const SBError &SBError::operator=(const SBError &rhs) {
   LLDB_INSTRUMENT_VA(this, rhs);
 
   if (this != &rhs)
-    m_opaque_up = clone(rhs.m_opaque_up);
+    if (rhs.m_opaque_up)
+      m_opaque_up = std::make_unique<Status>(rhs.m_opaque_up->clone());
+
   return *this;
 }
 
@@ -111,9 +114,9 @@ void SBError::SetError(uint32_t err, ErrorType type) {
   *m_opaque_up = Status(err, type);
 }
 
-void SBError::SetError(const Status &lldb_error) {
+void SBError::SetError(Status &&lldb_error) {
   CreateIfNeeded();
-  *m_opaque_up = lldb_error;
+  *m_opaque_up = std::move(lldb_error);
 }
 
 void SBError::SetErrorToErrno() {
diff --git a/lldb/source/API/SBFile.cpp b/lldb/source/API/SBFile.cpp
index 623708780f4c67..2ae4b1481afbf2 100644
--- a/lldb/source/API/SBFile.cpp
+++ b/lldb/source/API/SBFile.cpp
@@ -62,8 +62,7 @@ SBError SBFile::Read(uint8_t *buf, size_t num_bytes, size_t *bytes_read) {
     error = Status::FromErrorString("invalid SBFile");
     *bytes_read = 0;
   } else {
-    Status status = m_opaque_sp->Read(buf, num_bytes);
-    error.SetError(status);
+    error.SetError(m_opaque_sp->Read(buf, num_bytes));
     *bytes_read = num_bytes;
   }
   return error;
@@ -78,8 +77,7 @@ SBError SBFile::Write(const uint8_t *buf, size_t num_bytes,
     error = Status::FromErrorString("invalid SBFile");
     *bytes_written = 0;
   } else {
-    Status status = m_opaque_sp->Write(buf, num_bytes);
-    error.SetError(status);
+    error.SetError(m_opaque_sp->Write(buf, num_bytes));
     *bytes_written = num_bytes;
   }
   return error;
@@ -92,8 +90,7 @@ SBError SBFile::Flush() {
   if (!m_opaque_sp) {
     error = Status::FromErrorString("invalid SBFile");
   } else {
-    Status status = m_opaque_sp->Flush();
-    error.SetError(status);
+    error.SetError(m_opaque_sp->Flush());
   }
   return error;
 }
@@ -106,10 +103,8 @@ bool SBFile::IsValid() const {
 SBError SBFile::Close() {
   LLDB_INSTRUMENT_VA(this);
   SBError error;
-  if (m_opaque_sp) {
-    Status status = m_opaque_sp->Close();
-    error.SetError(status);
-  }
+  if (m_opaque_sp)
+    error.SetError(m_opaque_sp->Close());
   return error;
 }
 
diff --git a/lldb/source/API/SBFormat.cpp b/lldb/source/API/SBFormat.cpp
index 51cddceea0372e..080e219d64a362 100644
--- a/lldb/source/API/SBFormat.cpp
+++ b/lldb/source/API/SBFormat.cpp
@@ -36,7 +36,7 @@ SBFormat::SBFormat(const char *format, lldb::SBError &error) {
   FormatEntrySP format_entry_sp = std::make_shared<FormatEntity::Entry>();
   Status status = FormatEntity::Parse(format, *format_entry_sp);
 
-  error.SetError(status);
+  error.SetError(std::move(status));
   if (error.Success())
     m_opaque_sp = format_entry_sp;
 }
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index b1360e88bcd3af..30c44b974988d0 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -809,7 +809,7 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
         Status var_error;
         variable_list = frame->GetVariableList(true, &var_error);
         if (var_error.Fail())
-          value_list.SetError(var_error);
+          value_list.SetError(std::move(var_error));
         if (variable_list) {
           const size_t num_variables = variable_list->GetSize();
           if (num_variables) {
@@ -1033,7 +1033,8 @@ SBValue SBFrame::EvaluateExpression(const char *expr) {
     Status error;
     error = Status::FromErrorString("can't evaluate expressions when the "
                                     "process is running.");
-    ValueObjectSP error_val_sp = ValueObjectConstResult::Create(nullptr, error);
+    ValueObjectSP error_val_sp =
+        ValueObjectConstResult::Create(nullptr, std::move(error));
     result.SetSP(error_val_sp, false);
   }
   return result;
@@ -1129,13 +1130,13 @@ lldb::SBValue SBFrame::EvaluateExpression(const char *expr,
       Status error;
       error = Status::FromErrorString("can't evaluate expressions when the "
                                       "process is running.");
-      expr_value_sp = ValueObjectConstResult::Create(nullptr, error);
+      expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error));
       expr_result.SetSP(expr_value_sp, false);
     }
   } else {
       Status error;
       error = Status::FromErrorString("sbframe object is not valid.");
-      expr_value_sp = ValueObjectConstResult::Create(nullptr, error);
+      expr_value_sp = ValueObjectConstResult::Create(nullptr, std::move(error));
       expr_result.SetSP(expr_value_sp, false);
   }
 
diff --git a/lldb/source/API/SBPlatform.cpp b/lldb/source/API/SBPlatform.cpp
index 2f0f925302f16e..10ed653500d9f8 100644
--- a/lldb/source/API/SBPlatform.cpp
+++ b/lldb/source/API/SBPlatform.cpp
@@ -586,7 +586,7 @@ SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,
       Status status;
       ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(),
                                                  target.GetSP().get(), status);
-      error.SetError(status);
+      error.SetError(std::move(status));
       return SBProcess(process_sp);
     }
 
@@ -728,7 +728,7 @@ SBError SBPlatform::SetLocateModuleCallback(
           symbol_file_spec = symbol_file_spec_sb.ref();
         }
 
-        return error.ref();
+        return error.ref().clone();
       });
   return SBError();
 }
diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index 3eed51f0245f6f..9773144723c34c 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -1450,7 +1450,7 @@ lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
       std::lock_guard<std::recursive_mutex> guard(
           process_sp->GetTarget().GetAPIMutex());
       Status error = process_sp->DeallocateMemory(ptr);
-      sb_error.SetError(error);
+      sb_error.SetError(std::move(error));
     } else {
       sb_error = Status::FromErrorString("process is running");
     }
diff --git a/lldb/source/API/SBSaveCoreOptions.cpp b/lldb/source/API/SBSaveCoreOptions.cpp
index 2cd431611ef558..ef82b0253f1199 100644
--- a/lldb/source/API/SBSaveCoreOptions.cpp
+++ b/lldb/source/API/SBSaveCoreOptions.cpp
@@ -40,8 +40,7 @@ SBSaveCoreOptions::operator=(const SBSaveCoreOptions &rhs) {
 
 SBError SBSaveCoreOptions::SetPluginName(const char *name) {
   LLDB_INSTRUMENT_VA(this, name);
-  lldb_private::Status error = m_opaque_up->SetPluginName(name);
-  return SBError(error);
+  return SBError(m_opaque_up->SetPluginName(name));
 }
 
 void SBSaveCoreOptions::SetStyle(lldb::SaveCoreStyle style) {
diff --git a/lldb/source/API/SBStructuredData.cpp b/lldb/source/API/SBStructuredData.cpp
index 801ebf45e0e524..b891a34bd7c76a 100644
--- a/lldb/source/API/SBStructuredData.cpp
+++ b/lldb/source/API/SBStructuredData.cpp
@@ -133,7 +133,7 @@ lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const {
 
   Status error = m_impl_up->GetDescription(stream.ref());
   SBError sb_error;
-  sb_error.SetError(error);
...
[truncated]

@adrian-prantl adrian-prantl force-pushed the status-wraps-error branch 2 times, most recently from 1151a01 to 089f8e8 Compare August 30, 2024 18:54
Copy link
Member

@medismailben medismailben left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great! LGTM with comments.

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two high-level comments:

  • I think that the FromError/clone changes would be better of as a separate patch(es). I have no problem with the changes themselves, but I think it'd be better to separate the meat of this patch from the mechanical renaming. The renames could be done either before an after the patch, as (AFAICT) the functions are just fancy names for (copy) constructors.
  • I think this class should accept an open class hierarchy (like llvm::Error) does and not assume that it can enumerate all the error subclasses. I think the only additional property that we need of the error classes is the ability to clone themselves, which we could achieve by providing a ClonableErrorInfo class with an abstract clone method. We can still keep the code which converts all unclonable errors into a string error (but I'd only do it after a copy, not immediately during construction). The thing I want to avoid is the proliferation of very specific error types inside the base Status class -- the mach/windows error types should arguably be defined in the host library, and even the ExpressionError type might be better off inside the command interpreter or something. I'm not saying you have to do the refactor now, but I'd like to have the option to do so in the future.

Comment on lines 248 to 246
if (ec.category() == std::generic_category() ||
ec.category() == generic_category() ||
ec.category() == expression_category())
result = ec.value();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about just returning ec.value() regardless of the category?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This special case only exists because it otherwise breaks the GDBRemoteCommunicationServer unit test. Probably not worth preserving, but I didn't want to unnecessarily change this behavior either.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the SendErrorResponse_StringError test.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually prefer changing the code over there if it meant simplifying this. Would #108170 do the trick?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I incorporate the change. There's still some amount of compatibility-wrapping needed, but it got better.

@adrian-prantl adrian-prantl force-pushed the status-wraps-error branch 2 times, most recently from 992600a to 3ffcc5e Compare September 3, 2024 17:04
@adrian-prantl
Copy link
Collaborator Author

Two high-level comments:

  • I think that the FromError/clone changes would be better of as a separate patch(es). I have no problem with the changes themselves, but I think it'd be better to separate the meat of this patch from the mechanical renaming. The renames could be done either before an after the patch, as (AFAICT) the functions are just fancy names for (copy) constructors.

I can do that.

  • I think this class should accept an open class hierarchy (like llvm::Error) does and not assume that it can enumerate all the error subclasses. I think the only additional property that we need of the error classes is the ability to clone themselves, which we could achieve by providing a ClonableErrorInfo class with an abstract clone method. We can still keep the code which converts all unclonable errors into a string error (but I'd only do it after a copy, not immediately during construction). The thing I want to avoid is the proliferation of very specific error types inside the base Status class -- the mach/windows error types should arguably be defined in the host library, and even the ExpressionError type might be better off inside the command interpreter or something. I'm not saying you have to do the refactor now, but I'd like to have the option to do so in the future.

It really looks like the need for cloneable errors and long-term storage of errors is the key insight that came out of this patch. I'll think a bit about this as I'm splitting this patch up further.

@adrian-prantl
Copy link
Collaborator Author

So far I broke out #106774 and #107170. I'm still thinking about how to approach Pavel's cloneableError suggestion.

@adrian-prantl
Copy link
Collaborator Author

Wasn't half as bad. @labath This update introduces a ClonableError base class. This will enable us (after a bit more refactoring) to move the various Error subclass declarations closer to where they are needed. Right now the ErrorFromEnums() method still prevents that.

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am worried about the thread safety aspects of this, in particular for these "long term storage" errors. I don't know if we have any users like this, but I think it wouldn't be unreasonable for someone to expect that they can access these errors from multiple threads (concurrently). I'm not sure if the current implementation is safe in this respect, but I suspect it isn't because of the fiddling with the "checked" flag that the Error class does. If it is a problem, one way around it might be to store the Error in a "deconstructed" form -- as a list of ErrorInfoBase objects...

Comment on lines 59 to 70
class ExpressionCategory : public std::error_category {
const char *name() const override { return "LLDBExpressionCategory"; }
std::string message(int __ev) const override {
return ExecutionResultAsCString(static_cast<lldb::ExpressionResults>(__ev));
};
};
ExpressionCategory &expression_category() {
static ExpressionCategory g_expression_category;
return g_expression_category;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this? My understanding was that the std::error_code conversion is for compatibility, and so we may not need it if we can ensure that everyone gets the error string via info->message() rather than info->convertToErrorCode().message().

Since we did have this class up to this point, I don't think we have any instances of the second pattern.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the time being, we do. I'm not opposed to get rid of this later, either. Right now expressions return an ExpressionResult enum, which is encoded as this custom ExpressionCategory error code in this patch.

A failing expression returns an
ErrorList({
ECError(ExpressionCategory, ExpressionResult),
ExpressionError(diagnostic1),
ExpressionError(diagnostic2),
...
})

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that's fine, although I'm wondering if an error list is the best way to represent these. If I were doing this, I might have a single "ExpressionError" which contains the ExpressionResult enum and a list of compiler diagnostics (errors).

/// Creates a deep copy of all known errors and converts all other
/// errors to a new llvm::StringError.
static llvm::Error CloneError(llvm::Error &error) {
std::vector<std::unique_ptr<llvm::ErrorInfoBase>> info;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could avoid the temporary vector by using llvm::joinErrors directly from the callback.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping. WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that we then would need to delay initializing an llvm::Error variable. I could not find any code that makes this look any less ugly than what we have now. (I toyed with an optionalllvm::Error).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about this:

  Error result = ErrorSuccess();
  auto clone = [](const ErrorInfoBase &e) {
    if (e.isA<CloneableError>())
      return Error(static_cast<const CloneableError &>(e)->Clone());
    return make_error<StringError>(e.message(), e.convertToErrorCode(), true);
  };
  visitErrors(r, [&](const ErrorInfoBase &e) {
    result = joinErrors(std::move(result), clone(e));
  });
  return result;

Comment on lines 248 to 246
if (ec.category() == std::generic_category() ||
ec.category() == generic_category() ||
ec.category() == expression_category())
result = ec.value();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

@labath
Copy link
Collaborator

labath commented Sep 5, 2024

Wasn't half as bad. @labath This update introduces a ClonableError base class. This will enable us (after a bit more refactoring) to move the various Error subclass declarations closer to where they are needed. Right now the ErrorFromEnums() method still prevents that.

I think that's fine. We can do something about that, and at least it enables us to avoid adding new error types to this file.

@labath
Copy link
Collaborator

labath commented Sep 5, 2024

Also, some (unit) tests would be nice.

@adrian-prantl adrian-prantl force-pushed the status-wraps-error branch 2 times, most recently from 6e4559f to 12bf3fb Compare September 5, 2024 20:43
adrian-prantl added a commit that referenced this pull request Sep 19, 2024
@adrian-prantl
Copy link
Collaborator Author

So I thought I had understood this because I had simulated the missing ip6 support on the bots inside of Socked::CreateSocket, but I still had failing unit tests at the end of the day so I reverted this again for now.

adrian-prantl added a commit that referenced this pull request Sep 19, 2024
…FC) (#106774)

(based on a conversation I had with @labath yesterday in
#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError.
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
…FC) (llvm#106774)

(based on a conversation I had with @labath yesterday in
llvm#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
…FC) (llvm#106774)

(based on a conversation I had with @labath yesterday in
llvm#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError.
@DavidSpickett
Copy link
Collaborator

DavidSpickett commented Sep 20, 2024

This is failing on Windows because we use an error code that means there was no error in one of the tests in lldb/unittests/Utility/StatusTest.cpp:

  auto success = Status(NO_ERROR, ErrorType::eErrorTypeWin32);
  EXPECT_STREQ(NULL, success.AsCString());
  EXPECT_FALSE(success.ToError());
  EXPECT_TRUE(success.Success());

This now marks the status as a failure.

https://lab.llvm.org/buildbot/#/builders/141/builds/2544

I would be tempted to remove the test but given that this is a Windows defined value, all sorts of APIs might return it and we don't want to be marking lots of things as failures when they aren't.

DavidSpickett added a commit that referenced this pull request Sep 20, 2024
…Error (NFC) (#106774)"

This reverts commit 104b249 because
it has caused 2 test failures on Windows:
https://lab.llvm.org/buildbot/#/builders/141/builds/2544

Failed Tests (2):
  lldb-api :: functionalities/gdb_remote_client/TestGDBRemotePlatformFile.py
  lldb-unit :: Utility/./UtilityTests.exe/StatusTest/ErrorWin32

I reckon the cause is the same, that we construct an error with the Win32
NO_ERROR value which means there was no error but we're assuming anything
with an error code is a failure.
@DavidSpickett
Copy link
Collaborator

I've reverted this 1553714. I feel like the solution isn't that complicated but it's close to end of the work day for me and I'd like to see the bot green again.

If you have a suggestion on how to handle this I can try it on Windows on Monday.

@DavidSpickett
Copy link
Collaborator

Output from the 2 failures:

FAIL: test_file_fail (TestGDBRemotePlatformFile.TestGDBRemotePlatformFile.test_file_fail)

    Test mocked failures of remote operations

----------------------------------------------------------------------

Traceback (most recent call last):
  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\test\API\functionalities\gdb_remote_client\TestGDBRemotePlatformFile.py", line 53, in test_file_fail
    self.match(
  File "C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\packages\Python\lldbsuite\test\lldbtest.py", line 2092, in match
    self.assertTrue(
AssertionError: False is not true : 'platform file open /some/file.txt -v 0755' returned unexpected result, got 'error: function not supported'

Config=aarch64-C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\bin\clang.exe

----------------------------------------------------------------------

******************** TEST 'lldb-unit :: Utility/./UtilityTests.exe/1/8' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Utility\.\UtilityTests.exe-lldb-unit-4868-1-8.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=8 GTEST_SHARD_INDEX=1 C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Utility\.\UtilityTests.exe
--

Script:
--
C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\build\tools\lldb\unittests\Utility\.\UtilityTests.exe --gtest_filter=StatusTest.ErrorWin32
--
C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp(86): error: Expected equality of these values:
  0
    Which is: NULL
  success.AsCString()
    Which is: "The operation completed successfully. "

C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp(87): error: Value of: success.ToError()
  Actual: true
Expected: false

C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp(88): error: Value of: success.Success()
  Actual: false
Expected: true


C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp:86
Expected equality of these values:
  0
    Which is: NULL
  success.AsCString()
    Which is: "The operation completed successfully. "

C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp:87
Value of: success.ToError()
  Actual: true
Expected: false

C:\Users\tcwg\llvm-worker\lldb-aarch64-windows\llvm-project\lldb\unittests\Utility\StatusTest.cpp:88
Value of: success.Success()
  Actual: false
Expected: true

adrian-prantl added a commit that referenced this pull request Sep 21, 2024
…FC) (#106774)

(based on a conversation I had with @labath yesterday in
#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError, and support
for initializing a Windows error with a NO_ERROR error code.
adrian-prantl added a commit that referenced this pull request Sep 21, 2024
adrian-prantl added a commit that referenced this pull request Sep 23, 2024
…FC) (#106774)

(based on a conversation I had with @labath yesterday in
#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError, and support
for initializing a Windows error with a NO_ERROR error code.
adrian-prantl added a commit that referenced this pull request Sep 23, 2024
…Error (NFC) (#106774)"

This reverts commit 40d8888.
One last Windows failure remaining.
adrian-prantl added a commit that referenced this pull request Sep 23, 2024
…FC) (#106774)

(based on a conversation I had with @labath yesterday in
#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError, and support
for initializing a Windows error with a NO_ERROR error code, and
modifying TestGDBRemotePlatformFile.py to support different renderings
of ENOSYS.
adrian-prantl added a commit to adrian-prantl/llvm-project that referenced this pull request Oct 11, 2024
…FC) (llvm#106774)

(based on a conversation I had with @labath yesterday in
llvm#106442)

Most APIs that currently vend a Status would be better served by
returning llvm::Expected<> instead. If possibles APIs should be
refactored to avoid Status. The only legitimate long-term uses of Status
are objects that need to store an error for a long time (which should be
questioned as a design decision, too).

This patch makes the transition to llvm::Error easier by making the
places that cannot switch to llvm::Error explicit: They are marked with
a call to Status::clone(). Every other API can and should be refactored
to use llvm::Expected. In the end Status should only be used in very few
places.

Whenever an unchecked Error is dropped by Status it logs this to the
verbose API channel.

Implementation notes:

This patch introduces two new kinds of error_category as well as new
llvm::Error types. Here is the mapping of lldb::ErrorType to
llvm::Errors:
```
   (eErrorTypeInvalid)
   eErrorTypeGeneric      llvm::StringError
   eErrorTypePOSIX        llvm::ECError
   eErrorTypeMachKernel   MachKernelError
   eErrorTypeExpression   llvm::ErrorList<ExpressionError>
   eErrorTypeWin32        Win32Error
```

Relanding with built-in cloning support for llvm::ECError, and support
for initializing a Windows error with a NO_ERROR error code, and
modifying TestGDBRemotePlatformFile.py to support different renderings
of ENOSYS.

(cherry picked from commit 1fae131)
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Oct 31, 2024
…5170ac5f7

Local branch amd-gfx b625170 Merged main:76883932014bcce2efb57be062f901de26317707 into amd-gfx:888e970457a7
Remote branch main b44da24 [lldb] Change the implementation of Status to store an llvm::Error (NFC) (llvm#106774)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants