diff options
author | Lang Hames <lhames@gmail.com> | 2019-02-05 23:17:11 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2019-02-05 23:17:11 +0000 |
commit | 3e040e05f89c058bb6e6a88c4e9ffccf1185b084 (patch) | |
tree | 499687725ced8471cb5893b8d57f80f937c60165 /llvm/lib/Object | |
parent | 7b7a4ef3d33d85efa6b27a51919fe7ef956be6ee (diff) | |
download | bcm5719-llvm-3e040e05f89c058bb6e6a88c4e9ffccf1185b084.tar.gz bcm5719-llvm-3e040e05f89c058bb6e6a88c4e9ffccf1185b084.zip |
[ADT] Add a fallible_iterator wrapper.
A fallible iterator is one whose increment or decrement operations may fail.
This would usually be supported by replacing the ++ and -- operators with
methods that return error:
class MyFallibleIterator {
public:
// ...
Error inc();
Errro dec();
// ...
};
The downside of this style is that it no longer conforms to the C++ iterator
concept, and can not make use of standard algorithms and features such as
range-based for loops.
The fallible_iterator wrapper takes an iterator written in the style above
and adapts it to (mostly) conform with the C++ iterator concept. It does this
by providing standard ++ and -- operator implementations, returning any errors
generated via a side channel (an Error reference passed into the wrapper at
construction time), and immediately jumping the iterator to a known 'end'
value upon error. It also marks the Error as checked any time an iterator is
compared with a known end value and found to be inequal, allowing early exit
from loops without redundant error checking*.
Usage looks like:
MyFallibleIterator I = ..., E = ...;
Error Err = Error::success();
for (auto &Elem : make_fallible_range(I, E, Err)) {
// Loop body is only entered when safe.
// Early exits from loop body permitted without checking Err.
if (SomeCondition)
return;
}
if (Err)
// Handle error.
* Since failure causes a fallible iterator to jump to end, testing that a
fallible iterator is not an end value implicitly verifies that the error is a
success value, and so is equivalent to an error check.
Reviewers: dblaikie, rupprecht
Subscribers: mgorny, dexonsmith, kristina, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D57618
llvm-svn: 353237
Diffstat (limited to 'llvm/lib/Object')
-rw-r--r-- | llvm/lib/Object/Archive.cpp | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/llvm/lib/Object/Archive.cpp b/llvm/lib/Object/Archive.cpp index 3def30949fc..1d31feb714e 100644 --- a/llvm/lib/Object/Archive.cpp +++ b/llvm/lib/Object/Archive.cpp @@ -778,19 +778,18 @@ Archive::child_iterator Archive::child_begin(Error &Err, return child_end(); if (SkipInternal) - return child_iterator(Child(this, FirstRegularData, - FirstRegularStartOfFile), - &Err); + return child_iterator::itr( + Child(this, FirstRegularData, FirstRegularStartOfFile), Err); const char *Loc = Data.getBufferStart() + strlen(Magic); Child C(this, Loc, &Err); if (Err) return child_end(); - return child_iterator(C, &Err); + return child_iterator::itr(C, Err); } Archive::child_iterator Archive::child_end() const { - return child_iterator(Child(nullptr, nullptr, nullptr), nullptr); + return child_iterator::end(Child(nullptr, nullptr, nullptr)); } StringRef Archive::Symbol::getName() const { |