1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[Support] Make ErrorAsOutParameter take an Error* rather than an Error&.

This allows ErrorAsOutParameter to work better with "optional" errors. For
example, consider a function where for certain input values it is known that
the function can't fail. This can now be written as:

Result foo(Arg X, Error *Err) {
  ErrorAsOutParameter EAO(Err);

  if (<Error Condition>) {
    if (Err)
      *Err = <report error>;
    else
      llvm_unreachable("Unexpected failure!");
  }
}

Rather than having to construct an ErrorAsOutParameter under every conditional
where Err is known to be non-null.

llvm-svn: 276430
This commit is contained in:
Lang Hames 2016-07-22 16:11:25 +00:00
parent c5dafe9b5a
commit 3bf43acb9a
7 changed files with 22 additions and 15 deletions

View File

@ -688,7 +688,7 @@ public:
private:
OrcRemoteTargetClient(ChannelT &Channel, Error &Err) : Channel(Channel) {
ErrorAsOutParameter EAO(Err);
ErrorAsOutParameter EAO(&Err);
if (auto RIOrErr = callST<GetRemoteInfo>(Channel)) {
std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;

View File

@ -131,10 +131,10 @@ public:
// iteration. And if there is an error break out of the loop.
child_iterator &operator++() { // Preincrement
assert(E && "Can't increment iterator with no Error attached");
ErrorAsOutParameter ErrAsOutParam(E);
if (auto ChildOrErr = C.getNext())
C = *ChildOrErr;
else {
ErrorAsOutParameter ErrAsOutParam(*E);
C = C.getParent()->child_end().C;
*E = ChildOrErr.takeError();
E = nullptr;

View File

@ -571,24 +571,32 @@ inline void consumeError(Error Err) {
/// RAII:
///
/// Result foo(Error &Err) {
/// ErrorAsOutParameter ErrAsOutParam(Err); // 'Checked' flag set
/// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set
/// // <body of foo>
/// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed.
/// }
///
/// ErrorAsOutParameter takes an Error* rather than Error& so that it can be
/// used with optional Errors (Error pointers that are allowed to be null). If
/// ErrorAsOutParameter took an Error reference, an instance would have to be
/// created inside every condition that verified that Error was non-null. By
/// taking an Error pointer we can just create one instance at the top of the
/// function.
class ErrorAsOutParameter {
public:
ErrorAsOutParameter(Error &Err) : Err(Err) {
ErrorAsOutParameter(Error *Err) : Err(Err) {
// Raise the checked bit if Err is success.
(void)!!Err;
if (Err)
(void)!!*Err;
}
~ErrorAsOutParameter() {
// Clear the checked bit.
if (!Err)
Err = Error::success();
if (Err && !*Err)
*Err = Error::success();
}
private:
Error &Err;
Error *Err;
};
/// Tagged union holding either a T or a Error.

View File

@ -108,16 +108,15 @@ Archive::Child::Child(const Archive *Parent, const char *Start, Error *Err)
: Parent(Parent) {
if (!Start)
return;
ErrorAsOutParameter ErrAsOutParam(Err);
uint64_t Size = sizeof(ArchiveMemberHeader);
Data = StringRef(Start, Size);
if (!isThinMember()) {
Expected<uint64_t> MemberSize = getRawSize();
if (!MemberSize) {
if (Err) {
ErrorAsOutParameter ErrAsOutParam(*Err);
if (Err)
*Err = MemberSize.takeError();
}
return;
}
Size += MemberSize.get();
@ -299,7 +298,7 @@ void Archive::setFirstRegular(const Child &C) {
Archive::Archive(MemoryBufferRef Source, Error &Err)
: Binary(Binary::ID_Archive, Source) {
ErrorAsOutParameter ErrAsOutParam(Err);
ErrorAsOutParameter ErrAsOutParam(&Err);
StringRef Buffer = Data.getBuffer();
// Check for sufficient magic.
if (Buffer.startswith(ThinMagic)) {

View File

@ -267,7 +267,7 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr),
DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
HasPageZeroSegment(false) {
ErrorAsOutParameter ErrAsOutParam(Err);
ErrorAsOutParameter ErrAsOutParam(&Err);
uint64_t BigSize;
if (is64Bit()) {
parseHeader(this, Header64, Err);

View File

@ -114,7 +114,7 @@ MachOUniversalBinary::create(MemoryBufferRef Source) {
MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, Error &Err)
: Binary(Binary::ID_MachOUniversalBinary, Source), Magic(0),
NumberOfObjects(0) {
ErrorAsOutParameter ErrAsOutParam(Err);
ErrorAsOutParameter ErrAsOutParam(&Err);
if (Data.getBufferSize() < sizeof(MachO::fat_header)) {
Err = make_error<GenericBinaryError>("File too small to be a Mach-O "
"universal file",

View File

@ -109,7 +109,7 @@ TEST(Error, UncheckedSuccess) {
// ErrorAsOutParameter tester.
void errAsOutParamHelper(Error &Err) {
ErrorAsOutParameter ErrAsOutParam(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