about summary refs log tree commit diff
path: root/src/rustllvm/ArchiveWrapper.cpp
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-12-30 07:34:19 +0000
committerbors <bors@rust-lang.org>2016-12-30 07:34:19 +0000
commit7f2d2afa9196ba6314a29e58d5324dbd9923c75e (patch)
tree483907141a5dcd2cfc7e4ea91f7234d77bddf83b /src/rustllvm/ArchiveWrapper.cpp
parent75f5981d4500e52de767d61ec50a34b97be2a301 (diff)
parente484197482698ee0bb83a66987a5f64c46ae306b (diff)
downloadrust-7f2d2afa9196ba6314a29e58d5324dbd9923c75e.tar.gz
rust-7f2d2afa9196ba6314a29e58d5324dbd9923c75e.zip
Auto merge of #38697 - alexcrichton:rollup, r=alexcrichton
Rollup of 25 pull requests

- Successful merges: #37149, #38491, #38517, #38559, #38587, #38609, #38611, #38622, #38628, #38630, #38631, #38632, #38635, #38647, #38649, #38655, #38659, #38660, #38662, #38665, #38671, #38674, #38676, #38693, #38695
- Failed merges: #38657, #38680
Diffstat (limited to 'src/rustllvm/ArchiveWrapper.cpp')
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp35
1 files changed, 26 insertions, 9 deletions
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index c7f426fbfa3..7304f384c61 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -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
 };
 
@@ -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
@@ -129,19 +133,33 @@ 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
@@ -149,7 +167,6 @@ LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
 #endif
     Archive::Child *ret = new Archive::Child(child);
 
-    ++rai->cur;
     return ret;
 }