Skip to content

Commit d6d55a4

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 ba2aa1d commit d6d55a4

File tree

3 files changed

+242
-90
lines changed

3 files changed

+242
-90
lines changed

lldb/include/lldb/Utility/Status.h

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,67 @@ 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+
std::string message() const override { return m_string; }
86+
static char ID;
87+
88+
protected:
89+
std::string m_string;
90+
};
91+
3192
/// \class Status Status.h "lldb/Utility/Status.h" An error handling class.
3293
///
3394
/// This class is designed to be able to hold any error code that can be
@@ -100,9 +161,7 @@ class Status {
100161
}
101162

102163
static Status FromExpressionError(lldb::ExpressionResults result,
103-
std::string msg) {
104-
return Status(result, lldb::eErrorTypeExpression, msg);
105-
}
164+
std::string msg);
106165

107166
/// Set the current error to errno.
108167
///
@@ -115,6 +174,7 @@ class Status {
115174
const Status &operator=(Status &&);
116175
/// Avoid using this in new code. Migrate APIs to llvm::Expected instead.
117176
static Status FromError(llvm::Error error);
177+
118178
/// FIXME: Replace this with a takeError() method.
119179
llvm::Error ToError() const;
120180
/// Don't call this function in new code. Instead, redesign the API
@@ -149,12 +209,20 @@ class Status {
149209

150210
/// Access the error value.
151211
///
212+
/// If the internally stored \ref llvm::Error is an \ref
213+
/// llvm::ErrorList then this returns the error value of the first
214+
/// error.
215+
///
152216
/// \return
153217
/// The error value.
154218
ValueType GetError() const;
155219

156220
/// Access the error type.
157221
///
222+
/// If the internally stored \ref llvm::Error is an \ref
223+
/// llvm::ErrorList then this returns the error value of the first
224+
/// error.
225+
///
158226
/// \return
159227
/// The error type enumeration value.
160228
lldb::ErrorType GetType() const;
@@ -170,12 +238,9 @@ class Status {
170238
bool Success() const;
171239

172240
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.
241+
Status(llvm::Error error) : m_error(std::move(error)) {}
242+
llvm::Error m_error;
243+
/// TODO: Replace this with just callling toString(m_error).
179244
mutable std::string m_string;
180245
};
181246

lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,9 @@ PythonException::PythonException(const char *caller) {
973973
PyErr_Clear();
974974
}
975975
Py_XDECREF(repr);
976+
Py_INCREF(m_exception);
977+
if (m_traceback)
978+
Py_INCREF(m_traceback);
976979
} else {
977980
PyErr_Clear();
978981
}
@@ -993,8 +996,8 @@ void PythonException::Restore() {
993996
}
994997

995998
PythonException::~PythonException() {
996-
Py_XDECREF(m_exception_type);
997999
Py_XDECREF(m_exception);
1000+
Py_XDECREF(m_exception_type);
9981001
Py_XDECREF(m_traceback);
9991002
Py_XDECREF(m_repr_bytes);
10001003
}

0 commit comments

Comments
 (0)