[lld] r264067 - Use owning pointers instead of raw pointers for Atom's to fix leaks.

Pete Cooper via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 22 10:15:50 PDT 2016


Author: pete
Date: Tue Mar 22 12:15:50 2016
New Revision: 264067

URL: http://llvm.org/viewvc/llvm-project?rev=264067&view=rev
Log:
Use owning pointers instead of raw pointers for Atom's to fix leaks.

This is a re-commit of r264022 with a fix for MSVC.  The issue there was
that the code was running DefinedAtom::~Atom() for some value and instead
needed to cast to Atom before running ~Atom.  Original commit message follows.

Currently each File contains an BumpPtrAllocator in which Atom's are
allocated.  Some Atom's contain data structures like std::vector which
leak as we don't run ~Atom when they are BumpPtrAllocate'd.

Now each File actually owns its Atom's using an OwningAtomPtr.  This
is analygous to std::unique_ptr and may be replaced by it if possible.

An Atom can therefore only be owned by a single File, so the Resolver now
moves them from one File to another.  The MachOLinkingContext owns the File's
and so clears all the Atom's in ~MachOLinkingContext, then delete's all the
File's.  This makes sure all Atom's have been destructed before any of the
BumpPtrAllocator's in which they run have gone away.

Should hopefully fix the remaining leaks.  Will keep an eye on the bots to
make sure.

Modified:
    lld/trunk/include/lld/Core/Atom.h
    lld/trunk/include/lld/Core/DefinedAtom.h
    lld/trunk/include/lld/Core/File.h
    lld/trunk/include/lld/Core/Resolver.h
    lld/trunk/include/lld/Core/SharedLibraryAtom.h
    lld/trunk/include/lld/Core/SharedLibraryFile.h
    lld/trunk/include/lld/Core/Simple.h
    lld/trunk/include/lld/Core/UndefinedAtom.h
    lld/trunk/lib/Core/File.cpp
    lld/trunk/lib/Core/Resolver.cpp
    lld/trunk/lib/Driver/DarwinLdDriver.cpp
    lld/trunk/lib/ReaderWriter/FileArchive.cpp
    lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
    lld/trunk/lib/ReaderWriter/MachO/Atoms.h
    lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.h
    lld/trunk/lib/ReaderWriter/MachO/File.h
    lld/trunk/lib/ReaderWriter/MachO/FlatNamespaceFile.h
    lld/trunk/lib/ReaderWriter/MachO/GOTPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/LayoutPass.h
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/SectCreateFile.h
    lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp
    lld/trunk/lib/ReaderWriter/MachO/TLVPass.cpp
    lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp

Modified: lld/trunk/include/lld/Core/Atom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Atom.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Atom.h (original)
+++ lld/trunk/include/lld/Core/Atom.h Tue Mar 22 12:15:50 2016
@@ -16,6 +16,9 @@ namespace lld {
 
 class File;
 
+template<typename T>
+class OwningAtomPtr;
+
 ///
 /// The linker has a Graph Theory model of linking. An object file is seen
 /// as a set of Atoms with References to other Atoms.  Each Atom is a node
@@ -24,6 +27,7 @@ class File;
 /// undefined symbol (extern declaration).
 ///
 class Atom {
+  template<typename T> friend class OwningAtomPtr;
 public:
   /// Whether this atom is defined or a proxy for an undefined symbol
   enum Definition {
@@ -71,6 +75,53 @@ private:
   Definition _definition;
 };
 
+/// Class which owns an atom pointer and runs the atom destructor when the
+/// owning pointer goes out of scope.
+template<typename T>
+class OwningAtomPtr {
+private:
+  OwningAtomPtr(const OwningAtomPtr &) = delete;
+  void operator=(const OwningAtomPtr&) = delete;
+public:
+  OwningAtomPtr() : atom(nullptr) { }
+  OwningAtomPtr(T *atom) : atom(atom) { }
+
+  ~OwningAtomPtr() {
+    if (atom)
+      runDestructor(atom);
+  }
+
+  void runDestructor(Atom *atom) {
+    atom->~Atom();
+  }
+
+  OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) {
+    ptr.atom = nullptr;
+  }
+
+  void operator=(OwningAtomPtr&& ptr) {
+    atom = ptr.atom;
+    ptr.atom = nullptr;
+  }
+
+  T *const &get() const {
+    return atom;
+  }
+
+  T *&get() {
+    return atom;
+  }
+
+  T *release() {
+    auto *v = atom;
+    atom = nullptr;
+    return v;
+  }
+
+private:
+  T *atom;
+};
+
 } // namespace lld
 
 #endif // LLD_CORE_ATOM_H

Modified: lld/trunk/include/lld/Core/DefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/DefinedAtom.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/DefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/DefinedAtom.h Tue Mar 22 12:15:50 2016
@@ -363,6 +363,8 @@ protected:
   // constructor.
   DefinedAtom() : Atom(definitionRegular) { }
 
+  ~DefinedAtom() override = default;
+
   /// \brief Returns a pointer to the Reference object that the abstract
   /// iterator "points" to.
   virtual const Reference *derefIterator(const void *iter) const = 0;

Modified: lld/trunk/include/lld/Core/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/File.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/File.h (original)
+++ lld/trunk/include/lld/Core/File.h Tue Mar 22 12:15:50 2016
@@ -15,6 +15,7 @@
 #include "lld/Core/SharedLibraryAtom.h"
 #include "lld/Core/UndefinedAtom.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include <functional>
@@ -39,6 +40,10 @@ class LinkingContext;
 /// The Atom objects in a File are owned by the File object.  The Atom objects
 /// are destroyed when the File object is destroyed.
 class File {
+protected:
+  /// The type of atom mutable container.
+  template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
+
 public:
   virtual ~File();
 
@@ -104,18 +109,67 @@ public:
     return _allocator;
   }
 
-  /// The type of atom mutable container.
-  template <typename T> using AtomVector = std::vector<const T *>;
-
-  /// The range type for the atoms. It's backed by a std::vector, but hides
-  /// its member functions so that you can only call begin or end.
+  /// The range type for the atoms.
   template <typename T> class AtomRange {
   public:
-    AtomRange(AtomVector<T> v) : _v(v) {}
-    typename AtomVector<T>::const_iterator begin() const { return _v.begin(); }
-    typename AtomVector<T>::const_iterator end() const { return _v.end(); }
-    typename AtomVector<T>::iterator begin() { return _v.begin(); }
-    typename AtomVector<T>::iterator end() { return _v.end(); }
+    AtomRange(AtomVector<T> &v) : _v(v) {}
+    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
+
+    typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
+                                           const T*> ConstDerefFn;
+
+    typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
+
+    typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
+                                  ConstDerefFn> ConstItTy;
+    typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
+                                  DerefFn> ItTy;
+
+    static const T* DerefConst(const OwningAtomPtr<T> &p) {
+      return p.get();
+    }
+
+    static T* Deref(OwningAtomPtr<T> &p) {
+      return p.get();
+    }
+
+    ConstItTy begin() const {
+      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
+    }
+    ConstItTy end() const {
+      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
+    }
+
+    ItTy begin() {
+      return ItTy(_v.begin(), DerefFn(Deref));
+    }
+    ItTy end() {
+      return ItTy(_v.end(), DerefFn(Deref));
+    }
+
+    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
+      return llvm::make_range(_v.begin(), _v.end());
+    }
+
+    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
+      return llvm::make_range(_v.begin(), _v.end());
+    }
+
+    bool empty() const {
+      return _v.empty();
+    }
+
+    size_t size() const {
+      return _v.size();
+    }
+
+    const OwningAtomPtr<T> &operator[](size_t idx) const {
+      return _v[idx];
+    }
+
+    OwningAtomPtr<T> &operator[](size_t idx) {
+      return _v[idx];
+    }
 
   private:
     AtomVector<T> &_v;
