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 <stdint.h>
19#include <string>
20#include <system_error>
21#include <type_traits>
22
23namespace llvm {
24class raw_ostream;
25}
26
27namespace 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.
44class Status {
45public:
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 ~Status();
68
69 // llvm::Error support
70 explicit Status(llvm::Error error) { *this = std::move(error); }
71 const Status &operator=(llvm::Error error);
72 llvm::Error ToError() const;
73
74 /// Get the error string associated with the current error.
75 //
76 /// Gets the error value as a NULL terminated C string. The error string
77 /// will be fetched and cached on demand. The error string will be retrieved
78 /// from a callback that is appropriate for the type of the error and will
79 /// be cached until the error value is changed or cleared.
80 ///
81 /// \return
82 /// The error as a NULL terminated C string value if the error
83 /// is valid and is able to be converted to a string value,
84 /// NULL otherwise.
85 const char *AsCString(const char *default_error_str = "unknown error") const;
86
87 /// Clear the object state.
88 ///
89 /// Reverts the state of this object to contain a generic success value and
90 /// frees any cached error string value.
91 void Clear();
92
93 /// Test for error condition.
94 ///
95 /// \return
96 /// \b true if this object contains an error, \b false
97 /// otherwise.
98 bool Fail() const;
99
100 /// Access the error value.
101 ///
102 /// \return
103 /// The error value.
104 ValueType GetError() const;
105
106 /// Access the error type.
107 ///
108 /// \return
109 /// The error type enumeration value.
110 lldb::ErrorType GetType() const;
111
112 /// Set accessor from a kern_return_t.
113 ///
114 /// Set accessor for the error value to \a err and the error type to \c
115 /// MachKernel.
116 ///
117 /// \param[in] err
118 /// A mach error code.
119 void SetMachError(uint32_t err);
120
121 void SetExpressionError(lldb::ExpressionResults, const char *mssg);
122
123 int SetExpressionErrorWithFormat(lldb::ExpressionResults, const char *format,
124 ...) __attribute__((format(printf, 3, 4)));
125
126 /// Set accessor with an error value and type.
127 ///
128 /// Set accessor for the error value to \a err and the error type to \a
129 /// type.
130 ///
131 /// \param[in] err
132 /// A mach error code.
133 ///
134 /// \param[in] type
135 /// The type for \a err.
136 void SetError(ValueType err, lldb::ErrorType type);
137
138 /// Set the current error to errno.
139 ///
140 /// Update the error value to be \c errno and update the type to be \c
141 /// Status::POSIX.
142 void SetErrorToErrno();
143
144 /// Set the current error to a generic error.
145 ///
146 /// Update the error value to be \c LLDB_GENERIC_ERROR and update the type
147 /// to be \c Status::Generic.
148 void SetErrorToGenericError();
149
150 /// Set the current error string to \a err_str.
151 ///
152 /// Set accessor for the error string value for a generic errors, or to
153 /// supply additional details above and beyond the standard error strings
154 /// that the standard type callbacks typically provide. This allows custom
155 /// strings to be supplied as an error explanation. The error string value
156 /// will remain until the error value is cleared or a new error value/type
157 /// is assigned.
158 ///
159 /// \param err_str
160 /// The new custom error string to copy and cache.
161 void SetErrorString(llvm::StringRef err_str);
162
163 /// Set the current error string to a formatted error string.
164 ///
165 /// \param format
166 /// A printf style format string
167 int SetErrorStringWithFormat(const char *format, ...)
168 __attribute__((format(printf, 2, 3)));
169
170 int SetErrorStringWithVarArg(const char *format, va_list args);
171
172 template <typename... Args>
173 void SetErrorStringWithFormatv(const char *format, Args &&... args) {
174 SetErrorString(llvm::formatv(format, std::forward<Args>(args)...).str());
175 }
176
177 /// Test for success condition.
178 ///
179 /// Returns true if the error code in this object is considered a successful
180 /// return value.
181 ///
182 /// \return
183 /// \b true if this object contains an value that describes
184 /// success (non-erro), \b false otherwise.
185 bool Success() const;
186
187 /// Test for a failure due to a generic interrupt.
188 ///
189 /// Returns true if the error code in this object was caused by an
190 /// interrupt. At present only supports Posix EINTR.
191 ///
192 /// \return
193 /// \b true if this object contains an value that describes
194 /// failure due to interrupt, \b false otherwise.
195 bool WasInterrupted() const;
196
197protected:
198 /// Member variables
199 ValueType m_code; ///< Status code as an integer value.
200 lldb::ErrorType m_type; ///< The type of the above error code.
201 mutable std::string m_string; ///< A string representation of the error code.
202};
203
204} // namespace lldb_private
205
206namespace llvm {
207template <> struct format_provider<lldb_private::Status> {
208 static void format(const lldb_private::Status &error, llvm::raw_ostream &OS,
209 llvm::StringRef Options);
210};
211}
212
213#define LLDB_ERRORF(status, fmt, ...) \
214 do { \
215 if (status) { \
216 (status)->SetErrorStringWithFormat((fmt), __VA_ARGS__); \
217 } \
218 } while (0);
219
220#endif // LLDB_UTILITY_STATUS_H
221