Possibly fix MSVC compilation after r256054.
[oota-llvm.git] / lib / Object / Archive.cpp
index 1cc3c48c6c3c818d279a92f59f6b9614e02623b0..99b0650c8b7e26efc0d7bd832f1cdc4f42cb0250 100644 (file)
@@ -82,6 +82,10 @@ unsigned ArchiveMemberHeader::getGID() const {
   return Ret;
 }
 
+Archive::Child::Child(const Archive *Parent, StringRef Data,
+                      uint16_t StartOfFile)
+    : Parent(Parent), Data(Data), StartOfFile(StartOfFile) {}
+
 Archive::Child::Child(const Archive *Parent, const char *Start,
                       std::error_code *EC)
     : Parent(Parent) {
@@ -92,11 +96,8 @@ Archive::Child::Child(const Archive *Parent, const char *Start,
   Data = StringRef(Start, Size);
   if (!isThinMember()) {
     ErrorOr<uint64_t> MemberSize = getRawSize();
-    if (MemberSize.getError()) {
-      assert (EC && "Error must be caught");
-      *EC = MemberSize.getError();
+    if ((*EC = MemberSize.getError()))
       return;
-    }
     Size += MemberSize.get();
     Data = StringRef(Start, Size);
   }
@@ -107,24 +108,12 @@ Archive::Child::Child(const Archive *Parent, const char *Start,
   StringRef Name = getRawName();
   if (Name.startswith("#1/")) {
     uint64_t NameSize;
-    if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) {
-      if (EC)
-        *EC = object_error::parse_failed; // Long name offset is not an integer.
-      return;
-    }
+    if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize))
+      llvm_unreachable("Long name length is not an integer");
     StartOfFile += NameSize;
   }
 }
 