@@ -123,19 +177,25 @@ public:
 
   /// \brief Must be implemented to return the AtomVector object for
   /// all DefinedAtoms in this File.
-  virtual const AtomVector<DefinedAtom> &defined() const = 0;
+  virtual const AtomRange<DefinedAtom> defined() const = 0;
 
   /// \brief Must be implemented to return the AtomVector object for
   /// all UndefinedAtomw in this File.
-  virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
+  virtual const AtomRange<UndefinedAtom> undefined() const = 0;
 
   /// \brief Must be implemented to return the AtomVector object for
   /// all SharedLibraryAtoms in this File.
-  virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
+  virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
 
   /// \brief Must be implemented to return the AtomVector object for
   /// all AbsoluteAtoms in this File.
-  virtual const AtomVector<AbsoluteAtom> &absolute() const = 0;
+  virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
+
+  /// Drop all of the atoms owned by this file.  This will result in all of
+  /// the atoms running their destructors.
+  /// This is required because atoms may be allocated on a BumpPtrAllocator
+  /// of a different file.  We need to destruct all atoms before any files.
+  virtual void clearAtoms() = 0;
 
   /// \brief If a file is parsed using a different method than doParse(),
   /// one must use this method to set the last error status, so that
@@ -194,19 +254,22 @@ public:
 
   std::error_code doParse() override { return _ec; }
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     llvm_unreachable("internal error");
   }
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     llvm_unreachable("internal error");
   }
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     llvm_unreachable("internal error");
   }
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     llvm_unreachable("internal error");
   }
 
+  void clearAtoms() override {
+  }
+
 private:
   std::error_code _ec;
 };

Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Mar 22 12:15:50 2016
@@ -35,10 +35,10 @@ public:
   Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {}
 
   // InputFiles::Handler methods
-  void doDefinedAtom(const DefinedAtom&);
-  bool doUndefinedAtom(const UndefinedAtom &);
-  void doSharedLibraryAtom(const SharedLibraryAtom &);
-  void doAbsoluteAtom(const AbsoluteAtom &);
+  void doDefinedAtom(OwningAtomPtr<DefinedAtom> atom);
+  bool doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom);
+  void doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom);
+  void doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom);
 
   // Handle files, this adds atoms from the current file thats
   // being processed by the resolver
@@ -71,17 +71,16 @@ private:
                                  UndefCallback callback);
 
   void markLive(const Atom *atom);
-  void addAtoms(const std::vector<const DefinedAtom *>&);
 
   class MergedFile : public SimpleFile {
   public:
     MergedFile() : SimpleFile("<linker-internal>", kindResolverMergedObject) {}
-    void addAtoms(std::vector<const Atom*>& atoms);
+    void addAtoms(llvm::MutableArrayRef<OwningAtomPtr<Atom>> atoms);
   };
 
   LinkingContext &_ctx;
   SymbolTable _symbolTable;
-  std::vector<const Atom *>     _atoms;
+  std::vector<OwningAtomPtr<Atom>>     _atoms;
   std::set<const Atom *>        _deadStripRoots;
   llvm::DenseSet<const Atom *>  _liveAtoms;
   llvm::DenseSet<const Atom *>  _deadAtoms;

Modified: lld/trunk/include/lld/Core/SharedLibraryAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SharedLibraryAtom.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SharedLibraryAtom.h (original)
+++ lld/trunk/include/lld/Core/SharedLibraryAtom.h Tue Mar 22 12:15:50 2016
@@ -44,6 +44,8 @@ public:
 
 protected:
   SharedLibraryAtom() : Atom(definitionSharedLibrary) {}
+
+  ~SharedLibraryAtom() override = default;
 };
 
 } // namespace lld

Modified: lld/trunk/include/lld/Core/SharedLibraryFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/SharedLibraryFile.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/SharedLibraryFile.h (original)
+++ lld/trunk/include/lld/Core/SharedLibraryFile.h Tue Mar 22 12:15:50 2016
@@ -27,28 +27,35 @@ public:
   /// Check if the shared library exports a symbol with the specified name.
   /// If so, return a SharedLibraryAtom which represents that exported
   /// symbol.  Otherwise return nullptr.
-  virtual const SharedLibraryAtom *exports(StringRef name,
+  virtual OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
                                            bool dataSymbolOnly) const = 0;
 
   // Returns the install name.
   virtual StringRef getDSOName() const = 0;
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     return _definedAtoms;
   }
 
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _undefinedAtoms;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     return _sharedLibraryAtoms;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _absoluteAtoms;
   }
 
+  void clearAtoms() override {
+    _definedAtoms.clear();
+    _undefinedAtoms.clear();
+    _sharedLibraryAtoms.clear();
+    _absoluteAtoms.clear();
+  }
+
 protected:
   /// only subclasses of SharedLibraryFile can be instantiated
   explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}

Modified: lld/trunk/include/lld/Core/Simple.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Simple.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Simple.h (original)
+++ lld/trunk/include/lld/Core/Simple.h Tue Mar 22 12:15:50 2016
@@ -31,20 +31,35 @@ public:
   SimpleFile(StringRef path, File::Kind kind)
     : File(path, kind) {}
 
-  void addAtom(const DefinedAtom &a) { _defined.push_back(&a); }
-  void addAtom(const UndefinedAtom &a) { _undefined.push_back(&a); }
-  void addAtom(const SharedLibraryAtom &a) { _shared.push_back(&a); }
-  void addAtom(const AbsoluteAtom &a) { _absolute.push_back(&a); }
+  ~SimpleFile() override {
+    _defined.clear();
+    _undefined.clear();
+    _shared.clear();
+    _absolute.clear();
+  }
+
+  void addAtom(DefinedAtom &a) {
+    _defined.push_back(OwningAtomPtr<DefinedAtom>(&a));
+  }
+  void addAtom(UndefinedAtom &a) {
+    _undefined.push_back(OwningAtomPtr<UndefinedAtom>(&a));
+  }
+  void addAtom(SharedLibraryAtom &a) {
+    _shared.push_back(OwningAtomPtr<SharedLibraryAtom>(&a));
+  }
+  void addAtom(AbsoluteAtom &a) {
+    _absolute.push_back(OwningAtomPtr<AbsoluteAtom>(&a));
+  }
 
   void addAtom(const Atom &atom) {
     if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
-      _defined.push_back(p);
+      addAtom(const_cast<DefinedAtom &>(*p));
     } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
-      _undefined.push_back(p);
+      addAtom(const_cast<UndefinedAtom &>(*p));
     } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
