Skip to content

Check *all* errors in LLVMRustArchiveIterator* API #38676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 30, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions src/rustllvm/ArchiveWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ struct RustArchiveMember {


struct RustArchiveIterator {
bool first;
Archive::child_iterator cur;
Archive::child_iterator end;
#if LLVM_VERSION_GE(3, 9)
Error err;

RustArchiveIterator() : err(Error::success()) { }
RustArchiveIterator() : first(true), err(Error::success()) { }
#else
RustArchiveIterator() : first(true) { }
#endif
};

Expand Down Expand Up @@ -120,6 +123,7 @@ LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
rai->cur = ar->child_begin(rai->err);
if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
delete rai;
return NULL;
}
#endif
Expand All @@ -129,27 +133,40 @@ LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {

extern "C" LLVMRustArchiveChildConstRef
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
if (rai->cur == rai->end) return nullptr;

// Advancing the iterator validates the next child, and this can
// uncover an error. LLVM requires that we check all Errors,
// so we only advance the iterator if we actually need to fetch
// the next child.
// This means we must not advance the iterator in the *first* call,
// but instead advance it *before* fetching the child in all later calls.
if (!rai->first) {
++rai->cur;
#if LLVM_VERSION_GE(3, 9)
if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
return NULL;
}
if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
return nullptr;
}
#endif
if (rai->cur == rai->end)
return NULL;
} else {
rai->first = false;
}

if (rai->cur == rai->end) return nullptr;

#if LLVM_VERSION_EQ(3, 8)
const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
if (!*cur) {
LLVMRustSetLastError(cur->getError().message().c_str());
return NULL;
return nullptr;
}
const Archive::Child &child = cur->get();
#else
const Archive::Child &child = *rai->cur.operator->();
#endif
Archive::Child *ret = new Archive::Child(child);

++rai->cur;
return ret;
}

Expand Down