-ErrorOr<std::unique_ptr<Archive::Child>> Archive::Child::create(
-  const Archive *Parent, const char *Start) {
-  std::error_code EC;
-  std::unique_ptr<Archive::Child> Ret(new Archive::Child(Parent, Start, &EC));
-  if (EC)
-    return EC;
-  return std::move(Ret);
-}
-
 ErrorOr<uint64_t> Archive::Child::getSize() const {
   if (Parent->IsThin) {
     ErrorOr<uint32_t> Size = getHeader()->getSize();
@@ -170,25 +159,24 @@ ErrorOr<StringRef> Archive::Child::getBuffer() const {
 ErrorOr<Archive::Child> Archive::Child::getNext() const {
   size_t SpaceToSkip = Data.size();
   // If it's odd, add 1 to make it even.
-  size_t Pad = 0;
   if (SpaceToSkip & 1)
-    Pad++;
+    ++SpaceToSkip;
 
-  const char *NextLoc = Data.data() + SpaceToSkip + Pad;
+  const char *NextLoc = Data.data() + SpaceToSkip;
 
   // Check to see if this is at the end of the archive.
-  if (NextLoc == Parent->Data.getBufferEnd() ||
-      NextLoc == Parent->Data.getBufferEnd() - Pad )
+  if (NextLoc == Parent->Data.getBufferEnd())
     return Child(Parent, nullptr, nullptr);
 
   // Check to see if this is past the end of the archive.
   if (NextLoc > Parent->Data.getBufferEnd())
     return object_error::parse_failed;
 
-  auto ChildOrErr = Child::create(Parent, NextLoc);
-  if (std::error_code EC = ChildOrErr.getError())
+  std::error_code EC;
+  Child Ret(Parent, NextLoc, &EC);
+  if (EC)
     return EC;
-  return std::move(*ChildOrErr.get());
+  return Ret;
 }
 
 uint64_t Archive::Child::getChildOffset() const {
@@ -210,24 +198,12 @@ ErrorOr<StringRef> Archive::Child::getName() const {
     // Get the offset.
     std::size_t offset;
     if (name.substr(1).rtrim(" ").getAsInteger(10, offset))
-      return object_error::parse_failed; // Long name offset is not an integer.
-    // Check for bad stringtable iterator.
-    if (std::error_code EC = Parent->StringTable->getError())
-      return EC;
-    const char *addr = (*Parent->StringTable)->Data.begin()
-                       + sizeof(ArchiveMemberHeader)
-                       + offset;
+      llvm_unreachable("Long name offset is not an integer");
+
     // Verify it.
-    auto Size = (*Parent->StringTable)->getSize();
-    if (std::error_code EC = Size.getError())
-      return EC;
-    if (Parent->StringTable == Parent->child_end()
-        || addr < ((*Parent->StringTable)->Data.begin()
-                   + sizeof(ArchiveMemberHeader))
-        || addr > ((*Parent->StringTable)->Data.begin()
-                   + sizeof(ArchiveMemberHeader)
-                   + Size.get()))
+    if (offset >= Parent->StringTable.size())
       return object_error::parse_failed;
+    const char *addr = Parent->StringTable.begin() + offset;
 
     // GNU long file names end with a "/\n".
     if (Parent->kind() == K_GNU || Parent->kind() == K_MIPS64) {
@@ -238,7 +214,7 @@ ErrorOr<StringRef> Archive::Child::getName() const {
   } else if (name.startswith("#1/")) {
     uint64_t name_size;
     if (name.substr(3).rtrim(" ").getAsInteger(10, name_size))
-      return object_error::parse_failed; // Long name offset is not an integer.
+      llvm_unreachable("Long name length is not an ingeter");
     return Data.substr(sizeof(ArchiveMemberHeader), name_size)
         .rtrim(StringRef("\0", 1));
   }
@@ -276,9 +252,13 @@ ErrorOr<std::unique_ptr<Archive>> Archive::create(MemoryBufferRef Source) {
   return std::move(Ret);
 }
 
+void Archive::setFirstRegular(const Child &C) {
+  FirstRegularData = C.Data;
+  FirstRegularStartOfFile = C.StartOfFile;
+}
+
 Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
-    : Binary(Binary::ID_Archive, Source), SymbolTable(child_end()),
-      StringTable(child_end()), FirstRegular(child_end()) {
+    : Binary(Binary::ID_Archive, Source) {
   StringRef Buffer = Data.getBuffer();
   // Check for sufficient magic.
   if (Buffer.startswith(ThinMagic)) {
@@ -291,15 +271,26 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
   }
 
   // Get the special members.
-  child_iterator i = child_begin(false);
-  child_iterator e = child_end();
+  child_iterator I = child_begin(false);
+  if ((ec = I->getError()))
+    return;
+  child_iterator E = child_end();
 
-  if (!*i || i == e) {
-    ec = i->getError();
+  if (I == E) {
+    ec = std::error_code();
     return;
   }
+  const Child *C = &**I;
+
+  auto Increment = [&]() {
+    ++I;
+    if ((ec = I->getError()))
+      return true;
+    C = &**I;
+    return false;
+  };
 
-  StringRef Name = (*i)->getRawName();
+  StringRef Name = C->getRawName();
 
   // Below is the pattern that is used to figure out the archive format
   // GNU archive format
@@ -322,14 +313,13 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
 
   if (Name == "__.SYMDEF") {
     Format = K_BSD;
-    SymbolTable = i;
-    ++i;
-    if (!*i) {
-      ec = i->getError();
+    // We know that the symbol table is not an external file, so we just assert
+    // there is no error.
+    SymbolTable = *C->getBuffer();
+    if (Increment())
       return;
-    }
+    setFirstRegular(*C);
 
-    FirstRegular = i;
     ec = std::error_code();
     return;
   }
@@ -337,20 +327,19 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
   if (Name.startswith("#1/")) {
     Format = K_BSD;
     // We know this is BSD, so getName will work since there is no string table.
-    ErrorOr<StringRef> NameOrErr = (*i)->getName();
+    ErrorOr<StringRef> NameOrErr = C->getName();
     ec = NameOrErr.getError();
     if (ec)
       return;
     Name = NameOrErr.get();
     if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") {
-      SymbolTable = i;
-      ++i;
-      if (!*i) {
-        ec = i->getError();
+      // We know that the symbol table is not an external file, so we just
+      // assert there is no error.
+      SymbolTable = *C->getBuffer();
+      if (Increment())
         return;
-      }
     }
-    FirstRegular = i;
+    setFirstRegular(*C);
     return;
   }
 
@@ -361,34 +350,36 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
 
   bool has64SymTable = false;
   if (Name == "/" || Name == "/SYM64/") {
-    SymbolTable = i;
+    // We know that the symbol table is not an external file, so we just assert
+    // there is no error.
+    SymbolTable = *C->getBuffer();
     if (Name == "/SYM64/")
       has64SymTable = true;
 
-    ++i;
-    if (!*i || i == e) {
-      ec = i->getError();
+    if (Increment())
+      return;
+    if (I == E) {
+      ec = std::error_code();
       return;
     }
-    Name = (*i)->getRawName();
+    Name = C->getRawName();
   }
 
   if (Name == "//") {
     Format = has64SymTable ? K_MIPS64 : K_GNU;
-    StringTable = i;
-    ++i;
-    if (!*i) {
-      ec = i->getError();
+    // The string table is never an external member, so we just assert on the
+    // ErrorOr.
+    StringTable = *C->getBuffer();
+    if (Increment())
       return;
-    }
-    FirstRegular = i;
+    setFirstRegular(*C);
     ec = std::error_code();
     return;
   }
 
   if (Name[0] != '/') {
     Format = has64SymTable ? K_MIPS64 : K_GNU;
-    FirstRegular = i;
+    setFirstRegular(*C);
     ec = std::error_code();
     return;
   }
@@ -399,31 +390,30 @@ Archive::Archive(MemoryBufferRef Source, std::error_code &ec)
   }
 
   Format = K_COFF;
-  SymbolTable = i;
+  // We know that the symbol table is not an external file, so we just assert
+  // there is no error.
+  SymbolTable = *C->getBuffer();
 
-  ++i;
-  if (!*i) {
-    ec = i->getError();
+  if (Increment())
     return;
-  }
-  if (i == e) {
-    FirstRegular = i;
+
+  if (I == E) {
+    setFirstRegular(*C);
     ec = std::error_code();
     return;
   }
 
-  Name = (*i)->getRawName();
+  Name = C->getRawName();
 
   if (Name == "//") {
-    StringTable = i;
-    ++i;
-    if (!*i) {
-      ec = i->getError();
+    // The string table is never an external member, so we just assert on the
+    // ErrorOr.
+    StringTable = *C->getBuffer();
+    if (Increment())
       return;
-    }
   }
 
-  FirstRegular = i;
+  setFirstRegular(*C);
   ec = std::error_code();
 }
 
@@ -432,30 +422,25 @@ Archive::child_iterator Archive::child_begin(bool SkipInternal) const {
     return child_end();
 
   if (SkipInternal)
-    return FirstRegular;
+    return Child(this, FirstRegularData, FirstRegularStartOfFile);
 
   const char *Loc = Data.getBufferStart() + strlen(Magic);
-  auto ChildOrErr = Child::create(this, Loc);
-  if (std::error_code EC = ChildOrErr.getError())
+  std::error_code EC;
+  Child c(this, Loc, &EC);
+  if (EC)
     return child_iterator(EC);
-  Child c = *(ChildOrErr.get());
   return child_iterator(c);
 }
 
 Archive::child_iterator Archive::child_end() const {
-  // This with a second argument of nullptr can't return an Error.
-  auto ChildOrErr = Child::create(this, nullptr);
-  if (ChildOrErr.getError())
-    llvm_unreachable("Can't create Archive::child_end().");
-  Child c = *(ChildOrErr.get());
-  return child_iterator(c);
+  return Child(this, nullptr, nullptr);
 }
 
 StringRef Archive::Symbol::getName() const {
   return Parent->getSymbolTable().begin() + StringIndex;
 }
 
-ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {
+ErrorOr<Archive::Child> Archive::Symbol::getMember() const {
   const char *Buf = Parent->getSymbolTable().begin();
   const char *Offsets = Buf;
   if (Parent->kind() == K_MIPS64)
@@ -500,11 +485,11 @@ ErrorOr<Archive::child_iterator> Archive::Symbol::getMember() const {
   }
 
   const char *Loc = Parent->getData().begin() + Offset;
-  auto ChildOrErr = Child::create(Parent, Loc);
-  if (std::error_code EC = ChildOrErr.getError())
+  std::error_code EC;
+  Child C(Parent, Loc, &EC);
+  if (EC)
     return EC;
-  child_iterator Iter(std::move(*ChildOrErr.get()));
-  return Iter;
+  return C;
 }
 
 Archive::Symbol Archive::Symbol::getNext() const {
@@ -623,6 +608,4 @@ Archive::child_iterator Archive::findSym(StringRef name) const {
   return child_end();
 }
 
-bool Archive::hasSymbolTable() const {
-  return SymbolTable != child_end();
-}
+bool Archive::hasSymbolTable() const { return !SymbolTable.empty(); }