-      _shared.push_back(p);
+      addAtom(const_cast<SharedLibraryAtom &>(*p));
     } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
-      _absolute.push_back(p);
+      addAtom(const_cast<AbsoluteAtom &>(*p));
     } else {
       llvm_unreachable("atom has unknown definition kind");
     }
@@ -52,25 +67,35 @@ public:
 
   void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
     auto &atoms = _defined;
-    auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
+    auto newEnd = std::remove_if(atoms.begin(), atoms.end(),
+                                 [&pred](OwningAtomPtr<DefinedAtom> &p) {
+                                   return pred(p.get());
+                                 });
     atoms.erase(newEnd, atoms.end());
   }
 
-  const AtomVector<DefinedAtom> &defined() const override { return _defined; }
+  const AtomRange<DefinedAtom> defined() const override { return _defined; }
 
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _undefined;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     return _shared;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _absolute;
   }
 
-  typedef llvm::MutableArrayRef<const DefinedAtom *> DefinedAtomRange;
+  void clearAtoms() override {
+    _defined.clear();
+    _undefined.clear();
+    _shared.clear();
+    _absolute.clear();
+  }
+
+  typedef AtomRange<DefinedAtom> DefinedAtomRange;
   DefinedAtomRange definedAtoms() { return _defined; }
 
 private:
@@ -169,6 +194,10 @@ public:
     _references.setAllocator(&f.allocator());
   }
 
+  ~SimpleDefinedAtom() {
+    _references.clearAndLeakNodesUnsafely();
+  }
+
   const File &file() const override { return _file; }
 
   StringRef name() const override { return StringRef(); }
@@ -265,6 +294,8 @@ public:
     assert(!name.empty() && "UndefinedAtoms must have a name");
   }
 
+  ~SimpleUndefinedAtom() override = default;
+
   /// file - returns the File that produced/owns this Atom
   const File &file() const override { return _file; }
 

Modified: lld/trunk/include/lld/Core/UndefinedAtom.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/UndefinedAtom.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/UndefinedAtom.h (original)
+++ lld/trunk/include/lld/Core/UndefinedAtom.h Tue Mar 22 12:15:50 2016
@@ -59,6 +59,8 @@ public:
 
 protected:
   UndefinedAtom() : Atom(definitionUndefined) {}
+
+  ~UndefinedAtom() override = default;
 };
 
 } // namespace lld

Modified: lld/trunk/lib/Core/File.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/File.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/Core/File.cpp (original)
+++ lld/trunk/lib/Core/File.cpp Tue Mar 22 12:15:50 2016
@@ -13,7 +13,7 @@
 
 namespace lld {
 
-File::~File() {}
+File::~File() { }
 
 File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
 File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;

Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Mar 22 12:15:50 2016
@@ -33,16 +33,16 @@ ErrorOr<bool> Resolver::handleFile(File
   if (auto ec = _ctx.handleLoadedFile(file))
     return ec;
   bool undefAdded = false;
-  for (const DefinedAtom *atom : file.defined())
-    doDefinedAtom(*atom);
-  for (const UndefinedAtom *atom : file.undefined()) {
-    if (doUndefinedAtom(*atom))
+  for (auto &atom : file.defined().owning_ptrs())
+    doDefinedAtom(std::move(atom));
+  for (auto &atom : file.undefined().owning_ptrs()) {
+    if (doUndefinedAtom(std::move(atom)))
       undefAdded = true;
   }
-  for (const SharedLibraryAtom *atom : file.sharedLibrary())
-    doSharedLibraryAtom(*atom);
-  for (const AbsoluteAtom *atom : file.absolute())
-    doAbsoluteAtom(*atom);
+  for (auto &atom : file.sharedLibrary().owning_ptrs())
+    doSharedLibraryAtom(std::move(atom));
+  for (auto &atom : file.absolute().owning_ptrs())
+    doAbsoluteAtom(std::move(atom));
   return undefAdded;
 }
 
@@ -113,9 +113,9 @@ std::error_code Resolver::handleSharedLi
   undefAddedOrError = forEachUndefines(file, searchForOverrides,
                                        [&](StringRef undefName,
                                            bool dataSymbolOnly)->ErrorOr<bool> {
-    if (const SharedLibraryAtom *atom =
-            sharedLibrary->exports(undefName, dataSymbolOnly))
-      doSharedLibraryAtom(*atom);
+    auto atom = sharedLibrary->exports(undefName, dataSymbolOnly);
+    if (atom.get())
+      doSharedLibraryAtom(std::move(atom));
     return false;
   });
 
@@ -124,84 +124,79 @@ std::error_code Resolver::handleSharedLi
   return std::error_code();
 }
 
-bool Resolver::doUndefinedAtom(const UndefinedAtom &atom) {
+bool Resolver::doUndefinedAtom(OwningAtomPtr<UndefinedAtom> atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                     << "       UndefinedAtom: "
-                    << llvm::format("0x%09lX", &atom)
-                    << ", name=" << atom.name() << "\n");
-
-  // add to list of known atoms
-  _atoms.push_back(&atom);
+                    << llvm::format("0x%09lX", atom.get())
+                    << ", name=" << atom.get()->name() << "\n");
 
   // tell symbol table
-  bool newUndefAdded = _symbolTable.add(atom);
+  bool newUndefAdded = _symbolTable.add(*atom.get());
   if (newUndefAdded)
-    _undefines.push_back(atom.name());
+    _undefines.push_back(atom.get()->name());
+
+  // add to list of known atoms
+  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
 
   return newUndefAdded;
 }
 
 // Called on each atom when a file is added. Returns true if a given
 // atom is added to the symbol table.
