1 //===-- Status.h ------------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_UTILITY_STATUS_H 10 #define LLDB_UTILITY_STATUS_H 11 12 #include "lldb/lldb-defines.h" 13 #include "lldb/lldb-enumerations.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Support/Error.h" 16 #include "llvm/Support/FormatVariadic.h" 17 #include <cstdarg> 18 #include <cstdint> 19 #include <string> 20 #include <system_error> 21 #include <type_traits> 22 23 namespace llvm { 24 class raw_ostream; 25 } 26 27 namespace lldb_private { 28 29 /// \class Status Status.h "lldb/Utility/Status.h" An error handling class. 30 /// 31 /// This class is designed to be able to hold any error code that can be 32 /// encountered on a given platform. The errors are stored as a value of type 33 /// Status::ValueType. This value should be large enough to hold any and all 34 /// errors that the class supports. Each error has an associated type that is 35 /// of type lldb::ErrorType. New types can be added to support new error 36 /// types, and architecture specific types can be enabled. In the future we 37 /// may wish to switch to a registration mechanism where new error types can 38 /// be registered at runtime instead of a hard coded scheme. 39 /// 40 /// All errors in this class also know how to generate a string representation 41 /// of themselves for printing results and error codes. The string value will 42 /// be fetched on demand and its string value will be cached until the error 43 /// is cleared of the value of the error changes. 44 class Status { 45 public: 46 /// Every error value that this object can contain needs to be able to fit 47 /// into ValueType. 48 typedef uint32_t ValueType; 49 50 Status(); 51 52 /// Initialize the error object with a generic success value. 53 /// 54 /// \param[in] err 55 /// An error code. 56 /// 57 /// \param[in] type 58 /// The type for \a err. 59 explicit Status(ValueType err, 60 lldb::ErrorType type = lldb::eErrorTypeGeneric); 61 62 Status(std::error_code EC); 63 64 explicit Status(const char *format, ...) 65 __attribute__((format(printf, 2, 3))); 66 67 template <typename... Args> 68 static Status createWithFormat(const char *format, Args &&...args) { 69 return Status(llvm::formatv(format, std::forward<Args>(args)...)); 70 } 71 72 ~Status(); 73 74 // llvm::Error support 75 explicit Status(llvm::Error error) { *this = std::move(error); } 76 const Status &operator=(llvm::Error error); 77 llvm::Error ToError() const; 78 79 /// Get the error string associated with the current error. 80 // 81 /// Gets the error value as a NULL terminated C string. The error string 82 /// will be fetched and cached on demand. The error string will be retrieved 83 /// from a callback that is appropriate for the type of the error and will 84 /// be cached until the error value is changed or cleared. 85 /// 86 /// \return 87 /// The error as a NULL terminated C string value if the error 88 /// is valid and is able to be converted to a string value, 89 /// NULL otherwise. 90 const char *AsCString(const char *default_error_str = "unknown error") const; 91 92 /// Clear the object state. 93 /// 94 /// Reverts the state of this object to contain a generic success value and 95 /// frees any cached error string value. 96 void Clear(); 97 98 /// Test for error condition. 99 /// 100 /// \return 101 /// \b true if this object contains an error, \b false 102 /// otherwise. 103 bool Fail() const; 104 105 /// Access the error value. 106 /// 107 /// \return 108 /// The error value. 109 ValueType GetError() const; 110 111 /// Access the error type. 112 /// 113 /// \return 114 /// The error type enumeration value. 115 lldb::ErrorType GetType() const; 116 117 /// Set accessor from a kern_return_t. 118 /// 119 /// Set accessor for the error value to \a err and the error type to \c 120 /// MachKernel. 121 /// 122 /// \param[in] err 123 /// A mach error code. 124 void SetMachError(uint32_t err); 125 126 void SetExpressionError(lldb::ExpressionResults, const char *mssg); 127 128 int SetExpressionErrorWithFormat(lldb::ExpressionResults, const char *format, 129 ...) __attribute__((format(printf, 3, 4))); 130 131 /// Set accessor with an error value and type. 132 /// 133 /// Set accessor for the error value to \a err and the error type to \a 134 /// type. 135 /// 136 /// \param[in] err 137 /// A mach error code. 138 /// 139 /// \param[in] type 140 /// The type for \a err. 141 void SetError(ValueType err, lldb::ErrorType type); 142 143 /// Set the current error to errno. 144 /// 145 /// Update the error value to be \c errno and update the type to be \c 146 /// Status::POSIX. 147 void SetErrorToErrno(); 148 149 /// Set the current error to a generic error. 150 /// 151 /// Update the error value to be \c LLDB_GENERIC_ERROR and update the type 152 /// to be \c Status::Generic. 153 void SetErrorToGenericError(); 154 155 /// Set the current error string to \a err_str. 156 /// 157 /// Set accessor for the error string value for a generic errors, or to 158 /// supply additional details above and beyond the standard error strings 159 /// that the standard type callbacks typically provide. This allows custom 160 /// strings to be supplied as an error explanation. The error string value 161 /// will remain until the error value is cleared or a new error value/type 162 /// is assigned. 163 /// 164 /// \param err_str 165 /// The new custom error string to copy and cache. 166 void SetErrorString(llvm::StringRef err_str); 167 168 /// Set the current error string to a formatted error string. 169 /// 170 /// \param format 171 /// A printf style format string 172 int SetErrorStringWithFormat(const char *format, ...) 173 __attribute__((format(printf, 2, 3))); 174 175 int SetErrorStringWithVarArg(const char *format, va_list args); 176 177 template <typename... Args> 178 void SetErrorStringWithFormatv(const char *format, Args &&... args) { 179 SetErrorString(llvm::formatv(format, std::forward<Args>(args)...).str()); 180 } 181 182 /// Test for success condition. 183 /// 184 /// Returns true if the error code in this object is considered a successful 185 /// return value. 186 /// 187 /// \return 188 /// \b true if this object contains an value that describes 189 /// success (non-erro), \b false otherwise. 190 bool Success() const; 191 192 protected: 193 /// Member variables 194 ValueType m_code = 0; ///< Status code as an integer value. 195 lldb::ErrorType m_type = 196 lldb::eErrorTypeInvalid; ///< The type of the above error code. 197 mutable std::string m_string; ///< A string representation of the error code. 198 private: 199 explicit Status(const llvm::formatv_object_base &payload) { 200 SetErrorToGenericError(); 201 m_string = payload.str(); 202 } 203 }; 204 205 } // namespace lldb_private 206 207 namespace llvm { 208 template <> struct format_provider<lldb_private::Status> { 209 static void format(const lldb_private::Status &error, llvm::raw_ostream &OS, 210 llvm::StringRef Options); 211 }; 212 } 213 214 #define LLDB_ERRORF(status, fmt, ...) \ 215 do { \ 216 if (status) { \ 217 (status)->SetErrorStringWithFormat((fmt), __VA_ARGS__); \ 218 } \ 219 } while (0); 220 221 #endif // LLDB_UTILITY_STATUS_H 222