mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-28 06:00:28 +00:00
[Support] Switch to RAII helper for error-as-out-parameter idiom.
As discussed on the llvm-commits thread for r264467. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264479 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9a0b1af1ce
commit
bbb35fb68d
@ -143,13 +143,6 @@ public:
|
||||
/// constructor, but should be preferred for readability where possible.
|
||||
static Error success() { return Error(); }
|
||||
|
||||
/// Create a 'pre-checked' success value suitable for use as an out-parameter.
|
||||
static Error errorForOutParameter() {
|
||||
Error Err;
|
||||
(void)!!Err;
|
||||
return Err;
|
||||
}
|
||||
|
||||
// Errors are not copy-constructable.
|
||||
Error(const Error &Other) = delete;
|
||||
|
||||
@ -552,6 +545,36 @@ inline void consumeError(Error Err) {
|
||||
handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {});
|
||||
}
|
||||
|
||||
/// Helper for Errors used as out-parameters.
|
||||
///
|
||||
/// This helper is for use with the Error-as-out-parameter idiom, where an error
|
||||
/// is passed to a function or method by reference, rather than being returned.
|
||||
/// In such cases it is helpful to set the checked bit on entry to the function
|
||||
/// so that the error can be written to (unchecked Errors abort on assignment)
|
||||
/// and clear the checked bit on exit so that clients cannot accidentally forget
|
||||
/// to check the result. This helper performs these actions automatically using
|
||||
/// RAII:
|
||||
///
|
||||
/// Result foo(Error &Err) {
|
||||
/// ErrorAsOutParameter ErrAsOutParam(Err); // 'Checked' flag set
|
||||
/// // <body of foo>
|
||||
/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
|
||||
/// }
|
||||
class ErrorAsOutParameter {
|
||||
public:
|
||||
ErrorAsOutParameter(Error &Err) : Err(Err) {
|
||||
// Raise the checked bit if Err is success.
|
||||
(void)!!Err;
|
||||
}
|
||||
~ErrorAsOutParameter() {
|
||||
// Clear the checked bit.
|
||||
if (!Err)
|
||||
Err = Error::success();
|
||||
}
|
||||
private:
|
||||
Error &Err;
|
||||
};
|
||||
|
||||
/// Tagged union holding either a T or a Error.
|
||||
///
|
||||
/// This class parallels ErrorOr, but replaces error_code with Error. Since
|
||||
|
@ -246,7 +246,7 @@ static Error parseSegmentLoadCommand(
|
||||
Expected<std::unique_ptr<MachOObjectFile>>
|
||||
MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
|
||||
bool Is64Bits) {
|
||||
Error Err = Error::errorForOutParameter();
|
||||
Error Err;
|
||||
std::unique_ptr<MachOObjectFile> Obj(
|
||||
new MachOObjectFile(std::move(Object), IsLittleEndian,
|
||||
Is64Bits, Err));
|
||||
@ -262,7 +262,7 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
|
||||
DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
|
||||
DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
|
||||
HasPageZeroSegment(false) {
|
||||
|
||||
ErrorAsOutParameter ErrAsOutParam(Err);
|
||||
if (is64Bit())
|
||||
parseHeader(this, Header64, Err);
|
||||
else
|
||||
|
@ -105,12 +105,32 @@ TEST(Error, UncheckedSuccess) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Test that errors to be used as out parameters are implicitly checked (
|
||||
// and thus destruct quietly).
|
||||
TEST(Error, ErrorAsOutParameter) {
|
||||
Error E = Error::errorForOutParameter();
|
||||
// ErrorAsOutParameter tester.
|
||||
void errAsOutParamHelper(Error &Err) {
|
||||
ErrorAsOutParameter ErrAsOutParam(Err);
|
||||
// Verify that checked flag is raised - assignment should not crash.
|
||||
Err = Error::success();
|
||||
// Raise the checked bit manually - caller should still have to test the
|
||||
// error.
|
||||
(void)!!Err;
|
||||
}
|
||||
|
||||
// Test that ErrorAsOutParameter sets the checked flag on construction.
|
||||
TEST(Error, ErrorAsOutParameterChecked) {
|
||||
Error E;
|
||||
errAsOutParamHelper(E);
|
||||
(void)!!E;
|
||||
}
|
||||
|
||||
// Test that ErrorAsOutParameter clears the checked flag on destruction.
|
||||
#ifndef NDEBUG
|
||||
TEST(Error, ErrorAsOutParameterUnchecked) {
|
||||
EXPECT_DEATH({ Error E; errAsOutParamHelper(E); },
|
||||
"Program aborted due to an unhandled Error:")
|
||||
<< "ErrorAsOutParameter did not clear the checked flag on destruction.";
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check that we abort on unhandled failure cases. (Force conversion to bool
|
||||
// to make sure that we don't accidentally treat checked errors as handled).
|
||||
// Test runs in debug mode only.
|
||||
|
Loading…
Reference in New Issue
Block a user