-void Resolver::doDefinedAtom(const DefinedAtom &atom) {
+void Resolver::doDefinedAtom(OwningAtomPtr<DefinedAtom> atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                     << "         DefinedAtom: "
-                    << llvm::format("0x%09lX", &atom)
+                    << llvm::format("0x%09lX", atom.get())
                     << ", file=#"
-                    << atom.file().ordinal()
+                    << atom.get()->file().ordinal()
                     << ", atom=#"
-                    << atom.ordinal()
+                    << atom.get()->ordinal()
                     << ", name="
-                    << atom.name()
+                    << atom.get()->name()
                     << ", type="
-                    << atom.contentType()
+                    << atom.get()->contentType()
                     << "\n");
 
-  // add to list of known atoms
-  _atoms.push_back(&atom);
-  _symbolTable.add(atom);
-
   // An atom that should never be dead-stripped is a dead-strip root.
-  if (_ctx.deadStrip() && atom.deadStrip() == DefinedAtom::deadStripNever) {
-    _deadStripRoots.insert(&atom);
+  if (_ctx.deadStrip() &&
+      atom.get()->deadStrip() == DefinedAtom::deadStripNever) {
+    _deadStripRoots.insert(atom.get());
   }
+
+  // add to list of known atoms
+  _symbolTable.add(*atom.get());
+  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
 }
 
-void Resolver::doSharedLibraryAtom(const SharedLibraryAtom &atom) {
+void Resolver::doSharedLibraryAtom(OwningAtomPtr<SharedLibraryAtom> atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                     << "   SharedLibraryAtom: "
-                    << llvm::format("0x%09lX", &atom)
+                    << llvm::format("0x%09lX", atom.get())
                     << ", name="
-                    << atom.name()
+                    << atom.get()->name()
                     << "\n");
 
-  // add to list of known atoms
-  _atoms.push_back(&atom);
-
   // tell symbol table
-  _symbolTable.add(atom);
+  _symbolTable.add(*atom.get());
+
+  // add to list of known atoms
+  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
 }
 
-void Resolver::doAbsoluteAtom(const AbsoluteAtom &atom) {
+void Resolver::doAbsoluteAtom(OwningAtomPtr<AbsoluteAtom> atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                     << "       AbsoluteAtom: "
-                    << llvm::format("0x%09lX", &atom)
+                    << llvm::format("0x%09lX", atom.get())
                     << ", name="
-                    << atom.name()
+                    << atom.get()->name()
                     << "\n");
 
-  // add to list of known atoms
-  _atoms.push_back(&atom);
-
   // tell symbol table
-  if (atom.scope() != Atom::scopeTranslationUnit)
-    _symbolTable.add(atom);
-}
+  if (atom.get()->scope() != Atom::scopeTranslationUnit)
+    _symbolTable.add(*atom.get());
 
-// utility to add a vector of atoms
-void Resolver::addAtoms(const std::vector<const DefinedAtom *> &newAtoms) {
-  for (const DefinedAtom *newAtom : newAtoms)
-    doDefinedAtom(*newAtom);
+  // add to list of known atoms
+  _atoms.push_back(OwningAtomPtr<Atom>(atom.release()));
 }
 
 // Returns true if at least one of N previous files has created an
@@ -316,8 +311,8 @@ void Resolver::updateReferences() {
   DEBUG_WITH_TYPE("resolver",
                   llvm::dbgs() << "******** Updating references:\n");
   ScopedTask task(getDefaultDomain(), "updateReferences");
-  for (const Atom *atom : _atoms) {
-    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
+  for (const OwningAtomPtr<Atom> &atom : _atoms) {
+    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get())) {
       for (const Reference *ref : *defAtom) {
         // A reference of type kindAssociate should't be updated.
         // Instead, an atom having such reference will be removed
@@ -325,7 +320,7 @@ void Resolver::updateReferences() {
         // go away as a group.
         if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
             ref->kindValue() == lld::Reference::kindAssociate) {
-          if (_symbolTable.isCoalescedAway(atom))
+          if (_symbolTable.isCoalescedAway(atom.get()))
             _deadAtoms.insert(ref->target());
           continue;
         }
@@ -373,19 +368,19 @@ void Resolver::deadStripOptimize() {
   // Make a reverse map of such references before traversing the graph.
   // While traversing the list of atoms, mark AbsoluteAtoms as live
   // in order to avoid reclaim.
-  for (const Atom *atom : _atoms) {
-    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+  for (const OwningAtomPtr<Atom> &atom : _atoms) {
+    if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
       for (const Reference *ref : *defAtom)
         if (isBackref(ref))
-          _reverseRef.insert(std::make_pair(ref->target(), atom));
-    if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom))
+          _reverseRef.insert(std::make_pair(ref->target(), atom.get()));
+    if (const AbsoluteAtom *absAtom = dyn_cast<AbsoluteAtom>(atom.get()))
       markLive(absAtom);
   }
 
   // By default, shared libraries are built with all globals as dead strip roots
   if (_ctx.globalsAreDeadStripRoots())
-    for (const Atom *atom : _atoms)
-      if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom))
+    for (const OwningAtomPtr<Atom> &atom : _atoms)
+      if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom.get()))
         if (defAtom->scope() == DefinedAtom::scopeGlobal)
           _deadStripRoots.insert(defAtom);
 
@@ -401,8 +396,9 @@ void Resolver::deadStripOptimize() {
     markLive(dsrAtom);
 
   // now remove all non-live atoms from _atoms
-  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
-                 return _liveAtoms.count(a) == 0;
+  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+                              [&](OwningAtomPtr<Atom> &a) {
+                 return _liveAtoms.count(a.get()) == 0;
                }),
                _atoms.end());
 }
@@ -461,8 +457,10 @@ void Resolver::removeCoalescedAwayAtoms(
   DEBUG_WITH_TYPE("resolver",
                   llvm::dbgs() << "******** Removing coalesced away atoms:\n");
   ScopedTask task(getDefaultDomain(), "removeCoalescedAwayAtoms");
-  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), [&](const Atom *a) {
-                 return _symbolTable.isCoalescedAway(a) || _deadAtoms.count(a);
+  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
+                              [&](OwningAtomPtr<Atom> &a) {
+                 return _symbolTable.isCoalescedAway(a.get()) ||
+                        _deadAtoms.count(a.get());
                }),
                _atoms.end());
 }
@@ -488,15 +486,16 @@ bool Resolver::resolve() {
   return true;
 }
 
-void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
+void Resolver::MergedFile::addAtoms(
+                              llvm::MutableArrayRef<OwningAtomPtr<Atom>> all) {
   ScopedTask task(getDefaultDomain(), "addAtoms");
   DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
 
-  for (const Atom *atom : all) {
+  for (OwningAtomPtr<Atom> &atom : all) {
 #ifndef NDEBUG
-    if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+    if (auto *definedAtom = dyn_cast<DefinedAtom>(atom.get())) {
       DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                      << llvm::format("    0x%09lX", atom)
+                      << llvm::format("    0x%09lX", definedAtom)
                       << ", file=#"
                       << definedAtom->file().ordinal()
                       << ", atom=#"
@@ -508,13 +507,13 @@ void Resolver::MergedFile::addAtoms(std:
                       << "\n");
     } else {
       DEBUG_WITH_TYPE("resolver", llvm::dbgs()
-                      << llvm::format("    0x%09lX", atom)
+                      << llvm::format("    0x%09lX", atom.get())
                       << ", name="
-                      << atom->name()
+                      << atom.get()->name()
                       << "\n");
     }
 #endif
-    addAtom(*atom);
+    addAtom(*atom.release());
   }
 }
 

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Tue Mar 22 12:15:50 2016
@@ -1169,7 +1169,14 @@ bool link(llvm::ArrayRef<const char *> a
   Resolver resolver(ctx);
   if (!resolver.resolve())
     return false;
-  std::unique_ptr<SimpleFile> merged = resolver.resultFile();
+  SimpleFile *merged = nullptr;
+  {
+    std::unique_ptr<SimpleFile> mergedFile = resolver.resultFile();
+    merged = mergedFile.get();
+    auto &members = ctx.getNodes();
+    members.insert(members.begin(),
+                   llvm::make_unique<FileNode>(std::move(mergedFile)));
+  }
   resolveTask.end();
 
   // Run passes on linked atoms.

Modified: lld/trunk/lib/ReaderWriter/FileArchive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/FileArchive.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/FileArchive.cpp (original)
+++ lld/trunk/lib/ReaderWriter/FileArchive.cpp Tue Mar 22 12:15:50 2016
@@ -88,22 +88,29 @@ public:
     return std::error_code();
   }
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     return _noDefinedAtoms;
   }
 
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _noUndefinedAtoms;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     return _noSharedLibraryAtoms;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _noAbsoluteAtoms;
   }
 
