Skip to content

Commit 12bf3fb

Browse files
committed
[lldb] Change the implementation of Status to store an llvm::Error (NFC)
Most APIs that currently vend a Status would be better served by returning llvm::Expected<> instead. Where possible, 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
1 parent 3b426a8 commit 12bf3fb

File tree

2 files changed

+233
-86
lines changed

2 files changed

+233
-86
lines changed

lldb/include/lldb/Utility/Status.h

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,66 @@ namespace lldb_private {
2828

2929
const char *ExpressionResultAsCString(lldb::ExpressionResults result);
3030

31+
/// Going a bit against the spirit of llvm::Error,
32+
/// lldb_private::Status need to store errors long-term and sometimes
33+
/// copy them. This base class defines an interface for this
34+
/// operation.
35+
class CloneableError
36+
: public llvm::ErrorInfo<CloneableError, llvm::ErrorInfoBase> {
37+
public:
38+
using llvm::ErrorInfo<CloneableError, llvm::ErrorInfoBase>::ErrorInfo;
39+
CloneableError() : ErrorInfo() {}
40+
virtual std::unique_ptr<CloneableError> Clone() const = 0;
41+
static char ID;
42+
};
43+
44+
/// Common base class for all error-code errors.
45+
class CloneableECError
46+
: public llvm::ErrorInfo<CloneableECError, CloneableError> {
47+
public:
48+
using llvm::ErrorInfo<CloneableECError, CloneableError>::ErrorInfo;
49+
CloneableECError(std::error_code ec) : ErrorInfo() {}
50+
std::error_code convertToErrorCode() const override { return EC; }
51+
void log(llvm::raw_ostream &OS) const override { OS << EC.message(); }
52+
static char ID;
53+
54+
protected:
55+
std::error_code EC;
56+
};
57+
58+
/// FIXME: Move these declarations closer to where they're used.
59+
class MachKernelError
60+
: public llvm::ErrorInfo<MachKernelError, CloneableECError> {
61+
public:
62+
using llvm::ErrorInfo<MachKernelError, CloneableECError>::ErrorInfo;
63+
MachKernelError(std::error_code ec) : ErrorInfo(ec) {}
64+
std::string message() const override;
65+
std::unique_ptr<CloneableError> Clone() const override;
66+
static char ID;
67+
};
68+
69+
class Win32Error : public llvm::ErrorInfo<Win32Error, CloneableECError> {
70+
public:
71+
using llvm::ErrorInfo<Win32Error, CloneableECError>::ErrorInfo;
72+
Win32Error(std::error_code ec, const llvm::Twine &msg = {}) : ErrorInfo(ec) {}
73+
std::string message() const override;
74+
std::unique_ptr<CloneableError> Clone() const override;
75+
static char ID;
76+
};
77+
78+
class ExpressionError
79+
: public llvm::ErrorInfo<ExpressionError, CloneableECError> {
80+
public:
81+
using llvm::ErrorInfo<ExpressionError, CloneableECError>::ErrorInfo;
82+
ExpressionError(std::error_code ec, std::string msg = {})
83+
: ErrorInfo(ec), m_string(msg) {}
84+
std::unique_ptr<CloneableError> Clone() const override;
85+
static char ID;
86+
87+
protected:
88+
std::string m_string;
89+
};
90+
3191
/// \class Status Status.h "lldb/Utility/Status.h" An error handling class.
3292
///
3393
/// This class is designed to be able to hold any error code that can be
@@ -100,9 +160,7 @@ class Status {
100160
}
101161

102162
static Status FromExpressionError(lldb::ExpressionResults result,
103-
std::string msg) {
104-
return Status(result, lldb::eErrorTypeExpression, msg);
105-
}
163+
std::string msg);
106164

107165
/// Set the current error to errno.
108166
///
@@ -115,6 +173,7 @@ class Status {
115173
const Status &operator=(Status &&);
116174
/// Avoid using this in new code. Migrate APIs to llvm::Expected instead.
117175
static Status FromError(llvm::Error error);
176+
118177
/// FIXME: Replace this with a takeError() method.
119178
llvm::Error ToError() const;
120179
/// Don't call this function in new code. Instead, redesign the API
@@ -170,12 +229,8 @@ class Status {
170229
bool Success() const;
171230

172231
protected:
173-
Status(llvm::Error error);
174-
/// Status code as an integer value.
175-
ValueType m_code = 0;
176-
/// The type of the above error code.
177-
lldb::ErrorType m_type = lldb::eErrorTypeInvalid;
178-
/// A string representation of the error code.
232+
Status(llvm::Error error) : m_error(std::move(error)) {}
233+
mutable llvm::Error m_error;
179234
mutable std::string m_string;
180235
};
181236

0 commit comments

Comments
 (0)