[lld] r223867 - Re-commit r223330: Rewrite InputGraph's Group

Rui Ueyama ruiu at google.com
Thu Dec 11 23:36:31 PST 2014


The change was one line.

  undefAdded = undefAdded || handleFile(*member);

was wrong because if undefAdded is true, handleFile() is not called. It
should've been this.

  undefAdded = handleFile(*member) || undefAdded;

A test that could have caught was not added yet. I'm writing one.

On Fri, Dec 12, 2014 at 2:28 PM, Shankar Easwaran <shankare at codeaurora.org>
wrote:

> Curious to figure out where the error was in the code that caused
> undefined symbols ?
>
> Was there a test added to check the failure which was not caught by any of
> the tests ?
>
> Shankar Easwaran
>
>
> On 12/9/2014 6:33 PM, Rui Ueyama wrote:
>
>> Author: ruiu
>> Date: Tue Dec  9 18:33:00 2014
>> New Revision: 223867
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=223867&view=rev
>> Log:
>> Re-commit r223330: Rewrite InputGraph's Group
>>
>> Modified:
>>      lld/trunk/include/lld/Core/InputGraph.h
>>      lld/trunk/include/lld/Core/LinkingContext.h
>>      lld/trunk/include/lld/Core/Resolver.h
>>      lld/trunk/include/lld/Driver/DarwinInputGraph.h
>>      lld/trunk/include/lld/Driver/WinLinkInputGraph.h
>>      lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>>      lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
>>      lld/trunk/lib/Core/InputGraph.cpp
>>      lld/trunk/lib/Core/Resolver.cpp
>>      lld/trunk/lib/Driver/DarwinInputGraph.cpp
>>      lld/trunk/lib/Driver/DarwinLdDriver.cpp
>>      lld/trunk/lib/Driver/Driver.cpp
>>      lld/trunk/lib/Driver/GnuLdDriver.cpp
>>      lld/trunk/lib/Driver/GnuLdInputGraph.cpp
>>      lld/trunk/lib/Driver/WinLinkDriver.cpp
>>      lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>>      lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
>>      lld/trunk/unittests/DriverTests/DriverTest.h
>>      lld/trunk/unittests/DriverTests/InputGraphTest.cpp
>>      lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
>>
>> Modified: lld/trunk/include/lld/Core/InputGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> Core/InputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/Core/InputGraph.h (original)
>> +++ lld/trunk/include/lld/Core/InputGraph.h Tue Dec  9 18:33:00 2014
>> @@ -59,12 +59,6 @@ public:
>>     /// assigned in the way files are resolved.
>>     virtual ErrorOr<File &> getNextFile();
>>   -  /// Notifies the current input element of Resolver made some
>> progress on
>> -  /// resolving undefined symbols using the current file. Group
>> (representing
>> -  /// --start-group and --end-group) uses that notification to make a
>> decision
>> -  /// whether it should iterate over again or terminate or not.
>> -  virtual void notifyProgress();
>> -
>>     /// Adds an observer of getNextFile(). Each time a new file is about
>> to be
>>     /// returned from getNextFile(), registered observers are called with
>> the file
>>     /// being returned.
>> @@ -76,14 +70,18 @@ public:
>>     /// \brief Adds a node at the beginning of the InputGraph
>>     void addInputElementFront(std::unique_ptr<InputElement>);
>>   -  /// Normalize the InputGraph. It calls expand() on each node and
>> then replace
>> -  /// it with getReplacements() results.
>> +  /// Normalize the InputGraph. It calls getReplacements() on each
>> element.
>>     void normalize();
>>   -  range<InputElementIterT> inputElements() {
>> -    return make_range(_inputArgs.begin(), _inputArgs.end());
>> +  InputElementVectorT &inputElements() {
>> +    return _inputArgs;
>>     }
>>   +  // Returns the current group size if we are at an --end-group.
>> +  // Otherwise returns 0.
>> +  int getGroupSize();
>> +  void skipGroup();
>> +
>>     // \brief Returns the number of input files.
>>     size_t size() const { return _inputArgs.size(); }
>>   @@ -108,8 +106,8 @@ class InputElement {
>>   public:
>>     /// Each input element in the graph can be a File or a control
>>     enum class Kind : uint8_t {
>> -    Group,      // Represents a type associated with Group
>> -    File        // Represents a type associated with File Nodes
>> +    File,       // Represents a type associated with File Nodes
>> +    GroupEnd,
>>     };
>>       InputElement(Kind type) : _kind(type) {}
>> @@ -129,16 +127,9 @@ public:
>>     /// Get the next file to be processed by the resolver
>>     virtual ErrorOr<File &> getNextFile() = 0;
>>   -  /// Refer InputGraph::notifyProgress(). By default, it does nothing.
>> Only
>> -  /// Group is interested in this message.
>> -  virtual void notifyProgress() {};
>> -
>>     /// \brief Reset the next index
>>     virtual void resetNextIndex() = 0;
>>   -  /// Returns true if we want to replace this node with children.
>> -  virtual void expand() {}
>> -
>>     /// Get the elements that we want to expand with.
>>     virtual bool getReplacements(InputGraph::InputElementVectorT &) {
>>       return false;
>> @@ -148,73 +139,31 @@ protected:
>>     Kind _kind; // The type of the Element
>>   };
>>   -/// \brief A Control node which contains a group of InputElements
>> -/// This affects the resolver so that it resolves undefined symbols
>> -/// in the group completely before looking at other input files that
>> -/// follow the group
>> -class Group : public InputElement {
>> +// This is a marker for --end-group. getSize() returns the number of
>> +// files between the corresponding --start-group and this marker.
>> +class GroupEnd : public InputElement {
>>   public:
>> -  Group()
>> -      : InputElement(InputElement::Kind::Group),
>> _currentElementIndex(0),
>> -        _nextElementIndex(0), _madeProgress(false) {}
>> +  GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}
>>   -  static inline bool classof(const InputElement *a) {
>> -    return a->kind() == InputElement::Kind::Group;
>> -  }
>> -
>> -  /// \brief Process input element and add it to the group
>> -  bool addFile(std::unique_ptr<InputElement> element) {
>> -    _elements.push_back(std::move(element));
>> -    return true;
>> -  }
>> +  int getSize() const { return _size; }
>>   -  range<InputGraph::InputElementIterT> elements() {
>> -    return make_range(_elements.begin(), _elements.end());
>> -  }
>> -
>> -  void resetNextIndex() override {
>> -    _madeProgress = false;
>> -    _currentElementIndex = 0;
>> -    _nextElementIndex = 0;
>> -    for (std::unique_ptr<InputElement> &elem : _elements)
>> -      elem->resetNextIndex();
>> +  static inline bool classof(const InputElement *a) {
>> +    return a->kind() == Kind::GroupEnd;
>>     }
>>       /// \brief Parse the group members.
>>     std::error_code parse(const LinkingContext &ctx, raw_ostream &diag)
>> override {
>> -    for (std::unique_ptr<InputElement> &ei : _elements)
>> -      if (std::error_code ec = ei->parse(ctx, diag))
>> -        return ec;
>>       return std::error_code();
>>     }
>>   -  /// If Resolver made a progress using the current file, it's ok to
>> revisit
>> -  /// files in this group in future.
>> -  void notifyProgress() override {
>> -    for (std::unique_ptr<InputElement> &elem : _elements)
>> -      elem->notifyProgress();
>> -    _madeProgress = true;
>> -  }
>> -
>> -  ErrorOr<File &> getNextFile() override;
>> -
>> -  void expand() override {
>> -    for (std::unique_ptr<InputElement> &elt : _elements)
>> -      elt->expand();
>> -    std::vector<std::unique_ptr<InputElement>> result;
>> -    for (std::unique_ptr<InputElement> &elt : _elements) {
>> -      if (elt->getReplacements(result))
>> -        continue;
>> -      result.push_back(std::move(elt));
>> -    }
>> -    _elements.swap(result);
>> +  ErrorOr<File &> getNextFile() override {
>> +    llvm_unreachable("shouldn't be here.");
>>     }
>>   -protected:
>> -  InputGraph::InputElementVectorT _elements;
>> -  uint32_t _currentElementIndex;
>> -  uint32_t _nextElementIndex;
>> -  bool _madeProgress;
>> +  void resetNextIndex() override {}
>> +
>> +private:
>> +  int _size;
>>   };
>>     /// \brief Represents an Input file in the graph
>> @@ -252,6 +201,8 @@ public:
>>       /// \brief add a file to the list of files
>>     virtual void addFiles(InputGraph::FileVectorT files) {
>> +    assert(files.size() == 1);
>> +    assert(_files.empty());
>>       for (std::unique_ptr<File> &ai : files)
>>         _files.push_back(std::move(ai));
>>     }
>> @@ -260,6 +211,8 @@ public:
>>     /// the node again.
>>     void resetNextIndex() override { _nextFileIndex = 0; }
>>   +  bool getReplacements(InputGraph::InputElementVectorT &result)
>> override;
>> +
>>   protected:
>>     /// \brief Read the file into _buffer.
>>     std::error_code getBuffer(StringRef filePath);
>> @@ -276,6 +229,10 @@ protected:
>>   class SimpleFileNode : public FileNode {
>>   public:
>>     SimpleFileNode(StringRef path) : FileNode(path) {}
>> +  SimpleFileNode(StringRef path, std::unique_ptr<File> f)
>> +      : FileNode(path) {
>> +    _files.push_back(std::move(f));
>> +  }
>>       virtual ~SimpleFileNode() {}
>>
>> Modified: lld/trunk/include/lld/Core/LinkingContext.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> Core/LinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/Core/LinkingContext.h (original)
>> +++ lld/trunk/include/lld/Core/LinkingContext.h Tue Dec  9 18:33:00 2014
>> @@ -322,6 +322,10 @@ public:
>>     bool runRoundTripPass() const { return _runRoundTripPasses; }
>>   #endif
>>   +  // This function is called just before the Resolver kicks in.
>> +  // Derived classes may use that chance to rearrange the input files.
>> +  virtual void maybeSortInputFiles() {}
>> +
>>     /// @}
>>   protected:
>>     LinkingContext(); // Must be subclassed
>>
>> Modified: lld/trunk/include/lld/Core/Resolver.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> Core/Resolver.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/Core/Resolver.h (original)
>> +++ lld/trunk/include/lld/Core/Resolver.h Tue Dec  9 18:33:00 2014
>> @@ -28,7 +28,8 @@ class LinkingContext;
>>   class Resolver {
>>   public:
>>     Resolver(LinkingContext &context)
>> -      : _context(context), _symbolTable(context), _result(new
>> MergedFile()) {}
>> +      : _context(context), _symbolTable(context), _result(new
>> MergedFile()),
>> +        _fileIndex(0) {}
>>       // InputFiles::Handler methods
>>     void doDefinedAtom(const DefinedAtom&);
>> @@ -38,10 +39,10 @@ public:
>>       // Handle files, this adds atoms from the current file thats
>>     // being processed by the resolver
>> -  void handleFile(const File &);
>> +  bool handleFile(const File &);
>>       // Handle an archive library file.
>> -  void handleArchiveFile(const File &);
>> +  bool handleArchiveFile(const File &);
>>       // Handle a shared library file.
>>     void handleSharedLibrary(const File &);
>> @@ -54,6 +55,9 @@ public:
>>   private:
>>     typedef std::function<void(StringRef, bool)> UndefCallback;
>>   +  bool undefinesAdded(int count);
>> +  ErrorOr<File &> nextFile(bool &inGroup);
>> +
>>     /// \brief Add section group/.gnu.linkonce if it does not exist
>> previously.
>>     void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);
>>   @@ -110,6 +114,11 @@ private:
>>     llvm::DenseSet<const Atom *>  _deadAtoms;
>>     std::unique_ptr<MergedFile>   _result;
>>     llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>>
>> _reverseRef;
>> +
>> +  // --start-group and --end-group
>> +  std::vector<File *> _files;
>> +  std::map<File *, bool> _newUndefinesAdded;
>> +  size_t _fileIndex;
>>   };
>>     } // namespace lld
>>
>> Modified: lld/trunk/include/lld/Driver/DarwinInputGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> Driver/DarwinInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/Driver/DarwinInputGraph.h (original)
>> +++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Tue Dec  9 18:33:00
>> 2014
>> @@ -23,18 +23,6 @@
>>     namespace lld {
>>   -
>> -class DarwinInputGraph : public InputGraph {
>> -public:
>> -  DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) {
>> }
>> -  ErrorOr<File &> getNextFile() override;
>> -  void notifyProgress() override;
>> -private:
>> -  bool _librariesPhase;
>> -  bool _repeatLibraries;
>> -};
>> -
>> -
>>   /// \brief Represents a MachO File
>>   class MachOFileNode : public FileNode {
>>   public:
>>
>> Modified: lld/trunk/include/lld/Driver/WinLinkInputGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> Driver/WinLinkInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (original)
>> +++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Tue Dec  9 18:33:00
>> 2014
>> @@ -55,21 +55,6 @@ public:
>>     ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
>>   };
>>   -/// \brief Represents a ELF control node
>> -class PECOFFGroup : public Group {
>> -public:
>> -  PECOFFGroup(PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}
>> -
>> -  /// \brief Parse the group members.
>> -  std::error_code parse(const LinkingContext &ctx, raw_ostream &diag)
>> override {
>> -    std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
>> -    return Group::parse(ctx, diag);
>> -  }
>> -
>> -private:
>> -  PECOFFLinkingContext &_ctx;
>> -};
>> -
>>   } // namespace lld
>>     #endif
>>
>> Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> ReaderWriter/MachOLinkingContext.h?rev=223867&r1=223866&r2=223867&
>> view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
>> +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Dec  9
>> 18:33:00 2014
>> @@ -283,6 +283,8 @@ public:
>>     /// bits are xxxx.yy.zz.  Largest number is 65535.255.255
>>     static bool parsePackedVersion(StringRef str, uint32_t &result);
>>   +  void maybeSortInputFiles() override;
>> +
>>   private:
>>     Writer &writer() const override;
>>     mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
>>
>> Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/
>> ReaderWriter/PECOFFLinkingContext.h?rev=223867&r1=223866&r2=223867&
>> view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
>> +++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Tue Dec  9
>> 18:33:00 2014
>> @@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;
>>   static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
>>     namespace lld {
>> -class Group;
>>     class PECOFFLinkingContext : public LinkingContext {
>>   public:
>> @@ -318,8 +317,7 @@ public:
>>     void setEntryNode(SimpleFileNode *node) { _entryNode = node; }
>>     SimpleFileNode *getEntryNode() const { return _entryNode; }
>>   -  void setLibraryGroup(Group *group) { _libraryGroup = group; }
>> -  Group *getLibraryGroup() const { return _libraryGroup; }
>> +  void addLibraryFile(std::unique_ptr<FileNode> file);
>>       void setModuleDefinitionFile(const std::string val) {
>>       _moduleDefinitionFile = val;
>> @@ -441,9 +439,6 @@ private:
>>     // The node containing the entry point file.
>>     SimpleFileNode *_entryNode;
>>   -  // The PECOFFGroup that contains all the .lib files.
>> -  Group *_libraryGroup;
>> -
>>     // Name of the temporary file for lib.exe subcommand. For debugging
>>     // only.
>>     std::string _moduleDefinitionFile;
>>
>> Modified: lld/trunk/lib/Core/InputGraph.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/
>> InputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Core/InputGraph.cpp (original)
>> +++ lld/trunk/lib/Core/InputGraph.cpp Tue Dec  9 18:33:00 2014
>> @@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(
>>     }
>>   }
>>   -void InputGraph::notifyProgress() { _currentInputElement->notifyProgress();
>> }
>> -
>>   void InputGraph::registerObserver(std::function<void(File *)> fn) {
>>     _observers.push_back(fn);
>>   }
>> @@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn
>>   ErrorOr<InputElement *> InputGraph::getNextInputElement() {
>>     if (_nextElementIndex >= _inputArgs.size())
>>       return make_error_code(InputGraphError::no_more_elements);
>> -  return _inputArgs[_nextElementIndex++].get();
>> +  InputElement *elem = _inputArgs[_nextElementIndex++].get();
>> +  if (isa<GroupEnd>(elem))
>> +    return getNextInputElement();
>> +  return elem;
>>   }
>>     void InputGraph::normalize() {
>> -  for (std::unique_ptr<InputElement> &elt : _inputArgs)
>> -    elt->expand();
>>     std::vector<std::unique_ptr<InputElement>> vec;
>>     for (std::unique_ptr<InputElement> &elt : _inputArgs) {
>>       if (elt->getReplacements(vec))
>> @@ -76,6 +75,25 @@ void InputGraph::normalize() {
>>     _inputArgs = std::move(vec);
>>   }
>>   +// If we are at the end of a group, return its size (which indicates
>> +// how many files we need to go back in the command line).
>> +// Returns 0 if we are not at the end of a group.
>> +int InputGraph::getGroupSize() {
>> +  if (_nextElementIndex >= _inputArgs.size())
>> +    return 0;
>> +  InputElement *elem = _inputArgs[_nextElementIndex].get();
>> +  if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
>> +    return group->getSize();
>> +  return 0;
>> +}
>> +
>> +void InputGraph::skipGroup() {
>> +  if (_nextElementIndex >= _inputArgs.size())
>> +    return;
>> +  if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))
>> +    _nextElementIndex++;
>> +}
>> +
>>   /// \brief Read the file into _buffer.
>>   std::error_code FileNode::getBuffer(StringRef filePath) {
>>     // Create a memory buffer
>> @@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri
>>     return std::error_code();
>>   }
>>   -/// \brief Return the next file that need to be processed by the
>> resolver.
>> -/// This also processes input elements depending on the resolve status
>> -/// of the input elements contained in the group.
>> -ErrorOr<File &> Group::getNextFile() {
>> -  // If there are no elements, move on to the next input element
>> -  if (_elements.empty())
>> -    return make_error_code(InputGraphError::no_more_files);
>> -
>> -  for (;;) {
>> -    // If we have processed all the elements, and have made no progress
>> on
>> -    // linking, we cannot resolve any symbol from this group. Continue
>> to the
>> -    // next one by returning no_more_files.
>> -    if (_nextElementIndex == _elements.size()) {
>> -      if (!_madeProgress)
>> -        return make_error_code(InputGraphError::no_more_files);
>> -      resetNextIndex();
>> -    }
>> -
>> -    _currentElementIndex = _nextElementIndex;
>> -    auto file = _elements[_nextElementIndex]->getNextFile();
>> -    // Move on to the next element if we have finished processing all
>> -    // the files in the input element
>> -    if (file.getError() == InputGraphError::no_more_files) {
>> -      _nextElementIndex++;
>> -      continue;
>> -    }
>> -    return *file;
>> -  }
>> +bool FileNode::getReplacements(InputGraph::InputElementVectorT &result)
>> {
>> +  if (_files.size() < 2)
>> +    return false;
>> +  for (std::unique_ptr<File> &file : _files)
>> +    result.push_back(llvm::make_unique<SimpleFileNode>(_path,
>> std::move(file)));
>> +  return true;
>>   }
>>
>> Modified: lld/trunk/lib/Core/Resolver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/
>> Resolver.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Core/Resolver.cpp (original)
>> +++ lld/trunk/lib/Core/Resolver.cpp Tue Dec  9 18:33:00 2014
>> @@ -27,7 +27,7 @@
>>     namespace lld {
>>   -void Resolver::handleFile(const File &file) {
>> +bool Resolver::handleFile(const File &file) {
>>     bool undefAdded = false;
>>     for (const DefinedAtom *atom : file.defined())
>>       doDefinedAtom(*atom);
>> @@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi
>>       doSharedLibraryAtom(*atom);
>>     for (const AbsoluteAtom *atom : file.absolute())
>>       doAbsoluteAtom(*atom);
>> -
>> -  // Notify the input file manager of the fact that we have made some
>> progress
>> -  // on linking using the current input file. It may want to know the
>> fact for
>> -  // --start-group/--end-group.
>> -  if (undefAdded) {
>> -    _context.getInputGraph().notifyProgress();
>> -  }
>> +  return undefAdded;
>>   }
>>     void Resolver::forEachUndefines(bool searchForOverrides,
>> @@ -76,17 +70,19 @@ void Resolver::forEachUndefines(bool sea
>>     } while (undefineGenCount != _symbolTable.size());
>>   }
>>   -void Resolver::handleArchiveFile(const File &file) {
>> +bool Resolver::handleArchiveFile(const File &file) {
>>     const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&
>> file);
>>     bool searchForOverrides =
>>         _context.searchArchivesToOverrideTentativeDefinitions();
>> +  bool undefAdded = false;
>>     forEachUndefines(searchForOverrides,
>>                      [&](StringRef undefName, bool dataSymbolOnly) {
>>       if (const File *member = archiveFile->find(undefName,
>> dataSymbolOnly)) {
>>         member->setOrdinal(_context.getNextOrdinalAndIncrement());
>> -      handleFile(*member);
>> +      undefAdded = handleFile(*member) || undefAdded;
>>       }
>>     });
>> +  return undefAdded;
>>   }
>>     void Resolver::handleSharedLibrary(const File &file) {
>> @@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto
>>       doDefinedAtom(*newAtom);
>>   }
>>   +// Returns true if at least one of N previous files has created an
>> +// undefined symbol.
>> +bool Resolver::undefinesAdded(int n) {
>> +  for (size_t i = _fileIndex - n; i < _fileIndex; ++i)
>> +    if (_newUndefinesAdded[_files[i]])
>> +      return true;
>> +  return false;
>> +}
>> +
>> +ErrorOr<File &> Resolver::nextFile(bool &inGroup) {
>> +  if (size_t groupSize = _context.getInputGraph().getGroupSize()) {
>> +    // We are at the end of the current group. If one or more new
>> +    // undefined atom has been added in the last groupSize files, we
>> +    // reiterate over the files.
>> +    if (undefinesAdded(groupSize))
>> +      _fileIndex -= groupSize;
>> +    _context.getInputGraph().skipGroup();
>> +    return nextFile(inGroup);
>> +  }
>> +  if (_fileIndex < _files.size()) {
>> +    // We are still in the current group.
>> +    inGroup = true;
>> +    return *_files[_fileIndex++];
>> +  }
>> +  // We are not in a group. Get a new file.
>> +  ErrorOr<File &> file = _context.getInputGraph().getNextFile();
>> +  if (std::error_code ec = file.getError()) {
>> +    if (ec != InputGraphError::no_more_files)
>> +      llvm::errs() << "Error occurred in getNextFile: " << ec.message()
>> << "\n";
>> +    return ec;
>> +  }
>> +  _files.push_back(&*file);
>> +  ++_fileIndex;
>> +  inGroup = false;
>> +  return *file;
>> +}
>> +
>>   // Keep adding atoms until _context.getNextFile() returns an error. This
>>   // function is where undefined atoms are resolved.
>>   bool Resolver::resolveUndefines() {
>>     ScopedTask task(getDefaultDomain(), "resolveUndefines");
>>       for (;;) {
>> -    ErrorOr<File &> file = _context.getInputGraph().getNextFile();
>> -    std::error_code ec = file.getError();
>> -    if (ec == InputGraphError::no_more_files)
>> -      return true;
>> -    if (!file) {
>> -      llvm::errs() << "Error occurred in getNextFile: " << ec.message()
>> << "\n";
>> -      return false;
>> -    }
>> -
>> +    bool inGroup = false;
>> +    bool undefAdded = false;
>> +    ErrorOr<File &> file = nextFile(inGroup);
>> +    if (std::error_code ec = file.getError())
>> +      return ec == InputGraphError::no_more_files;
>>       switch (file->kind()) {
>>       case File::kindObject:
>> +      if (inGroup)
>> +        break;
>>         assert(!file->hasOrdinal());
>>         file->setOrdinal(_context.getNextOrdinalAndIncrement());
>> -      handleFile(*file);
>> +      undefAdded = handleFile(*file);
>>         break;
>>       case File::kindArchiveLibrary:
>>         if (!file->hasOrdinal())
>>           file->setOrdinal(_context.getNextOrdinalAndIncrement());
>> -      handleArchiveFile(*file);
>> +      undefAdded = handleArchiveFile(*file);
>>         break;
>>       case File::kindSharedLibrary:
>>         if (!file->hasOrdinal())
>> @@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {
>>         handleSharedLibrary(*file);
>>         break;
>>       }
>> +    _newUndefinesAdded[&*file] = undefAdded;
>>     }
>>   }
>>
>> Modified: lld/trunk/lib/Driver/DarwinInputGraph.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> DarwinInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)
>> +++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Tue Dec  9 18:33:00 2014
>> @@ -18,48 +18,6 @@
>>   namespace lld {
>>     -ErrorOr<File &> DarwinInputGraph::getNextFile() {
>> -  // The darwin linker processes input files in two phases.  The first
>> phase
>> -  // links in all object (.o) files in command line order. The second
>> phase
>> -  // links in libraries in command line order. If there are still
>> UndefinedAtoms
>> -  // the second phase is repeated until notifyProgress() is not called by
>> -  // resolver.
>> -  for (;;) {
>> -    if (_currentInputElement) {
>> -      for(;;) {
>> -        ErrorOr<File &> next = _currentInputElement->getNextFile();
>> -        if (next.getError())
>> -          break;
>> -        File *file = &next.get();
>> -        bool fileIsLibrary = isa<SharedLibraryFile>(file) ||
>> -                             isa<ArchiveLibraryFile>(file);
>> -        if (fileIsLibrary == _librariesPhase) {
>> -          // Return library in library phase and object files in non-lib
>> mode.
>> -          return *file;
>> -        }
>> -      }
>> -    }
>> -
>> -    if (_nextElementIndex >= _inputArgs.size()) {
>> -      // If no more elements, done unless we need to repeat library scan.
>> -      if (_librariesPhase && !_repeatLibraries)
>> -        return make_error_code(InputGraphError::no_more_files);
>> -      // Clear iterations and only look for libraries.
>> -      _librariesPhase = true;
>> -      _repeatLibraries = false;
>> -      _nextElementIndex = 0;
>> -      for (auto &ie : _inputArgs) {
>> -        ie->resetNextIndex();
>> -      }
>> -    }
>> -    _currentInputElement = _inputArgs[_nextElementIndex++].get();
>> -  }
>> -}
>> -
>> -void DarwinInputGraph::notifyProgress() {
>> -  _repeatLibraries = true;
>> -}
>> -
>>   /// \brief Parse the input file to lld::File.
>>   std::error_code MachOFileNode::parse(const LinkingContext &ctx,
>>                                        raw_ostream &diagnostics)  {
>>
>> Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> DarwinLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
>> +++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Tue Dec  9 18:33:00 2014
>> @@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri
>>     }
>>   }
>>   -static void addFile(StringRef path, std::unique_ptr<DarwinInputGraph>
>> &inputGraph,
>> +static void addFile(StringRef path, std::unique_ptr<InputGraph>
>> &inputGraph,
>>                       MachOLinkingContext &ctx, bool loadWholeArchive,
>>                       bool upwardDylib) {
>>     auto node = llvm::make_unique<MachOFileNode>(path, ctx);
>> @@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St
>>   // per line. The <dir> prefix is prepended to each partial path.
>>   //
>>   static std::error_code parseFileList(StringRef fileListPath,
>> -                                     std::unique_ptr<DarwinInputGraph>
>> &inputGraph,
>> +                                     std::unique_ptr<InputGraph>
>> &inputGraph,
>>                                        MachOLinkingContext &ctx, bool
>> forceLoad,
>>                                        raw_ostream &diagnostics) {
>>     // If there is a comma, split off <dir>.
>> @@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con
>>       }
>>     }
>>   -  std::unique_ptr<DarwinInputGraph> inputGraph(new
>> DarwinInputGraph());
>> +  std::unique_ptr<InputGraph> inputGraph(new InputGraph());
>>       // Now construct the set of library search directories, following
>> ld64's
>>     // baroque set of accumulated hacks. Mostly, the algorithm constructs
>>
>> Modified: lld/trunk/lib/Driver/Driver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> Driver.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/Driver.cpp (original)
>> +++ lld/trunk/lib/Driver/Driver.cpp Tue Dec  9 18:33:00 2014
>> @@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex
>>         if (std::error_code ec = ie->parse(context, stream)) {
>>           if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))
>>             stream << fileNode->errStr(ec) << "\n";
>> -        else if (dyn_cast<Group>(ie.get()))
>> -          // FIXME: We need a better diagnostics here
>> -          stream << "Cannot parse group input element\n";
>>           else
>>             llvm_unreachable("Unknown type of input element");
>>           fail = true;
>> @@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex
>>     if (fail)
>>       return false;
>>   -  std::unique_ptr<SimpleFileNode> fileNode(
>> -      new SimpleFileNode("Internal Files"));
>> -
>>     InputGraph::FileVectorT internalFiles;
>>     context.createInternalFiles(internalFiles);
>> -
>> -  if (internalFiles.size())
>> -    fileNode->addFiles(std::move(internalFiles));
>> +  for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i !=
>> e; ++i) {
>> +    context.getInputGraph().addInputElementFront(
>> +        llvm::make_unique<SimpleFileNode>("internal", std::move(*i)));
>> +  }
>>       // Give target a chance to add files.
>>     InputGraph::FileVectorT implicitFiles;
>>     context.createImplicitFiles(implicitFiles);
>> -  if (implicitFiles.size())
>> -    fileNode->addFiles(std::move(implicitFiles));
>> -  context.getInputGraph().addInputElementFront(std::move(fileNode));
>> +  for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i !=
>> e; ++i) {
>> +    context.getInputGraph().addInputElementFront(
>> +        llvm::make_unique<SimpleFileNode>("implicit", std::move(*i)));
>> +  }
>> +
>> +  // Give target a chance to sort the input files.
>> +  // Mach-O uses this chance to move all object files before library
>> files.
>> +  context.maybeSortInputFiles();
>>       // Do core linking.
>>     ScopedTask resolveTask(getDefaultDomain(), "Resolve");
>>
>> Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> GnuLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
>> +++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Dec  9 18:33:00 2014
>> @@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const
>>     }
>>       std::unique_ptr<InputGraph> inputGraph(new InputGraph());
>> -  std::stack<Group *> groupStack;
>> +  std::stack<int> groupStack;
>> +  int numfiles = 0;
>>       ELFFileNode::Attributes attributes;
>>   @@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const
>>         break;
>>       }
>>   -    case OPT_start_group: {
>> -      std::unique_ptr<Group> group(new Group());
>> -      groupStack.push(group.get());
>> -      inputGraph->addInputElement(std::move(group));
>> +    case OPT_start_group:
>> +      groupStack.push(numfiles);
>>         break;
>> -    }
>>   -    case OPT_end_group:
>> +    case OPT_end_group: {
>> +      if (groupStack.empty()) {
>> +        diagnostics << "stray --end-group\n";
>> +        return false;
>> +      }
>> +      int startGroupPos = groupStack.top();
>> +      inputGraph->addInputElement(
>> +          llvm::make_unique<GroupEnd>(numfiles - startGroupPos));
>>         groupStack.pop();
>>         break;
>> +    }
>>         case OPT_z: {
>>         StringRef extOpt = inputArg->getValue();
>> @@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const
>>           }
>>         }
>>         std::unique_ptr<InputElement> inputFile(inputNode);
>> -      if (groupStack.empty()) {
>> -        inputGraph->addInputElement(std::move(inputFile));
>> -      } else {
>> -        groupStack.top()->addFile(std::move(inputFile));
>> -      }
>> +      ++numfiles;
>> +      inputGraph->addInputElement(std::move(inputFile));
>>         break;
>>       }
>>
>> Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> GnuLdInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
>> +++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Tue Dec  9 18:33:00 2014
>> @@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co
>>       auto *group = dyn_cast<script::Group>(c);
>>       if (!group)
>>         continue;
>> -    std::unique_ptr<Group> groupStart(new Group());
>> +    size_t numfiles = 0;
>>       for (const script::Path &path : group->getPaths()) {
>>         // TODO : Propagate Set WholeArchive/dashlPrefix
>>         attributes.setAsNeeded(path._asNeeded);
>> @@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co
>>             _elfLinkingContext, _elfLinkingContext.
>> allocateString(path._path),
>>             attributes);
>>         std::unique_ptr<InputElement> inputFile(inputNode);
>> -      groupStart.get()->addFile(std::move(inputFile));
>> +      _expandElements.push_back(std::move(inputFile));
>> +      ++numfiles;
>>       }
>> -    _expandElements.push_back(std::move(groupStart));
>> +    _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));
>>     }
>>     return std::error_code();
>>   }
>>
>> Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/
>> WinLinkDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
>> +++ lld/trunk/lib/Driver/WinLinkDriver.cpp Tue Dec  9 18:33:00 2014
>> @@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki
>>     ErrorOr<StringRef> path = fileNode->getPath(ctx);
>>     if (!path)
>>       return false;
>> -  for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()->
>> elements())
>> +  for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().
>> inputElements())
>>       if (auto *f = dyn_cast<FileNode>(p.get()))
>>         if (*path == *f->getPath(ctx))
>>           return true;
>> @@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons
>>       ctx.setEntryNode(entry.get());
>>       ctx.getInputGraph().addInputElement(std::move(entry));
>>   -    // The container for all library files.
>> -    std::unique_ptr<Group> group(new PECOFFGroup(ctx));
>> -    ctx.setLibraryGroup(group.get());
>> -    ctx.getInputGraph().addInputElement(std::move(group));
>> +    // Add a group-end marker.
>> +    ctx.getInputGraph().addInputElement(llvm::make_unique<GroupEnd>(0));
>>     }
>>       // Add the library files to the library group.
>> @@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons
>>         if (isReadingDirectiveSection)
>>           if (lib->parse(ctx, diag))
>>             return false;
>> -      ctx.getLibraryGroup()->addFile(std::move(lib));
>> +      ctx.addLibraryFile(std::move(lib));
>>       }
>>     }
>>
>> Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/
>> ReaderWriter/MachO/MachOLinkingContext.cpp?rev=
>> 223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
>> +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Dec  9
>> 18:33:00 2014
>> @@ -22,6 +22,7 @@
>>   #include "llvm/ADT/Triple.h"
>>   #include "llvm/Config/config.h"
>>   #include "llvm/Support/Errc.h"
>> +#include "llvm/Support/Debug.h"
>>   #include "llvm/Support/Host.h"
>>   #include "llvm/Support/MachO.h"
>>   #include "llvm/Support/Path.h"
>> @@ -923,4 +924,35 @@ bool MachOLinkingContext::customAtomOrde
>>     return true;
>>   }
>>   +static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {
>> +  FileNode *e = dyn_cast<FileNode>(const_cast<InputElement
>> *>(elem.get()));
>> +  if (!e || e->files().empty())
>> +    return nullptr;
>> +  return e->files()[0].get();
>> +}
>> +
>> +static bool isLibrary(const std::unique_ptr<InputElement> &elem) {
>> +  File *f = getFirstFile(elem);
>> +  return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));
>> +}
>> +
>> +// The darwin linker processes input files in two phases.  The first
>> phase
>> +// links in all object (.o) files in command line order. The second phase
>> +// links in libraries in command line order.
>> +// In this function we reorder the input files so that all the object
>> files
>> +// comes before any library file. We also make a group for the library
>> files
>> +// so that the Resolver will reiterate over the libraries as long as we
>> find
>> +// new undefines from libraries.
>> +void MachOLinkingContext::maybeSortInputFiles() {
>> +  std::vector<std::unique_ptr<InputElement>> &elements
>> +      = getInputGraph().inputElements();
>> +  std::stable_sort(elements.begin(), elements.end(),
>> +                   [](const std::unique_ptr<InputElement> &a,
>> +                      const std::unique_ptr<InputElement> &b) {
>> +                     return !isLibrary(a) && isLibrary(b);
>> +                   });
>> +  size_t numLibs = std::count_if(elements.begin(), elements.end(),
>> isLibrary);
>> +  elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
>> +}
>> +
>>   } // end namespace lld
>>
>> Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/
>> ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=
>> 223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
>> +++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Tue Dec
>> 9 18:33:00 2014
>> @@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte
>>         "<command line option /include>");
>>   }
>>   +void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode>
>> file) {
>> +  GroupEnd *currentGroupEnd;
>> +  int pos = -1;
>> +  std::vector<std::unique_ptr<InputElement>> &elements
>> +      = getInputGraph().inputElements();
>> +  for (int i = 0, e = elements.size(); i < e; ++i) {
>> +    if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i].get()))) {
>> +      pos = i;
>> +      break;
>> +    }
>> +  }
>> +  assert(pos >= 0);
>> +  elements.insert(elements.begin() + pos, std::move(file));
>> +  elements[pos + 1] = llvm::make_unique<GroupEnd>(
>> +      currentGroupEnd->getSize() + 1);
>> +}
>> +
>>   bool PECOFFLinkingContext::createImplicitFiles(
>>       std::vector<std::unique_ptr<File>> &) {
>>     // Create a file for __ImageBase.
>> @@ -109,7 +126,7 @@ bool PECOFFLinkingContext::createImplici
>>     auto exportNode = llvm::make_unique<SimpleFileNode>("<export>");
>>     exportNode->appendInputFile(
>>         llvm::make_unique<pecoff::ExportedSymbolRenameFile>(*this,
>> syms));
>> -  getLibraryGroup()->addFile(std::move(exportNode));
>> +  addLibraryFile(std::move(exportNode));
>>       // Create a file for the entry point function.
>>     getEntryNode()->appendInputFile(
>>
>> Modified: lld/trunk/unittests/DriverTests/DriverTest.h
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/
>> DriverTests/DriverTest.h?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/unittests/DriverTests/DriverTest.h (original)
>> +++ lld/trunk/unittests/DriverTests/DriverTest.h Tue Dec  9 18:33:00 2014
>> @@ -37,18 +37,6 @@ protected:
>>       llvm_unreachable("not handling other types of input files");
>>     }
>>   -  // Convenience method for getting i'th input files name.
>> -  std::string inputFile(int index1, int index2) {
>> -    Group *group = dyn_cast<Group>(
>> -        linkingContext()->getInputGraph().inputElements(
>> )[index1].get());
>> -    if (!group)
>> -      llvm_unreachable("not handling other types of input files");
>> -    FileNode *file = dyn_cast<FileNode>(group->
>> elements()[index2].get());
>> -    if (!file)
>> -      llvm_unreachable("not handling other types of input files");
>> -    return *file->getPath(*linkingContext());
>> -  }
>> -
>>     // For unit tests to call driver with various command lines.
>>     bool parse(const char *args, ...) {
>>       // Construct command line options from varargs.
>>
>> Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/
>> DriverTests/InputGraphTest.cpp?rev=223867&r1=223866&r2=223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
>> +++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Tue Dec  9
>> 18:33:00 2014
>> @@ -77,7 +77,7 @@ protected:
>>     } // end anonymous namespace
>>   -static std::unique_ptr<TestFileNode> createFile1(StringRef name) {
>> +static std::unique_ptr<TestFileNode> createFile(StringRef name) {
>>     std::vector<std::unique_ptr<File>> files;
>>     files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));
>>     std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
>> @@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre
>>     return file;
>>   }
>>   -static std::unique_ptr<TestFileNode> createFile2(StringRef name1,
>> -                                                 StringRef name2) {
>> -  std::vector<std::unique_ptr<File>> files;
>> -  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name1)));
>> -  files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name2)));
>> -  std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
>> -  file->addFiles(std::move(files));
>> -  return file;
>> -}
>> -
>>   TEST_F(InputGraphTest, Empty) {
>>     expectEnd();
>>   }
>>     TEST_F(InputGraphTest, File) {
>> -  _graph->addInputElement(createFile1("file1"));
>> -  EXPECT_EQ("file1", getNext());
>> -  expectEnd();
>> -}
>> -
>> -TEST_F(InputGraphTest, Files) {
>> -  _graph->addInputElement(createFile2("file1", "file2"));
>> -  EXPECT_EQ("file1", getNext());
>> -  EXPECT_EQ("file2", getNext());
>> -  expectEnd();
>> -}
>> -
>> -TEST_F(InputGraphTest, Group) {
>> -  _graph->addInputElement(createFile2("file1", "file2"));
>> -
>> -  std::unique_ptr<Group> group(new Group());
>> -  group->addFile(createFile2("file3", "file4"));
>> -  group->addFile(createFile1("file5"));
>> -  group->addFile(createFile1("file6"));
>> -  _graph->addInputElement(std::move(group));
>> -
>> +  _graph->addInputElement(createFile("file1"));
>>     EXPECT_EQ("file1", getNext());
>> -  EXPECT_EQ("file2", getNext());
>> -  EXPECT_EQ("file3", getNext());
>> -  EXPECT_EQ("file4", getNext());
>> -  EXPECT_EQ("file5", getNext());
>> -  EXPECT_EQ("file6", getNext());
>> -  expectEnd();
>> -}
>> -
>> -// Iterate through the group
>> -TEST_F(InputGraphTest, GroupIteration) {
>> -  _graph->addInputElement(createFile2("file1", "file2"));
>> -
>> -  std::unique_ptr<Group> group(new Group());
>> -  group->addFile(createFile2("file3", "file4"));
>> -  group->addFile(createFile1("file5"));
>> -  group->addFile(createFile1("file6"));
>> -  _graph->addInputElement(std::move(group));
>> -
>> -  EXPECT_EQ("file1", getNext());
>> -  EXPECT_EQ("file2", getNext());
>> -
>> -  EXPECT_EQ("file3", getNext());
>> -  EXPECT_EQ("file4", getNext());
>> -  EXPECT_EQ("file5", getNext());
>> -  EXPECT_EQ("file6", getNext());
>> -  _graph->notifyProgress();
>> -
>> -  EXPECT_EQ("file3", getNext());
>> -  EXPECT_EQ("file4", getNext());
>> -  _graph->notifyProgress();
>> -  EXPECT_EQ("file5", getNext());
>> -  EXPECT_EQ("file6", getNext());
>> -
>> -  EXPECT_EQ("file3", getNext());
>> -  EXPECT_EQ("file4", getNext());
>> -  EXPECT_EQ("file5", getNext());
>> -  EXPECT_EQ("file6", getNext());
>>     expectEnd();
>>   }
>>     // Node expansion tests
>>   TEST_F(InputGraphTest, Normalize) {
>> -  _graph->addInputElement(createFile2("file1", "file2"));
>> +  _graph->addInputElement(createFile("file1"));
>>       std::unique_ptr<TestExpandFileNode> expandFile(
>>         new TestExpandFileNode("node"));
>> -  expandFile->addElement(createFile1("file3"));
>> -  expandFile->addElement(createFile1("file4"));
>> +  expandFile->addElement(createFile("file2"));
>> +  expandFile->addElement(createFile("file3"));
>>     _graph->addInputElement(std::move(expandFile));
>> -
>> -  std::unique_ptr<Group> group(new Group());
>> -  std::unique_ptr<TestExpandFileNode> expandFile2(
>> -      new TestExpandFileNode("node"));
>> -  expandFile2->addElement(createFile1("file5"));
>> -  group->addFile(std::move(expandFile2));
>> -  _graph->addInputElement(std::move(group));
>> -
>> -  _graph->addInputElement(createFile1("file6"));
>>     _graph->normalize();
>>       EXPECT_EQ("file1", getNext());
>>     EXPECT_EQ("file2", getNext());
>>     EXPECT_EQ("file3", getNext());
>> -  EXPECT_EQ("file4", getNext());
>> -  EXPECT_EQ("file5", getNext());
>> -  EXPECT_EQ("file6", getNext());
>>     expectEnd();
>>   }
>>   @@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {
>>     std::vector<std::string> files;
>>     _graph->registerObserver([&](File *file) {
>> files.push_back(file->path()); });
>>   -  _graph->addInputElement(createFile1("file1"));
>> -  _graph->addInputElement(createFile1("file2"));
>> +  _graph->addInputElement(createFile("file1"));
>> +  _graph->addInputElement(createFile("file2"));
>>     EXPECT_EQ("file1", getNext());
>>     EXPECT_EQ("file2", getNext());
>>     expectEnd();
>>
>> Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/
>> DriverTests/WinLinkDriverTest.cpp?rev=223867&r1=223866&r2=
>> 223867&view=diff
>> ============================================================
>> ==================
>> --- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
>> +++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Tue Dec  9
>> 18:33:00 2014
>> @@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {
>>   TEST_F(WinLinkParserTest, InputOrder) {
>>     EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib",
>> "d.obj",
>>                       nullptr));
>> -  EXPECT_EQ(5, inputFileCount());
>> +  EXPECT_EQ(6, inputFileCount());
>>     EXPECT_EQ("b.obj", inputFile(0));
>>     EXPECT_EQ("c.obj", inputFile(1));
>>     EXPECT_EQ("d.obj", inputFile(2));
>> -  EXPECT_EQ("a.lib", inputFile(4, 0));
>> +  EXPECT_EQ("a.lib", inputFile(4));
>>   }
>>     //
>> @@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl
>>   TEST_F(WinLinkParserTest, DefaultLib) {
>>     EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
>>                       "/defaultlib:kernel32", "a.obj", nullptr));
>> -  EXPECT_EQ(3, inputFileCount());
>> +  EXPECT_EQ(5, inputFileCount());
>>     EXPECT_EQ("a.obj", inputFile(0));
>> -  EXPECT_EQ("user32.lib", inputFile(2, 0));
>> -  EXPECT_EQ("kernel32.lib", inputFile(2, 1));
>> +  EXPECT_EQ("user32.lib", inputFile(2));
>> +  EXPECT_EQ("kernel32.lib", inputFile(3));
>>   }
>>     TEST_F(WinLinkParserTest, DefaultLibDuplicates) {
>>     EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
>>                       "/defaultlib:user32.lib", "a.obj", nullptr));
>> -  EXPECT_EQ(3, inputFileCount());
>> +  EXPECT_EQ(4, inputFileCount());
>>     EXPECT_EQ("a.obj", inputFile(0));
>> -  EXPECT_EQ("user32.lib", inputFile(2, 0));
>> +  EXPECT_EQ("user32.lib", inputFile(2));
>>   }
>>     TEST_F(WinLinkParserTest, NoDefaultLib) {
>>     EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
>>                       "/defaultlib:kernel32", "/nodefaultlib:user32.lib",
>> "a.obj",
>>                       nullptr));
>> -  EXPECT_EQ(3, inputFileCount());
>> +  EXPECT_EQ(4, inputFileCount());
>>     EXPECT_EQ("a.obj", inputFile(0));
>> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
>> +  EXPECT_EQ("kernel32.lib", inputFile(2));
>>   }
>>     TEST_F(WinLinkParserTest, NoDefaultLibCase) {
>>     EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",
>>                       "/defaultlib:kernel32", "/nodefaultlib:USER32.LIB",
>> "a.obj",
>>                       nullptr));
>> -  EXPECT_EQ(3, inputFileCount());
>> +  EXPECT_EQ(4, inputFileCount());
>>     EXPECT_EQ("a.obj", inputFile(0));
>> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
>> +  EXPECT_EQ("kernel32.lib", inputFile(2));
>>   }
>>     TEST_F(WinLinkParserTest, NoDefaultLibAll) {
>> @@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {
>>     EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
>>                       "/defaultlib:kernel32", "/disallowlib:user32.lib",
>> "a.obj",
>>                       nullptr));
>> -  EXPECT_EQ(3, inputFileCount());
>> +  EXPECT_EQ(4, inputFileCount());
>>     EXPECT_EQ("a.obj", inputFile(0));
>> -  EXPECT_EQ("kernel32.lib", inputFile(2, 0));
>> +  EXPECT_EQ("kernel32.lib", inputFile(2));
>>   }
>>     //
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>>
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted
> by the Linux Foundation
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141212/0b76066a/attachment.html>


More information about the llvm-commits mailing list