+  void clearAtoms() override {
+    _noDefinedAtoms.clear();
+    _noUndefinedAtoms.clear();
+    _noSharedLibraryAtoms.clear();
+    _noAbsoluteAtoms.clear();
+  }
+
 protected:
   std::error_code doParse() override {
     // Make Archive object which will be owned by FileArchive object.

Modified: lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ArchHandler_arm.cpp Tue Mar 22 12:15:50 2016
@@ -1429,6 +1429,8 @@ public:
     _name = tmp.copy(file.allocator());
   }
 
+  ~Thumb2ToArmShimAtom() override = default;
+
   StringRef name() const override {
     return _name;
   }
@@ -1472,6 +1474,8 @@ public:
     _name = tmp.copy(file.allocator());
   }
 
+  ~ArmToThumbShimAtom() override = default;
+
   StringRef name() const override {
     return _name;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/Atoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/Atoms.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/Atoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/Atoms.h Tue Mar 22 12:15:50 2016
@@ -32,6 +32,8 @@ public:
         _contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
         _noDeadStrip(noDeadStrip) {}
 
+  ~MachODefinedAtom() override = default;
+
   uint64_t size() const override { return _content.size(); }
 
   ContentType contentType() const override { return _contentType; }
@@ -83,6 +85,8 @@ public:
                          content, align),
         _sectionName(sectionName) {}
 
+  ~MachODefinedCustomSectionAtom() override = default;
+
   SectionChoice sectionChoice() const override {
     return DefinedAtom::sectionCustomRequired;
   }
@@ -101,6 +105,8 @@ public:
       : SimpleDefinedAtom(f), _name(name), _scope(scope), _size(size),
         _align(align) {}
 
+  ~MachOTentativeDefAtom() override = default;
+
   uint64_t size() const override { return _size; }
 
   Merge merge() const override { return DefinedAtom::mergeAsTentative; }

Modified: lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/CompactUnwindPass.cpp Tue Mar 22 12:15:50 2016
@@ -88,6 +88,8 @@ public:
     addSecondLevelPages(pages);
   }
 
+  ~UnwindInfoAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeProcessedUnwindInfo;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ExecutableAtoms.h Tue Mar 22 12:15:50 2016
@@ -122,21 +122,28 @@ public:
           ArrayRef<uint8_t>(), DefinedAtom::Alignment(1)));
   }
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     return _definedAtoms;
   }
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _noUndefinedAtoms;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     return _noSharedLibraryAtoms;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _noAbsoluteAtoms;
   }
 
+  void clearAtoms() override {
+    _definedAtoms.clear();
+    _noUndefinedAtoms.clear();
+    _noSharedLibraryAtoms.clear();
+    _noAbsoluteAtoms.clear();
+  }
+
 
 private:
   mutable AtomVector<DefinedAtom> _definedAtoms;

Modified: lld/trunk/lib/ReaderWriter/MachO/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/File.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/File.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/File.h Tue Mar 22 12:15:50 2016
@@ -275,7 +275,8 @@ public:
 
   MachODylibFile(StringRef path) : SharedLibraryFile(path) {}
 
-  const SharedLibraryAtom *exports(StringRef name, bool isData) const override {
+  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
+                                           bool isData) const override {
     // Pass down _installName so that if this requested symbol
     // is re-exported through this dylib, the SharedLibraryAtom's loadName()
     // is this dylib installName and not the implementation dylib's.
@@ -328,25 +329,30 @@ public:
   }
 
 private:
-  const SharedLibraryAtom *exports(StringRef name,
+  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
                                    StringRef installName) const {
     // First, check if requested symbol is directly implemented by this dylib.
     auto entry = _nameToAtom.find(name);
     if (entry != _nameToAtom.end()) {
-      if (!entry->second.atom) {
-        // Lazily create SharedLibraryAtom.
-        entry->second.atom =
-          new (allocator()) MachOSharedLibraryAtom(*this, name, installName,
-                                                   entry->second.weakDef);
-      }
-      return entry->second.atom;
+      // FIXME: Make this map a set and only used in assert builds.
+      // Note, its safe to assert here as the resolver is the only client of
+      // this API and it only requests exports for undefined symbols.
+      // If we return from here we are no longer undefined so we should never
+      // get here again.
+      assert(!entry->second.atom && "Duplicate shared library export");
+      bool weakDef = entry->second.weakDef;
+      auto *atom = new (allocator()) MachOSharedLibraryAtom(*this, name,
+                                                            installName,
+                                                            weakDef);
+      entry->second.atom = atom;
+      return atom;
     }
 
     // Next, check if symbol is implemented in some re-exported dylib.
     for (const ReExportedDylib &dylib : _reExportedDylibs) {
       assert(dylib.file);
       auto atom = dylib.file->exports(name, installName);
-      if (atom)
+      if (atom.get())
         return atom;
     }
 

Modified: lld/trunk/lib/ReaderWriter/MachO/FlatNamespaceFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/FlatNamespaceFile.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/FlatNamespaceFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/FlatNamespaceFile.h Tue Mar 22 12:15:50 2016
@@ -25,34 +25,35 @@ public:
   FlatNamespaceFile(const MachOLinkingContext &context)
     : SharedLibraryFile("flat namespace") { }
 
-  const SharedLibraryAtom *exports(StringRef name,
+  OwningAtomPtr<SharedLibraryAtom> exports(StringRef name,
                                    bool dataSymbolOnly) const override {
-    _sharedLibraryAtoms.push_back(
-      new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
-                                               false));
-
-    return _sharedLibraryAtoms.back();
+    return new (allocator()) MachOSharedLibraryAtom(*this, name, getDSOName(),
+                                                    false);
   }
 
   StringRef getDSOName() const override { return "flat-namespace"; }
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     return _noDefinedAtoms;
   }
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _noUndefinedAtoms;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
-    return _sharedLibraryAtoms;
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
+    return _noSharedLibraryAtoms;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _noAbsoluteAtoms;
   }
 
-private:
-  mutable AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+  void clearAtoms() override {
+    _noDefinedAtoms.clear();
+    _noUndefinedAtoms.clear();
+    _noSharedLibraryAtoms.clear();
+    _noAbsoluteAtoms.clear();
+  }
 };
 
 } // namespace mach_o

Modified: lld/trunk/lib/ReaderWriter/MachO/GOTPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/GOTPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/GOTPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/GOTPass.cpp Tue Mar 22 12:15:50 2016
@@ -54,6 +54,8 @@ public:
   GOTEntryAtom(const File &file, bool is64, StringRef name)
     : SimpleDefinedAtom(file), _is64(is64), _name(name) { }
 
+  ~GOTEntryAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeGOT;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/LayoutPass.cpp Tue Mar 22 12:15:50 2016
@@ -146,7 +146,7 @@ static void printDefinedAtoms(const Simp
 
 /// Verify that the followon chain is sane. Should not be called in
 /// release binary.
-void LayoutPass::checkFollowonChain(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::checkFollowonChain(const SimpleFile::DefinedAtomRange &range) {
   ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
 
   // Verify that there's no cycle in follow-on chain.
@@ -176,8 +176,8 @@ static bool compareAtomsSub(const Layout
                             const LayoutPass::SortKey &rc,
                             LayoutPass::SortOverride customSorter,
                             std::string &reason) {
-  const DefinedAtom *left = lc._atom;
-  const DefinedAtom *right = rc._atom;
+  const DefinedAtom *left = lc._atom.get();
+  const DefinedAtom *right = rc._atom.get();
   if (left == right) {
     reason = "same";
     return false;
@@ -252,8 +252,9 @@ static bool compareAtoms(const LayoutPas
   bool result = compareAtomsSub(lc, rc, customSorter, reason);
   DEBUG({
     StringRef comp = result ? "<" : ">=";
-    llvm::dbgs() << "Layout: '" << lc._atom->name() << "' " << comp << " '"
-                 << rc._atom->name() << "' (" << reason << ")\n";
+    llvm::dbgs() << "Layout: '" << lc._atom.get()->name()
+                 << "' " << comp << " '"
+                 << rc._atom.get()->name() << "' (" << reason << ")\n";
   });
   return result;
 }
@@ -329,7 +330,7 @@ void LayoutPass::setChainRoot(const Defi
 /// d) If the targetAtom is part of a different chain and the root of the
 ///    targetAtom until the targetAtom has all atoms of size 0, then chain the
 ///    targetAtoms and its tree to the current chain
-void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &range) {
+void LayoutPass::buildFollowOnTable(const SimpleFile::DefinedAtomRange &range) {
   ScopedTask task(getDefaultDomain(), "LayoutPass::buildFollowOnTable");
   // Set the initial size of the followon and the followonNext hash to the
   // number of atoms that we have.
@@ -397,7 +398,8 @@ void LayoutPass::buildFollowOnTable(Simp
 /// assigning ordinals to each atom, if the atoms have their ordinals
 /// already assigned skip the atom and move to the next. This is the
 /// main map thats used to sort the atoms while comparing two atoms together
-void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
+void
+LayoutPass::buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range) {
   ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
   uint64_t index = 0;
   for (const DefinedAtom *ai : range) {
@@ -419,12 +421,12 @@ void LayoutPass::buildOrdinalOverrideMap
 std::vector<LayoutPass::SortKey>
 LayoutPass::decorate(SimpleFile::DefinedAtomRange &atomRange) const {
   std::vector<SortKey> ret;
-  for (const DefinedAtom *atom : atomRange) {
-    auto ri = _followOnRoots.find(atom);
-    auto oi = _ordinalOverrideMap.find(atom);
-    const DefinedAtom *root = (ri == _followOnRoots.end()) ? atom : ri->second;
+  for (OwningAtomPtr<DefinedAtom> &atom : atomRange.owning_ptrs()) {
+    auto ri = _followOnRoots.find(atom.get());
+    auto oi = _ordinalOverrideMap.find(atom.get());
+    const auto *root = (ri == _followOnRoots.end()) ? atom.get() : ri->second;
     uint64_t override = (oi == _ordinalOverrideMap.end()) ? 0 : oi->second;
-    ret.push_back(SortKey(atom, root, override));
+    ret.push_back(SortKey(std::move(atom), root, override));
   }
   return ret;
 }
@@ -433,7 +435,7 @@ void LayoutPass::undecorate(SimpleFile::
                             std::vector<SortKey> &keys) const {
   size_t i = 0;
   for (SortKey &k : keys)
-    atomRange[i++] = k._atom;
+    atomRange[i++] = std::move(k._atom);
 }
 
 /// Perform the actual pass

Modified: lld/trunk/lib/ReaderWriter/MachO/LayoutPass.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/LayoutPass.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/LayoutPass.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/LayoutPass.h Tue Mar 22 12:15:50 2016
@@ -33,9 +33,10 @@ namespace mach_o {
 class LayoutPass : public Pass {
 public:
   struct SortKey {
-    SortKey(const DefinedAtom *atom, const DefinedAtom *root, uint64_t override)
-        : _atom(atom), _root(root), _override(override) {}
-    const DefinedAtom *_atom;
+    SortKey(OwningAtomPtr<DefinedAtom> &&atom,
+            const DefinedAtom *root, uint64_t override)
+    : _atom(std::move(atom)), _root(root), _override(override) {}
+    OwningAtomPtr<DefinedAtom> _atom;
     const DefinedAtom *_root;
     uint64_t _override;
   };
@@ -53,10 +54,10 @@ public:
 private:
   // Build the followOn atoms chain as specified by the kindLayoutAfter
   // reference type
-  void buildFollowOnTable(SimpleFile::DefinedAtomRange &range);
+  void buildFollowOnTable(const SimpleFile::DefinedAtomRange &range);
 
   // Build a map of Atoms to ordinals for sorting the atoms
-  void buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range);
+  void buildOrdinalOverrideMap(const SimpleFile::DefinedAtomRange &range);
 
   const Registry &_registry;
   SortOverride _customSorter;
@@ -85,11 +86,12 @@ private:
   void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
 
   std::vector<SortKey> decorate(SimpleFile::DefinedAtomRange &atomRange) const;
+
   void undecorate(SimpleFile::DefinedAtomRange &atomRange,
                   std::vector<SortKey> &keys) const;
 
   // Check if the follow-on graph is a correct structure. For debugging only.
-  void checkFollowonChain(SimpleFile::DefinedAtomRange &range);
+  void checkFollowonChain(const SimpleFile::DefinedAtomRange &range);
 };
 
 } // namespace mach_o

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Mar 22 12:15:50 2016
@@ -171,7 +171,19 @@ bool MachOLinkingContext::sliceFromFatFi
 
 MachOLinkingContext::MachOLinkingContext() {}
 
-MachOLinkingContext::~MachOLinkingContext() {}
+MachOLinkingContext::~MachOLinkingContext() {
+  // Atoms are allocated on BumpPtrAllocator's on File's.
+  // As we transfer atoms from one file to another, we need to clear all of the
+  // atoms before we remove any of the BumpPtrAllocator's.
+  auto &nodes = getNodes();
+  for (unsigned i = 0, e = nodes.size(); i != e; ++i) {
+    FileNode *node = dyn_cast<FileNode>(nodes[i].get());
+    if (!node)
+      continue;
+    File *file = node->getFile();
+    file->clearAtoms();
+  }
+}
 
 void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
                                     uint32_t minOSVersion,

Modified: lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/ObjCPass.cpp Tue Mar 22 12:15:50 2016
@@ -56,6 +56,8 @@ public:
     Data.info.flags |= (swiftVersion << 8);
   }
 
+  ~ObjCImageInfoAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeObjCImageInfo;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/SectCreateFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/SectCreateFile.h?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/SectCreateFile.h (original)
+++ lld/trunk/lib/ReaderWriter/MachO/SectCreateFile.h Tue Mar 22 12:15:50 2016
@@ -31,6 +31,8 @@ public:
         _combinedName((segName + "/" + sectName).str()),
         _content(std::move(content)) {}
 
+    ~SectCreateAtom() override = default;
+
     uint64_t size() const override { return _content->getBufferSize(); }
 
     Scope scope() const override { return scopeGlobal; }
@@ -67,22 +69,29 @@ public:
       new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
   }
 
-  const AtomVector<DefinedAtom> &defined() const override {
+  const AtomRange<DefinedAtom> defined() const override {
     return _definedAtoms;
   }
 
-  const AtomVector<UndefinedAtom> &undefined() const override {
+  const AtomRange<UndefinedAtom> undefined() const override {
     return _noUndefinedAtoms;
   }
 
-  const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
     return _noSharedLibraryAtoms;
   }
 
-  const AtomVector<AbsoluteAtom> &absolute() const override {
+  const AtomRange<AbsoluteAtom> absolute() const override {
     return _noAbsoluteAtoms;
   }
 
+  void clearAtoms() override {
+    _definedAtoms.clear();
+    _noUndefinedAtoms.clear();
+    _noSharedLibraryAtoms.clear();
+    _noAbsoluteAtoms.clear();
+  }
+
 private:
   AtomVector<DefinedAtom> _definedAtoms;
 };

Modified: lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/StubsPass.cpp Tue Mar 22 12:15:50 2016
@@ -37,6 +37,8 @@ public:
   LazyPointerAtom(const File &file, bool is64)
     : SimpleDefinedAtom(file), _is64(is64) { }
 
+  ~LazyPointerAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeLazyPointer;
   }
@@ -71,6 +73,8 @@ public:
   NonLazyPointerAtom(const File &file, bool is64, ContentType contentType)
     : SimpleDefinedAtom(file), _is64(is64), _contentType(contentType) { }
 
+  ~NonLazyPointerAtom() override = default;
+
   ContentType contentType() const override {
     return _contentType;
   }
@@ -106,6 +110,8 @@ public:
   StubAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
       : SimpleDefinedAtom(file), _stubInfo(stubInfo){ }
 
+  ~StubAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeStub;
   }
@@ -138,6 +144,8 @@ public:
   StubHelperAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
       : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
 
+  ~StubHelperAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeStubHelper;
   }
@@ -171,6 +179,8 @@ public:
   StubHelperCommonAtom(const File &file, const ArchHandler::StubInfo &stubInfo)
       : SimpleDefinedAtom(file), _stubInfo(stubInfo) { }
 
+  ~StubHelperCommonAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeStubHelper;
   }

Modified: lld/trunk/lib/ReaderWriter/MachO/TLVPass.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/TLVPass.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/TLVPass.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/TLVPass.cpp Tue Mar 22 12:15:50 2016
@@ -30,6 +30,8 @@ public:
   TLVPEntryAtom(const File &file, bool is64, StringRef name)
       : SimpleDefinedAtom(file), _is64(is64), _name(name) {}
 
+  ~TLVPEntryAtom() override = default;
+
   ContentType contentType() const override {
     return DefinedAtom::typeTLVInitializerPtr;
   }

Modified: lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp?rev=264067&r1=264066&r2=264067&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp (original)
+++ lld/trunk/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp Tue Mar 22 12:15:50 2016
@@ -195,7 +195,7 @@ private:
 
 /// Mapping of Atoms.
 template <typename T> class AtomList {
-  typedef lld::File::AtomVector<T> Ty;
+  using Ty = std::vector<OwningAtomPtr<T>>;
 
 public:
   typename Ty::iterator begin() { return _atoms.begin(); }
@@ -503,10 +503,20 @@ template <> struct MappingTraits<ArchMem
 // Declare that an AtomList is a yaml sequence.
 template <typename T> struct SequenceTraits<AtomList<T> > {
   static size_t size(IO &io, AtomList<T> &seq) { return seq._atoms.size(); }
-  static const T *&element(IO &io, AtomList<T> &seq, size_t index) {
+  static T *&element(IO &io, AtomList<T> &seq, size_t index) {
     if (index >= seq._atoms.size())
       seq._atoms.resize(index + 1);
-    return seq._atoms[index];
+    return seq._atoms[index].get();
+  }
+};
+
+// Declare that an AtomRange is a yaml sequence.
+template <typename T> struct SequenceTraits<File::AtomRange<T> > {
+  static size_t size(IO &io, File::AtomRange<T> &seq) { return seq.size(); }
+  static T *&element(IO &io, File::AtomRange<T> &seq, size_t index) {
+    assert(io.outputting() && "AtomRange only used when outputting");
+    assert(index < seq.size() && "Out of range access");
+    return seq[index].get();
   }
 };
 
@@ -558,23 +568,29 @@ template <> struct MappingTraits<const l
 
     const lld::File *denormalize(IO &io) { return this; }
 
-    const AtomVector<lld::DefinedAtom> &defined() const override {
+    const AtomRange<lld::DefinedAtom> defined() const override {
       return _noDefinedAtoms;
     }
 
-    const AtomVector<lld::UndefinedAtom> &undefined() const override {
+    const AtomRange<lld::UndefinedAtom> undefined() const override {
       return _noUndefinedAtoms;
     }
 
-    const AtomVector<lld::SharedLibraryAtom> &
-    sharedLibrary() const override {
+    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
       return _noSharedLibraryAtoms;
     }
 
-    const AtomVector<lld::AbsoluteAtom> &absolute() const override {
+    const AtomRange<lld::AbsoluteAtom> absolute() const override {
       return _noAbsoluteAtoms;
     }
 
+    void clearAtoms() override {
+      _noDefinedAtoms.clear();
+      _noUndefinedAtoms.clear();
+      _noSharedLibraryAtoms.clear();
+      _noAbsoluteAtoms.clear();
+    }
+
     File *find(StringRef name, bool dataSymbolOnly) override {
       for (const ArchMember &member : _members) {
         for (const lld::DefinedAtom *atom : member._content->defined()) {
@@ -606,36 +622,46 @@ template <> struct MappingTraits<const l
   class NormalizedFile : public lld::File {
   public:
     NormalizedFile(IO &io)
-      : File("", kindNormalizedObject), _io(io), _rnb(nullptr) {}
+      : File("", kindNormalizedObject), _io(io), _rnb(nullptr),
+        _definedAtomsRef(_definedAtoms._atoms),
+        _undefinedAtomsRef(_undefinedAtoms._atoms),
+        _sharedLibraryAtomsRef(_sharedLibraryAtoms._atoms),
+        _absoluteAtomsRef(_absoluteAtoms._atoms) {}
     NormalizedFile(IO &io, const lld::File *file)
         : File(file->path(), kindNormalizedObject), _io(io),
-          _rnb(new RefNameBuilder(*file)), _path(file->path()) {
-      for (const lld::DefinedAtom *a : file->defined())
-        _definedAtoms._atoms.push_back(a);
-      for (const lld::UndefinedAtom *a : file->undefined())
-        _undefinedAtoms._atoms.push_back(a);
-      for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
-        _sharedLibraryAtoms._atoms.push_back(a);
-      for (const lld::AbsoluteAtom *a : file->absolute())
-        _absoluteAtoms._atoms.push_back(a);
+          _rnb(new RefNameBuilder(*file)), _path(file->path()),
+        _definedAtomsRef(file->defined()),
+        _undefinedAtomsRef(file->undefined()),
+        _sharedLibraryAtomsRef(file->sharedLibrary()),
+        _absoluteAtomsRef(file->absolute()) {
+    }
+
+    ~NormalizedFile() override {
     }
+
     const lld::File *denormalize(IO &io);
 
-    const AtomVector<lld::DefinedAtom> &defined() const override {
-      return _definedAtoms._atoms;
+    const AtomRange<lld::DefinedAtom> defined() const override {
+      return _definedAtomsRef;
     }
 
-    const AtomVector<lld::UndefinedAtom> &undefined() const override {
-      return _undefinedAtoms._atoms;
+    const AtomRange<lld::UndefinedAtom> undefined() const override {
+      return _undefinedAtomsRef;
     }
 
-    const AtomVector<lld::SharedLibraryAtom> &
-    sharedLibrary() const override {
-      return _sharedLibraryAtoms._atoms;
+    const AtomRange<lld::SharedLibraryAtom> sharedLibrary() const override {
+      return _sharedLibraryAtomsRef;
     }
 
-    const AtomVector<lld::AbsoluteAtom> &absolute() const override {
-      return _absoluteAtoms._atoms;
+    const AtomRange<lld::AbsoluteAtom> absolute() const override {
+      return _absoluteAtomsRef;
+    }
+
+    void clearAtoms() override {
+      _definedAtoms._atoms.clear();
+      _undefinedAtoms._atoms.clear();
+      _sharedLibraryAtoms._atoms.clear();
+      _absoluteAtoms._atoms.clear();
     }
 
     // Allocate a new copy of this string in _storage, so the strings
@@ -653,6 +679,10 @@ template <> struct MappingTraits<const l
     AtomList<lld::UndefinedAtom>         _undefinedAtoms;
     AtomList<lld::SharedLibraryAtom>     _sharedLibraryAtoms;
     AtomList<lld::AbsoluteAtom>          _absoluteAtoms;
+    AtomRange<lld::DefinedAtom>          _definedAtomsRef;
+    AtomRange<lld::UndefinedAtom>        _undefinedAtomsRef;
+    AtomRange<lld::SharedLibraryAtom>    _sharedLibraryAtomsRef;
+    AtomRange<lld::AbsoluteAtom>         _absoluteAtomsRef;
     llvm::BumpPtrAllocator               _storage;
   };
 
@@ -676,10 +706,18 @@ template <> struct MappingTraits<const l
     info->_file = keys.operator->();
 
     io.mapOptional("path",                 keys->_path);
-    io.mapOptional("defined-atoms",        keys->_definedAtoms);
-    io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
-    io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
-    io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
+
+    if (io.outputting()) {
+      io.mapOptional("defined-atoms",        keys->_definedAtomsRef);
+      io.mapOptional("undefined-atoms",      keys->_undefinedAtomsRef);
+      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtomsRef);
+      io.mapOptional("absolute-atoms",       keys->_absoluteAtomsRef);
+    } else {
+      io.mapOptional("defined-atoms",        keys->_definedAtoms);
+      io.mapOptional("undefined-atoms",      keys->_undefinedAtoms);
+      io.mapOptional("shared-library-atoms", keys->_sharedLibraryAtoms);
+      io.mapOptional("absolute-atoms",       keys->_absoluteAtoms);
+    }
   }
 
   static void mappingArchive(IO &io, const lld::File *&file) {
@@ -790,6 +828,9 @@ template <> struct MappingTraits<const l
       for (uint8_t x : cont)
         _content.push_back(x);
     }
+
+    ~NormalizedAtom() override = default;
+    
     const lld::DefinedAtom *denormalize(IO &io) {
       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
       assert(info != nullptr);
@@ -938,6 +979,14 @@ template <> struct MappingTraits<const l
   }
 };
 
+template <> struct MappingTraits<lld::DefinedAtom *> {
+  static void mapping(IO &io, lld::DefinedAtom *&atom) {
+    const lld::DefinedAtom *atomPtr = atom;
+    MappingTraits<const lld::DefinedAtom *>::mapping(io, atomPtr);
+    atom = const_cast<lld::DefinedAtom *>(atomPtr);
+  }
+};
+
 // YAML conversion for const lld::UndefinedAtom*
 template <> struct MappingTraits<const lld::UndefinedAtom *> {
 
@@ -950,6 +999,8 @@ template <> struct MappingTraits<const l
         : _file(fileFromContext(io)), _name(atom->name()),
           _canBeNull(atom->canBeNull()) {}
 
+    ~NormalizedAtom() override = default;
+
     const lld::UndefinedAtom *denormalize(IO &io) {
       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
       assert(info != nullptr);
@@ -993,6 +1044,14 @@ template <> struct MappingTraits<const l
   }
 };
 
+template <> struct MappingTraits<lld::UndefinedAtom *> {
+  static void mapping(IO &io, lld::UndefinedAtom *&atom) {
+    const lld::UndefinedAtom *atomPtr = atom;
+    MappingTraits<const lld::UndefinedAtom *>::mapping(io, atomPtr);
+    atom = const_cast<lld::UndefinedAtom *>(atomPtr);
+  }
+};
+
 // YAML conversion for const lld::SharedLibraryAtom*
 template <> struct MappingTraits<const lld::SharedLibraryAtom *> {
 
@@ -1006,6 +1065,8 @@ template <> struct MappingTraits<const l
           _loadName(atom->loadName()), _canBeNull(atom->canBeNullAtRuntime()),
           _type(atom->type()), _size(atom->size()) {}
 
+    ~NormalizedAtom() override = default;
+
     const lld::SharedLibraryAtom *denormalize(IO &io) {
       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
       assert(info != nullptr);
@@ -1061,6 +1122,14 @@ template <> struct MappingTraits<const l
   }
 };
 
+template <> struct MappingTraits<lld::SharedLibraryAtom *> {
+  static void mapping(IO &io, lld::SharedLibraryAtom *&atom) {
+    const lld::SharedLibraryAtom *atomPtr = atom;
+    MappingTraits<const lld::SharedLibraryAtom *>::mapping(io, atomPtr);
+    atom = const_cast<lld::SharedLibraryAtom *>(atomPtr);
+  }
+};
+
 // YAML conversion for const lld::AbsoluteAtom*
 template <> struct MappingTraits<const lld::AbsoluteAtom *> {
 
@@ -1071,6 +1140,9 @@ template <> struct MappingTraits<const l
     NormalizedAtom(IO &io, const lld::AbsoluteAtom *atom)
         : _file(fileFromContext(io)), _name(atom->name()),
           _scope(atom->scope()), _value(atom->value()) {}
+
+    ~NormalizedAtom() override = default;
+
     const lld::AbsoluteAtom *denormalize(IO &io) {
       YamlContext *info = reinterpret_cast<YamlContext *>(io.getContext());
       assert(info != nullptr);
@@ -1129,6 +1201,14 @@ template <> struct MappingTraits<const l
   }
 };
 
+template <> struct MappingTraits<lld::AbsoluteAtom *> {
+  static void mapping(IO &io, lld::AbsoluteAtom *&atom) {
+    const lld::AbsoluteAtom *atomPtr = atom;
+    MappingTraits<const lld::AbsoluteAtom *>::mapping(io, atomPtr);
+    atom = const_cast<lld::AbsoluteAtom *>(atomPtr);
+  }
+};
+
 } // namespace llvm
 } // namespace yaml
 




More information about the llvm-commits mailing list