[llvm-debuginfo-analyzer] (08a/09) - Memory Management
authorCarlos Alberto Enciso <carlos.alberto.enciso@gmail.com>
Thu, 16 Feb 2023 09:52:50 +0000 (09:52 +0000)
committerCarlos Alberto Enciso <carlos.alberto.enciso@gmail.com>
Thu, 16 Feb 2023 10:15:19 +0000 (10:15 +0000)
llvm-debuginfo-analyzer is a command line tool that processes debug
info contained in a binary file and produces a debug information
format agnostic “Logical View”, which is a high-level semantic
representation of the debug info, independent of the low-level
format.

The code has been divided into the following patches:

1) Interval tree
2) Driver and documentation
3) Logical elements
4) Locations and ranges
5) Select elements
6) Warning and internal options
7) Compare elements
8) ELF Reader
8a) Memory Management
9) CodeView Reader

Full details:

https://discourse.llvm.org/t/llvm-dev-rfc-llvm-dva-debug-information-visual-analyzer/62570

This patch:

This is a high level summary of the changes in this patch.

Memory Management
- Use Bump allocators for memory management.

As the logical elements are only allocated in one pass (debuginfo
parsing) and they are never manipulated/created/destroyed later,
use the SpecificBumpPtrAllocator for the memory management.

Reviewed By: dblaikie, Orlando

Differential Revision: https://reviews.llvm.org/D137933

21 files changed:
llvm/include/llvm/DebugInfo/LogicalView/Core/LVLocation.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVObject.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVReader.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVScope.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVSupport.h
llvm/include/llvm/DebugInfo/LogicalView/Core/LVSymbol.h
llvm/include/llvm/DebugInfo/LogicalView/LVReaderHandler.h
llvm/include/llvm/DebugInfo/LogicalView/Readers/LVBinaryReader.h
llvm/lib/DebugInfo/LogicalView/Core/LVLocation.cpp
llvm/lib/DebugInfo/LogicalView/Core/LVScope.cpp
llvm/lib/DebugInfo/LogicalView/Core/LVSymbol.cpp
llvm/lib/DebugInfo/LogicalView/Core/LVType.cpp
llvm/lib/DebugInfo/LogicalView/LVReaderHandler.cpp
llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp
llvm/lib/DebugInfo/LogicalView/Readers/LVELFReader.cpp
llvm/unittests/DebugInfo/LogicalView/CompareElementsTest.cpp
llvm/unittests/DebugInfo/LogicalView/ELFReaderTest.cpp
llvm/unittests/DebugInfo/LogicalView/LocationRangesTest.cpp
llvm/unittests/DebugInfo/LogicalView/LogicalElementsTest.cpp
llvm/unittests/DebugInfo/LogicalView/SelectElementsTest.cpp
llvm/unittests/DebugInfo/LogicalView/WarningInternalTest.cpp

index 94edd83..dc1df9f 100644 (file)
@@ -172,7 +172,7 @@ public:
 
 class LVLocationSymbol final : public LVLocation {
   // Location descriptors for the active range.
-  LVAutoOperations *Entries = nullptr;
+  std::unique_ptr<LVOperations> Entries;
 
   void updateKind() override;
 
@@ -180,7 +180,7 @@ public:
   LVLocationSymbol() : LVLocation() {}
   LVLocationSymbol(const LVLocationSymbol &) = delete;
   LVLocationSymbol &operator=(const LVLocationSymbol &) = delete;
-  ~LVLocationSymbol() { delete Entries; };
+  ~LVLocationSymbol() = default;
 
   void addObject(LVAddress LowPC, LVAddress HighPC, LVUnsigned SectionOffset,
                  uint64_t LocDescOffset) override;
index a097372..ca429d2 100644 (file)
@@ -74,21 +74,6 @@ using LVSymbolGetFunction = bool (LVSymbol::*)() const;
 using LVTypeSetFunction = void (LVType::*)();
 using LVTypeGetFunction = bool (LVType::*)() const;
 
-// The LVScope class represents a logical scope and uses vectors to store its
-// children, which are pointers to other allocated logical elements (types,
-// symbols, lines, scopes, ranges). On destruction, we have to traverse each
-// vector and destroy its elements. The other case is LVSymbol.
-// These definitions are intended to be used by the LVScope and LVSymbol
-// to support automatic vector cleanup.
-using LVAutoLines = LVAutoSmallVector<LVLine *>;
-using LVAutoLocations = LVAutoSmallVector<LVLocation *>;
-using LVAutoOperations = LVAutoSmallVector<LVOperation *, 8>;
-using LVAutoScopes = LVAutoSmallVector<LVScope *>;
-using LVAutoSymbols = LVAutoSmallVector<LVSymbol *>;
-using LVAutoTypes = LVAutoSmallVector<LVType *>;
-
-// These definitions are intended to be used when the vector will be used
-// just a container, with no automatic destruction.
 using LVElements = SmallVector<LVElement *, 8>;
 using LVLines = SmallVector<LVLine *, 8>;
 using LVLocations = SmallVector<LVLocation *, 8>;
index ed1807c..ff1a41c 100644 (file)
@@ -54,6 +54,9 @@ public:
   raw_fd_ostream &os() { return OutputFile->os(); }
 };
 
+/// The logical reader owns of all the logical elements created during
+/// the debug information parsing. For its creation it uses a specific
+///  bump allocator for each type of logical element.
 class LVReader {
   LVBinaryType BinaryType;
 
@@ -74,6 +77,50 @@ class LVReader {
   Error createSplitFolder();
   bool OutputSplit = false;
 
+// Define a specific bump allocator for the given KIND.
+#define LV_OBJECT_ALLOCATOR(KIND)                                              \
+  llvm::SpecificBumpPtrAllocator<LV##KIND> Allocated##KIND;
+
+  // Lines allocator.
+  LV_OBJECT_ALLOCATOR(Line)
+  LV_OBJECT_ALLOCATOR(LineDebug)
+  LV_OBJECT_ALLOCATOR(LineAssembler)
+
+  // Locations allocator.
+  LV_OBJECT_ALLOCATOR(Location)
+  LV_OBJECT_ALLOCATOR(LocationSymbol)
+
+  // Operations allocator.
+  LV_OBJECT_ALLOCATOR(Operation)
+
+  // Scopes allocator.
+  LV_OBJECT_ALLOCATOR(Scope)
+  LV_OBJECT_ALLOCATOR(ScopeAggregate)
+  LV_OBJECT_ALLOCATOR(ScopeAlias)
+  LV_OBJECT_ALLOCATOR(ScopeArray)
+  LV_OBJECT_ALLOCATOR(ScopeCompileUnit)
+  LV_OBJECT_ALLOCATOR(ScopeEnumeration)
+  LV_OBJECT_ALLOCATOR(ScopeFormalPack)
+  LV_OBJECT_ALLOCATOR(ScopeFunction)
+  LV_OBJECT_ALLOCATOR(ScopeFunctionInlined)
+  LV_OBJECT_ALLOCATOR(ScopeFunctionType)
+  LV_OBJECT_ALLOCATOR(ScopeNamespace)
+  LV_OBJECT_ALLOCATOR(ScopeRoot)
+  LV_OBJECT_ALLOCATOR(ScopeTemplatePack)
+
+  // Symbols allocator.
+  LV_OBJECT_ALLOCATOR(Symbol)
+
+  // Types allocator.
+  LV_OBJECT_ALLOCATOR(Type)
+  LV_OBJECT_ALLOCATOR(TypeDefinition)
+  LV_OBJECT_ALLOCATOR(TypeEnumerator)
+  LV_OBJECT_ALLOCATOR(TypeImport)
+  LV_OBJECT_ALLOCATOR(TypeParam)
+  LV_OBJECT_ALLOCATOR(TypeSubrange)
+
+#undef LV_OBJECT_ALLOCATOR
+
 protected:
   LVScopeRoot *Root = nullptr;
   std::string InputFilename;
@@ -92,7 +139,7 @@ protected:
 
   // Create the Scope Root.
   virtual Error createScopes() {
-    Root = new LVScopeRoot();
+    Root = createScopeRoot();
     Root->setName(getFilename());
     if (options().getAttributeFormat())
       Root->setFileFormatName(FileFormatName);
@@ -129,9 +176,62 @@ public:
         OS(W.getOStream()) {}
   LVReader(const LVReader &) = delete;
   LVReader &operator=(const LVReader &) = delete;
-  virtual ~LVReader() {
-    if (Root)
-      delete Root;
+  virtual ~LVReader() = default;
+
+// Creates a logical object of the given KIND. The signature for the created
+// functions looks like:
+//   ...
+//   LVScope *createScope()
+//   LVScopeRoot *creatScopeRoot()
+//   LVType *createType();
+//   ...
+#define LV_CREATE_OBJECT(KIND)                                                 \
+  LV##KIND *create##KIND() {                                                   \
+    return new (Allocated##KIND.Allocate()) LV##KIND();                        \
+  }
+
+  // Lines creation.
+  LV_CREATE_OBJECT(Line)
+  LV_CREATE_OBJECT(LineDebug)
+  LV_CREATE_OBJECT(LineAssembler)
+
+  // Locations creation.
+  LV_CREATE_OBJECT(Location)
+  LV_CREATE_OBJECT(LocationSymbol)
+
+  // Scopes creation.
+  LV_CREATE_OBJECT(Scope)
+  LV_CREATE_OBJECT(ScopeAggregate)
+  LV_CREATE_OBJECT(ScopeAlias)
+  LV_CREATE_OBJECT(ScopeArray)
+  LV_CREATE_OBJECT(ScopeCompileUnit)
+  LV_CREATE_OBJECT(ScopeEnumeration)
+  LV_CREATE_OBJECT(ScopeFormalPack)
+  LV_CREATE_OBJECT(ScopeFunction)
+  LV_CREATE_OBJECT(ScopeFunctionInlined)
+  LV_CREATE_OBJECT(ScopeFunctionType)
+  LV_CREATE_OBJECT(ScopeNamespace)
+  LV_CREATE_OBJECT(ScopeRoot)
+  LV_CREATE_OBJECT(ScopeTemplatePack)
+
+  // Symbols creation.
+  LV_CREATE_OBJECT(Symbol)
+
+  // Types creation.
+  LV_CREATE_OBJECT(Type)
+  LV_CREATE_OBJECT(TypeDefinition)
+  LV_CREATE_OBJECT(TypeEnumerator)
+  LV_CREATE_OBJECT(TypeImport)
+  LV_CREATE_OBJECT(TypeParam)
+  LV_CREATE_OBJECT(TypeSubrange)
+
+#undef LV_CREATE_OBJECT
+
+  // Operations creation.
+  LVOperation *createOperation(LVSmall OpCode, LVUnsigned Operand1,
+                               LVUnsigned Operand2) {
+    return new (AllocatedOperation.Allocate())
+        LVOperation(OpCode, Operand1, Operand2);
   }
 
   StringRef getFilename(LVObject *Object, size_t Index) const;
index 8204163..4368e93 100644 (file)
@@ -63,12 +63,11 @@ using LVScopeKindSet = std::set<LVScopeKind>;
 using LVScopeDispatch = std::map<LVScopeKind, LVScopeGetFunction>;
 using LVScopeRequest = std::vector<LVScopeGetFunction>;
 
-using LVOffsetList = std::list<LVOffset>;
 using LVOffsetElementMap = std::map<LVOffset, LVElement *>;
-using LVOffsetLinesMap = std::map<LVOffset, LVLines *>;
-using LVOffsetLocationsMap = std::map<LVOffset, LVLocations *>;
+using LVOffsetLinesMap = std::map<LVOffset, LVLines>;
+using LVOffsetLocationsMap = std::map<LVOffset, LVLocations>;
 using LVOffsetSymbolMap = std::map<LVOffset, LVSymbol *>;
-using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsetList *>;
+using LVTagOffsetsMap = std::map<dwarf::Tag, LVOffsets>;
 
 // Class to represent a DWARF Scope.
 class LVScope : public LVElement {
@@ -100,7 +99,8 @@ class LVScope : public LVElement {
   // Calculate coverage factor.
   void calculateCoverage() {
     float CoveragePercentage = 0;
-    LVLocation::calculateCoverage(Ranges, CoverageFactor, CoveragePercentage);
+    LVLocation::calculateCoverage(Ranges.get(), CoverageFactor,
+                                  CoveragePercentage);
   }
 
   // Decide if the scope will be printed, using some conditions given by:
@@ -117,11 +117,11 @@ class LVScope : public LVElement {
 
 protected:
   // Types, Symbols, Scopes, Lines, Locations in this scope.
-  LVAutoTypes *Types = nullptr;
-  LVAutoSymbols *Symbols = nullptr;
-  LVAutoScopes *Scopes = nullptr;
-  LVAutoLines *Lines = nullptr;
-  LVAutoLocations *Ranges = nullptr;
+  std::unique_ptr<LVTypes> Types;
+  std::unique_ptr<LVSymbols> Symbols;
+  std::unique_ptr<LVScopes> Scopes;
+  std::unique_ptr<LVLines> Lines;
+  std::unique_ptr<LVLocations> Ranges;
 
   // Vector of elements (types, scopes and symbols).
   // It is the union of (*Types, *Symbols and *Scopes) to be used for
@@ -129,7 +129,7 @@ protected:
   // - Preserve the order the logical elements are read in.
   // - To have a single container with all the logical elements, when
   //   the traversal does not require any specific element kind.
-  LVElements *Children = nullptr;
+  std::unique_ptr<LVElements> Children;
 
   // Resolve the template parameters/arguments relationship.
   void resolveTemplate();
@@ -150,7 +150,7 @@ public:
   }
   LVScope(const LVScope &) = delete;
   LVScope &operator=(const LVScope &) = delete;
-  virtual ~LVScope();
+  virtual ~LVScope() = default;
 
   static bool classof(const LVElement *Element) {
     return Element->getSubclassID() == LVSubclassID::LV_SCOPE;
@@ -202,12 +202,12 @@ public:
   const char *kind() const override;
 
   // Get the specific children.
-  const LVLines *getLines() const { return Lines; }
-  const LVLocations *getRanges() const { return Ranges; }
-  const LVScopes *getScopes() const { return Scopes; }
-  const LVSymbols *getSymbols() const { return Symbols; }
-  const LVTypes *getTypes() const { return Types; }
-  const LVElements *getChildren() const { return Children; }
+  const LVLines *getLines() const { return Lines.get(); }
+  const LVLocations *getRanges() const { return Ranges.get(); }
+  const LVScopes *getScopes() const { return Scopes.get(); }
+  const LVSymbols *getSymbols() const { return Symbols.get(); }
+  const LVTypes *getTypes() const { return Types.get(); }
+  const LVElements *getChildren() const { return Children.get(); }
 
   void addElement(LVElement *Element);
   void addElement(LVLine *Line);
@@ -456,8 +456,8 @@ class LVScopeCompileUnit final : public LVScope {
                                  LVOffsetLocationsMap *Map) {
     LVOffset Offset = Element->getOffset();
     addInvalidOffset(Offset, Element);
-    addItem<LVOffsetLocationsMap, LVLocations, LVOffset, LVLocation *>(
-        Map, Offset, Location);
+    addItem<LVOffsetLocationsMap, LVOffset, LVLocation *>(Map, Offset,
+                                                          Location);
   }
 
   // Record scope sizes indexed by lexical level.
@@ -489,12 +489,7 @@ public:
   }
   LVScopeCompileUnit(const LVScopeCompileUnit &) = delete;
   LVScopeCompileUnit &operator=(const LVScopeCompileUnit &) = delete;
-  ~LVScopeCompileUnit() {
-    deleteList<LVTagOffsetsMap>(DebugTags);
-    deleteList<LVOffsetLocationsMap>(InvalidLocations);
-    deleteList<LVOffsetLocationsMap>(InvalidRanges);
-    deleteList<LVOffsetLinesMap>(LinesZero);
-  }
+  ~LVScopeCompileUnit() = default;
 
   LVScope *getCompileUnitParent() const override {
     return static_cast<LVScope *>(const_cast<LVScopeCompileUnit *>(this));
index a2274ec..d65ac64 100644 (file)
@@ -31,25 +31,6 @@ namespace logicalview {
 // Returns the unique string pool instance.
 LVStringPool &getStringPool();
 
-template <typename T>
-using TypeIsValid = std::bool_constant<std::is_pointer<T>::value>;
-
-// Utility class to help memory management and perform an automatic cleaning.
-template <typename T, unsigned N = 8>
-class LVAutoSmallVector : public SmallVector<T, N> {
-  static_assert(TypeIsValid<T>::value, "T must be a pointer type");
-
-public:
-  using iterator = typename SmallVector<T, N>::iterator;
-  LVAutoSmallVector() : SmallVector<T, N>::SmallVector() {}
-
-  ~LVAutoSmallVector() {
-    // Destroy the constructed elements in the vector.
-    for (auto *Item : *this)
-      delete Item;
-  }
-};
-
 // Used to record specific characteristics about the objects.
 template <typename T> class LVProperties {
   SmallBitVector Bits = SmallBitVector(static_cast<unsigned>(T::LastEntry) + 1);
@@ -147,25 +128,10 @@ std::string formatAttributes(const StringRef First, Args... Others) {
   return Stream.str();
 }
 
-// Add an item to a map with second being a list.
-template <typename MapType, typename ListType, typename KeyType,
-          typename ValueType>
+// Add an item to a map with second being a small vector.
+template <typename MapType, typename KeyType, typename ValueType>
 void addItem(MapType *Map, KeyType Key, ValueType Value) {
-  ListType *List = nullptr;
-  typename MapType::const_iterator Iter = Map->find(Key);
-  if (Iter != Map->end())
-    List = Iter->second;
-  else {
-    List = new ListType();
-    Map->emplace(Key, List);
-  }
-  List->push_back(Value);
-}
-
-// Delete the map contained list.
-template <typename MapType> void deleteList(MapType &Map) {
-  for (typename MapType::const_reference Entry : Map)
-    delete Entry.second;
+  (*Map)[Key].push_back(Value);
 }
 
 // Double map data structure.
@@ -174,33 +140,26 @@ class LVDoubleMap {
   static_assert(std::is_pointer<ValueType>::value,
                 "ValueType must be a pointer.");
   using LVSecondMapType = std::map<SecondKeyType, ValueType>;
-  using LVFirstMapType = std::map<FirstKeyType, LVSecondMapType *>;
+  using LVFirstMapType =
+      std::map<FirstKeyType, std::unique_ptr<LVSecondMapType>>;
   using LVAuxMapType = std::map<SecondKeyType, FirstKeyType>;
   using LVValueTypes = std::vector<ValueType>;
   LVFirstMapType FirstMap;
   LVAuxMapType AuxMap;
 
 public:
-  LVDoubleMap() = default;
-  ~LVDoubleMap() {
-    for (auto &Entry : FirstMap)
-      delete Entry.second;
-  }
-
   void add(FirstKeyType FirstKey, SecondKeyType SecondKey, ValueType Value) {
-    LVSecondMapType *SecondMap = nullptr;
     typename LVFirstMapType::iterator FirstIter = FirstMap.find(FirstKey);
     if (FirstIter == FirstMap.end()) {
-      SecondMap = new LVSecondMapType();
-      FirstMap.emplace(FirstKey, SecondMap);
+      auto SecondMapSP = std::make_unique<LVSecondMapType>();
+      SecondMapSP->emplace(SecondKey, Value);
+      FirstMap.emplace(FirstKey, std::move(SecondMapSP));
     } else {
-      SecondMap = FirstIter->second;
+      LVSecondMapType *SecondMap = FirstIter->second.get();
+      if (SecondMap->find(SecondKey) == SecondMap->end())
+        SecondMap->emplace(SecondKey, Value);
     }
 
-    assert(SecondMap && "SecondMap is null.");
-    if (SecondMap && SecondMap->find(SecondKey) == SecondMap->end())
-      SecondMap->emplace(SecondKey, Value);
-
     typename LVAuxMapType::iterator AuxIter = AuxMap.find(SecondKey);
     if (AuxIter == AuxMap.end()) {
       AuxMap.emplace(SecondKey, FirstKey);
@@ -212,8 +171,7 @@ public:
     if (FirstIter == FirstMap.end())
       return nullptr;
 
-    LVSecondMapType *SecondMap = FirstIter->second;
-    return SecondMap;
+    return FirstIter->second.get();
   }
 
   ValueType find(FirstKeyType FirstKey, SecondKeyType SecondKey) const {
@@ -239,8 +197,8 @@ public:
     if (FirstMap.empty())
       return Values;
     for (typename LVFirstMapType::const_reference FirstEntry : FirstMap) {
-      LVSecondMapType *SecondMap = FirstEntry.second;
-      for (typename LVSecondMapType::const_reference SecondEntry : *SecondMap)
+      LVSecondMapType &SecondMap = *FirstEntry.second;
+      for (typename LVSecondMapType::const_reference SecondEntry : SecondMap)
         Values.push_back(SecondEntry.second);
     }
     return Values;
index b9628e3..4b2a910 100644 (file)
@@ -46,7 +46,7 @@ class LVSymbol final : public LVElement {
 
   // Reference to DW_AT_specification, DW_AT_abstract_origin attribute.
   LVSymbol *Reference = nullptr;
-  LVAutoLocations *Locations = nullptr;
+  std::unique_ptr<LVLocations> Locations;
   LVLocation *CurrentLocation = nullptr;
 
   // Bitfields length.
@@ -60,8 +60,8 @@ class LVSymbol final : public LVElement {
   float CoveragePercentage = 0;
 
   // Add a location gap into the location list.
-  LVAutoLocations::iterator addLocationGap(LVAutoLocations::iterator Pos,
-                                           LVAddress LowPC, LVAddress HighPC);
+  LVLocations::iterator addLocationGap(LVLocations::iterator Pos,
+                                       LVAddress LowPC, LVAddress HighPC);
 
   // Find the current symbol in the given 'Targets'.
   LVSymbol *findIn(const LVSymbols *Targets) const;
@@ -73,7 +73,7 @@ public:
   }
   LVSymbol(const LVSymbol &) = delete;
   LVSymbol &operator=(const LVSymbol &) = delete;
-  ~LVSymbol() { delete Locations; }
+  ~LVSymbol() = default;
 
   static bool classof(const LVElement *Element) {
     return Element->getSubclassID() == LVSubclassID::LV_SYMBOL;
index 3030e9f..9f5e807 100644 (file)
@@ -27,7 +27,7 @@
 namespace llvm {
 namespace logicalview {
 
-using LVReaders = std::vector<LVReader *>;
+using LVReaders = std::vector<std::unique_ptr<LVReader>>;
 using ArgVector = std::vector<std::string>;
 using PdbOrObj = PointerUnion<object::ObjectFile *, pdb::PDBFile *>;
 
@@ -45,7 +45,6 @@ class LVReaderHandler {
   LVReaders TheReaders;
 
   Error createReaders();
-  void destroyReaders();
   Error printReaders();
   Error compareReaders();
 
@@ -72,20 +71,18 @@ public:
   }
   LVReaderHandler(const LVReaderHandler &) = delete;
   LVReaderHandler &operator=(const LVReaderHandler &) = delete;
-  ~LVReaderHandler() { destroyReaders(); }
 
   Error createReader(StringRef Filename, LVReaders &Readers) {
     return handleFile(Readers, Filename);
   }
   Error process();
 
-  Expected<LVReader *> createReader(StringRef Pathname) {
+  Expected<std::unique_ptr<LVReader>> createReader(StringRef Pathname) {
     LVReaders Readers;
     if (Error Err = createReader(Pathname, Readers))
       return std::move(Err);
-    return Readers[0];
+    return std::move(Readers[0]);
   }
-  void deleteReader(LVReader *Reader) { delete Reader; }
 
   void print(raw_ostream &OS) const;
 
index 8c3cce9..4b2dc66 100644 (file)
@@ -89,7 +89,7 @@ class LVBinaryReader : public LVReader {
   // Scopes with ranges for current compile unit. It is used to find a line
   // giving its exact or closest address. To support comdat functions, all
   // addresses for the same section are recorded in the same map.
-  using LVSectionRanges = std::map<LVSectionIndex, LVRange *>;
+  using LVSectionRanges = std::map<LVSectionIndex, std::unique_ptr<LVRange>>;
   LVSectionRanges SectionRanges;
 
   // Image base and virtual address for Executable file.
@@ -100,6 +100,8 @@ class LVBinaryReader : public LVReader {
   using LVSections = std::map<LVSectionIndex, object::SectionRef>;
   LVSections Sections;
 
+  std::vector<std::unique_ptr<LVLines>> DiscoveredLines;
+
 protected:
   // It contains the LVLineDebug elements representing the logical lines for
   // the current compile unit, created by parsing the debug line section.
@@ -149,7 +151,7 @@ public:
       : LVReader(Filename, FileFormatName, W, BinaryType) {}
   LVBinaryReader(const LVBinaryReader &) = delete;
   LVBinaryReader &operator=(const LVBinaryReader &) = delete;
-  virtual ~LVBinaryReader();
+  virtual ~LVBinaryReader() = default;
 
   void addToSymbolTable(StringRef Name, LVScope *Function,
                         LVSectionIndex SectionIndex = 0);
index 115b903..e11e56c 100644 (file)
@@ -579,8 +579,8 @@ void LVLocationSymbol::addObject(LVAddress LowPC, LVAddress HighPC,
 void LVLocationSymbol::addObject(LVSmall Opcode, LVUnsigned Operand1,
                                  LVUnsigned Operand2) {
   if (!Entries)
-    Entries = new LVAutoOperations();
-  Entries->emplace_back(new LVOperation(Opcode, Operand1, Operand2));
+    Entries = std::make_unique<LVOperations>();
+  Entries->push_back(getReader().createOperation(Opcode, Operand1, Operand2));
 }
 
 // Based on the DWARF attribute, define the location kind.
@@ -606,8 +606,7 @@ void LVLocation::setKind() {
 void LVLocationSymbol::updateKind() {
   // Update the location type for simple ones.
   if (Entries && Entries->size() == 1) {
-    LVOperation *Operation = Entries->front();
-    if (dwarf::DW_OP_fbreg == Operation->getOpcode())
+    if (dwarf::DW_OP_fbreg == Entries->front()->getOpcode())
       setIsStackOffset();
   }
 }
index fb503f3..2fc97cc 100644 (file)
@@ -45,15 +45,6 @@ const char *const KindUnion = "Union";
 //===----------------------------------------------------------------------===//
 // DWARF lexical block, such as: namespace, function, compile unit, module, etc.
 //===----------------------------------------------------------------------===//
-LVScope::~LVScope() {
-  delete Types;
-  delete Symbols;
-  delete Scopes;
-  delete Lines;
-  delete Ranges;
-  delete Children;
-}
-
 // Return a string representation for the scope kind.
 const char *LVScope::kind() const {
   const char *Kind = KindUndefined;
@@ -114,7 +105,7 @@ LVScopeDispatch LVScope::Dispatch = {
 
 void LVScope::addToChildren(LVElement *Element) {
   if (!Children)
-    Children = new LVElements();
+    Children = std::make_unique<LVElements>();
   Children->push_back(Element);
 }
 
@@ -137,7 +128,7 @@ void LVScope::addElement(LVLine *Line) {
   assert(Line && "Invalid line.");
   assert(!Line->getParent() && "Line already inserted");
   if (!Lines)
-    Lines = new LVAutoLines();
+    Lines = std::make_unique<LVLines>();
 
   // Add it to parent.
   Lines->push_back(Line);
@@ -161,7 +152,7 @@ void LVScope::addObject(LVLocation *Location) {
   assert(Location && "Invalid location.");
   assert(!Location->getParent() && "Location already inserted");
   if (!Ranges)
-    Ranges = new LVAutoLocations();
+    Ranges = std::make_unique<LVLocations>();
 
   // Add it to parent.
   Location->setParent(this);
@@ -176,7 +167,7 @@ void LVScope::addElement(LVScope *Scope) {
   assert(Scope && "Invalid scope.");
   assert(!Scope->getParent() && "Scope already inserted");
   if (!Scopes)
-    Scopes = new LVAutoScopes();
+    Scopes = std::make_unique<LVScopes>();
 
   // Add it to parent.
   Scopes->push_back(Scope);
@@ -203,7 +194,7 @@ void LVScope::addElement(LVSymbol *Symbol) {
   assert(Symbol && "Invalid symbol.");
   assert(!Symbol->getParent() && "Symbol already inserted");
   if (!Symbols)
-    Symbols = new LVAutoSymbols();
+    Symbols = std::make_unique<LVSymbols>();
 
   // Add it to parent.
   Symbols->push_back(Symbol);
@@ -230,7 +221,7 @@ void LVScope::addElement(LVType *Type) {
   assert(Type && "Invalid type.");
   assert(!Type->getParent() && "Type already inserted");
   if (!Types)
-    Types = new LVAutoTypes();
+    Types = std::make_unique<LVTypes>();
 
   // Add it to parent.
   Types->push_back(Type);
@@ -255,7 +246,7 @@ void LVScope::addElement(LVType *Type) {
 // Add a pair of ranges.
 void LVScope::addObject(LVAddress LowerAddress, LVAddress UpperAddress) {
   // Pack the ranges into a Location object.
-  LVLocation *Location = new LVLocation();
+  LVLocation *Location = getReader().createLocation();
   Location->setLowerAddress(LowerAddress);
   Location->setUpperAddress(UpperAddress);
   Location->setIsAddressRange();
@@ -341,7 +332,7 @@ void LVScope::addMissingElements(LVScope *Reference) {
       // information that is incorrect for the element to be inserted.
       // As the symbol being added does not exist in the debug section,
       // use its parent scope offset, to indicate its DIE location.
-      LVSymbol *Symbol = new LVSymbol();
+      LVSymbol *Symbol = getReader().createSymbol();
       addElement(Symbol);
       Symbol->setOffset(getOffset());
       Symbol->setIsOptimized();
@@ -690,7 +681,7 @@ void LVScope::sort() {
   if (SortFunction) {
     std::function<void(LVScope * Parent, LVSortFunction SortFunction)> Sort =
         [&](LVScope *Parent, LVSortFunction SortFunction) {
-          auto Traverse = [&](auto *Set, LVSortFunction SortFunction) {
+          auto Traverse = [&](auto &Set, LVSortFunction SortFunction) {
             if (Set)
               std::stable_sort(Set->begin(), Set->end(), SortFunction);
           };
@@ -877,7 +868,7 @@ bool LVScope::equalNumberOfChildren(const LVScope *Scope) const {
 }
 
 void LVScope::markMissingParents(const LVScope *Target, bool TraverseChildren) {
-  auto SetCompareState = [&](auto *Container) {
+  auto SetCompareState = [&](auto &Container) {
     if (Container)
       for (auto *Entry : *Container)
         Entry->setIsInCompare();
@@ -1356,8 +1347,7 @@ void LVScopeCompileUnit::addedElement(LVType *Type) {
 
 // Record unsuported DWARF tags.
 void LVScopeCompileUnit::addDebugTag(dwarf::Tag Target, LVOffset Offset) {
-  addItem<LVTagOffsetsMap, LVOffsetList, dwarf::Tag, LVOffset>(&DebugTags,
-                                                               Target, Offset);
+  addItem<LVTagOffsetsMap, dwarf::Tag, LVOffset>(&DebugTags, Target, Offset);
 }
 
 // Record elements with invalid offsets.
@@ -1390,8 +1380,7 @@ void LVScopeCompileUnit::addLineZero(LVLine *Line) {
   LVScope *Scope = Line->getParentScope();
   LVOffset Offset = Scope->getOffset();
   addInvalidOffset(Offset, Scope);
-  addItem<LVOffsetLinesMap, LVLines, LVOffset, LVLine *>(&LinesZero, Offset,
-                                                         Line);
+  addItem<LVOffsetLinesMap, LVOffset, LVLine *>(&LinesZero, Offset, Line);
 }
 
 void LVScopeCompileUnit::printLocalNames(raw_ostream &OS, bool Full) const {
@@ -1481,7 +1470,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
     PrintHeader(Header);
     for (LVOffsetLocationsMap::const_reference Entry : Map) {
       PrintElement(WarningOffsets, Entry.first);
-      for (const LVLocation *Location : *Entry.second)
+      for (const LVLocation *Location : Entry.second)
         OS << hexSquareString(Location->getOffset()) << " "
            << Location->getIntervalInfo() << "\n";
     }
@@ -1494,7 +1483,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
       OS << format("\n0x%02x", (unsigned)Entry.first) << ", "
          << dwarf::TagString(Entry.first) << "\n";
       unsigned Count = 0;
-      for (const LVOffset &Offset : *Entry.second)
+      for (const LVOffset &Offset : Entry.second)
         PrintOffset(Count, Offset);
       OS << "\n";
     }
@@ -1519,7 +1508,7 @@ void LVScopeCompileUnit::printWarnings(raw_ostream &OS, bool Full) const {
     for (LVOffsetLinesMap::const_reference Entry : LinesZero) {
       PrintElement(WarningOffsets, Entry.first);
       unsigned Count = 0;
-      for (const LVLine *Line : *Entry.second)
+      for (const LVLine *Line : Entry.second)
         PrintOffset(Count, Line->getOffset());
       OS << "\n";
     }
index 82633fb..7e86a2f 100644 (file)
@@ -66,10 +66,10 @@ void LVSymbol::addLocation(dwarf::Attribute Attr, LVAddress LowPC,
                            LVAddress HighPC, LVUnsigned SectionOffset,
                            uint64_t LocDescOffset, bool CallSiteLocation) {
   if (!Locations)
-    Locations = new LVAutoLocations();
+    Locations = std::make_unique<LVLocations>();
 
   // Create the location entry.
-  CurrentLocation = new LVLocationSymbol();
+  CurrentLocation = getReader().createLocationSymbol();
   CurrentLocation->setParent(this);
   CurrentLocation->setAttr(Attr);
   if (CallSiteLocation)
@@ -105,7 +105,7 @@ LVLocations::iterator LVSymbol::addLocationGap(LVLocations::iterator Pos,
                                                LVAddress LowPC,
                                                LVAddress HighPC) {
   // Create a location entry for the gap.
-  LVLocation *Gap = new LVLocationSymbol();
+  LVLocation *Gap = getReader().createLocationSymbol();
   Gap->setParent(this);
   Gap->setAttr(dwarf::DW_AT_location);
   Gap->addObject(LowPC, HighPC,
@@ -190,7 +190,7 @@ void LVSymbol::getLocations(LVLocations &LocationList) const {
 
 // Calculate coverage factor.
 void LVSymbol::calculateCoverage() {
-  if (!LVLocation::calculateCoverage(Locations, CoverageFactor,
+  if (!LVLocation::calculateCoverage(Locations.get(), CoverageFactor,
                                      CoveragePercentage)) {
     LVScope *Parent = getParentScope();
     if (Parent->getIsInlinedFunction()) {
@@ -444,6 +444,6 @@ void LVSymbol::printExtra(raw_ostream &OS, bool Full) const {
       Reference->printReference(OS, Full, const_cast<LVSymbol *>(this));
 
     // Print location information.
-    LVLocation::print(Locations, OS, Full);
+    LVLocation::print(Locations.get(), OS, Full);
   }
 }
index 3d32c34..de71e09 100644 (file)
@@ -253,16 +253,10 @@ void LVType::getParameters(const LVTypes *Types, LVTypes *TypesParam,
     if (!Type->getIsTemplateParam())
       continue;
     if (options().getAttributeArgument()) {
-      LVScope *Scope = nullptr;
       if (Type->getIsKindType())
-        Type = Type->getTypeAsType();
-      else {
-        if (Type->getIsKindScope()) {
-          Scope = Type->getTypeAsScope();
-          Type = nullptr;
-        }
-      }
-      Type ? TypesParam->push_back(Type) : ScopesParam->push_back(Scope);
+        TypesParam->push_back(Type->getTypeAsType());
+      else if (Type->getIsKindScope())
+        ScopesParam->push_back(Type->getTypeAsScope());
     } else
       TypesParam->push_back(Type);
   }
index 35dc30f..65633f2 100644 (file)
@@ -32,31 +32,26 @@ Error LVReaderHandler::process() {
   return Error::success();
 }
 
-void LVReaderHandler::destroyReaders() {
-  LLVM_DEBUG(dbgs() << "destroyReaders\n");
-  for (const LVReader *Reader : TheReaders)
-    delete Reader;
-}
-
 Error LVReaderHandler::createReader(StringRef Filename, LVReaders &Readers,
                                     PdbOrObj &Input, StringRef FileFormatName,
                                     StringRef ExePath) {
-  auto CreateOneReader = [&]() -> LVReader * {
+  auto CreateOneReader = [&]() -> std::unique_ptr<LVReader> {
     if (Input.is<ObjectFile *>()) {
       ObjectFile &Obj = *Input.get<ObjectFile *>();
       if (Obj.isELF() || Obj.isMachO())
-        return new LVELFReader(Filename, FileFormatName, Obj, W);
+        return std::make_unique<LVELFReader>(Filename, FileFormatName, Obj, W);
     }
     return nullptr;
   };
 
-  LVReader *Reader = CreateOneReader();
-  if (!Reader)
+  std::unique_ptr<LVReader> ReaderObj = CreateOneReader();
+  if (!ReaderObj)
     return createStringError(errc::invalid_argument,
                              "unable to create reader for: '%s'",
                              Filename.str().c_str());
 
-  Readers.push_back(Reader);
+  LVReader *Reader = ReaderObj.get();
+  Readers.emplace_back(std::move(ReaderObj));
   return Reader->doLoad();
 }
 
@@ -158,7 +153,9 @@ Error LVReaderHandler::createReaders() {
     LVReaders Readers;
     if (Error Err = createReader(Object, Readers))
       return Err;
-    TheReaders.insert(TheReaders.end(), Readers.begin(), Readers.end());
+    TheReaders.insert(TheReaders.end(),
+                      std::make_move_iterator(Readers.begin()),
+                      std::make_move_iterator(Readers.end()));
   }
 
   return Error::success();
@@ -167,7 +164,7 @@ Error LVReaderHandler::createReaders() {
 Error LVReaderHandler::printReaders() {
   LLVM_DEBUG(dbgs() << "printReaders\n");
   if (options().getPrintExecute())
-    for (LVReader *Reader : TheReaders)
+    for (const std::unique_ptr<LVReader> &Reader : TheReaders)
       if (Error Err = Reader->doPrint())
         return Err;
 
@@ -182,7 +179,8 @@ Error LVReaderHandler::compareReaders() {
     size_t ViewPairs = ReadersCount / 2;
     LVCompare Compare(OS);
     for (size_t Pair = 0, Index = 0; Pair < ViewPairs; ++Pair) {
-      if (Error Err = Compare.execute(TheReaders[Index], TheReaders[Index + 1]))
+      if (Error Err = Compare.execute(TheReaders[Index].get(),
+                                      TheReaders[Index + 1].get()))
         return Err;
       Index += 2;
     }
index b654c62..1fb5c4a 100644 (file)
@@ -297,29 +297,16 @@ void LVBinaryReader::addSectionRange(LVSectionIndex SectionIndex,
 }
 
 LVRange *LVBinaryReader::getSectionRanges(LVSectionIndex SectionIndex) {
-  LVRange *Range = nullptr;
   // Check if we already have a mapping for this section index.
   LVSectionRanges::iterator IterSection = SectionRanges.find(SectionIndex);
-  if (IterSection == SectionRanges.end()) {
-    Range = new LVRange();
-    SectionRanges.emplace(SectionIndex, Range);
-  } else {
-    Range = IterSection->second;
-  }
+  if (IterSection == SectionRanges.end())
+    IterSection =
+        SectionRanges.emplace(SectionIndex, std::make_unique<LVRange>()).first;
+  LVRange *Range = IterSection->second.get();
   assert(Range && "Range is null.");
   return Range;
 }
 
-LVBinaryReader::~LVBinaryReader() {
-  // Delete the lines created by 'createInstructions'.
-  std::vector<LVLines *> AllInstructionLines = ScopeInstructions.find();
-  for (LVLines *Entry : AllInstructionLines)
-    delete Entry;
-  // Delete the ranges created by 'getSectionRanges'.
-  for (LVSectionRanges::reference Entry : SectionRanges)
-    delete Entry.second;
-}
-
 Error LVBinaryReader::createInstructions(LVScope *Scope,
                                          LVSectionIndex SectionIndex,
                                          const LVNameInfo &NameInfo) {
@@ -380,7 +367,9 @@ Error LVBinaryReader::createInstructions(LVScope *Scope,
 
   // Address for first instruction line.
   LVAddress FirstAddress = Address;
-  LVLines *Instructions = new LVLines();
+  auto InstructionsSP = std::make_unique<LVLines>();
+  LVLines &Instructions = *InstructionsSP;
+  DiscoveredLines.emplace_back(std::move(InstructionsSP));
 
   while (Begin < End) {
     MCInst Instruction;
@@ -422,10 +411,10 @@ Error LVBinaryReader::createInstructions(LVScope *Scope,
       // the 'processLines()' function will move each created logical line
       // to its enclosing logical scope, using the debug ranges information
       // and they will be released when its scope parent is deleted.
-      LVLineAssembler *Line = new LVLineAssembler();
+      LVLineAssembler *Line = createLineAssembler();
       Line->setAddress(Address);
       Line->setName(StringRef(Stream.str()).trim());
-      Instructions->push_back(Line);
+      Instructions.push_back(Line);
       break;
     }
     }
@@ -439,15 +428,15 @@ Error LVBinaryReader::createInstructions(LVScope *Scope,
            << " Scope DIE: " << hexValue(Scope->getOffset()) << "\n"
            << "Address: " << hexValue(FirstAddress)
            << format(" - Collected instructions lines: %d\n",
-                     Instructions->size());
-    for (const LVLine *Line : *Instructions)
+                     Instructions.size());
+    for (const LVLine *Line : Instructions)
       dbgs() << format_decimal(++Index, 5) << ": "
              << hexValue(Line->getOffset()) << ", (" << Line->getName()
              << ")\n";
   });
 
   // The scope in the assembler names is linked to its own instructions.
-  ScopeInstructions.add(SectionIndex, Scope, Instructions);
+  ScopeInstructions.add(SectionIndex, Scope, &Instructions);
   AssemblerMappings.add(SectionIndex, FirstAddress, Scope);
 
   return Error::success();
index 7746bc5..8826603 100644 (file)
@@ -57,182 +57,182 @@ LVElement *LVELFReader::createElement(dwarf::Tag Tag) {
   switch (Tag) {
   // Types.
   case dwarf::DW_TAG_base_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsBase();
     if (options().getAttributeBase())
       CurrentType->setIncludeInPrint();
     return CurrentType;
   case dwarf::DW_TAG_const_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsConst();
     CurrentType->setName("const");
     return CurrentType;
   case dwarf::DW_TAG_enumerator:
-    CurrentType = new LVTypeEnumerator();
+    CurrentType = createTypeEnumerator();
     return CurrentType;
   case dwarf::DW_TAG_imported_declaration:
-    CurrentType = new LVTypeImport();
+    CurrentType = createTypeImport();
     CurrentType->setIsImportDeclaration();
     return CurrentType;
   case dwarf::DW_TAG_imported_module:
-    CurrentType = new LVTypeImport();
+    CurrentType = createTypeImport();
     CurrentType->setIsImportModule();
     return CurrentType;
   case dwarf::DW_TAG_pointer_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsPointer();
     CurrentType->setName("*");
     return CurrentType;
   case dwarf::DW_TAG_ptr_to_member_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsPointerMember();
     CurrentType->setName("*");
     return CurrentType;
   case dwarf::DW_TAG_reference_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsReference();
     CurrentType->setName("&");
     return CurrentType;
   case dwarf::DW_TAG_restrict_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsRestrict();
     CurrentType->setName("restrict");
     return CurrentType;
   case dwarf::DW_TAG_rvalue_reference_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsRvalueReference();
     CurrentType->setName("&&");
     return CurrentType;
   case dwarf::DW_TAG_subrange_type:
-    CurrentType = new LVTypeSubrange();
+    CurrentType = createTypeSubrange();
     return CurrentType;
   case dwarf::DW_TAG_template_value_parameter:
-    CurrentType = new LVTypeParam();
+    CurrentType = createTypeParam();
     CurrentType->setIsTemplateValueParam();
     return CurrentType;
   case dwarf::DW_TAG_template_type_parameter:
-    CurrentType = new LVTypeParam();
+    CurrentType = createTypeParam();
     CurrentType->setIsTemplateTypeParam();
     return CurrentType;
   case dwarf::DW_TAG_GNU_template_template_param:
-    CurrentType = new LVTypeParam();
+    CurrentType = createTypeParam();
     CurrentType->setIsTemplateTemplateParam();
     return CurrentType;
   case dwarf::DW_TAG_typedef:
-    CurrentType = new LVTypeDefinition();
+    CurrentType = createTypeDefinition();
     return CurrentType;
   case dwarf::DW_TAG_unspecified_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsUnspecified();
     return CurrentType;
   case dwarf::DW_TAG_volatile_type:
-    CurrentType = new LVType();
+    CurrentType = createType();
     CurrentType->setIsVolatile();
     CurrentType->setName("volatile");
     return CurrentType;
 
   // Symbols.
   case dwarf::DW_TAG_formal_parameter:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsParameter();
     return CurrentSymbol;
   case dwarf::DW_TAG_unspecified_parameters:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsUnspecified();
     CurrentSymbol->setName("...");
     return CurrentSymbol;
   case dwarf::DW_TAG_member:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsMember();
     return CurrentSymbol;
   case dwarf::DW_TAG_variable:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsVariable();
     return CurrentSymbol;
   case dwarf::DW_TAG_inheritance:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsInheritance();
     return CurrentSymbol;
   case dwarf::DW_TAG_call_site_parameter:
   case dwarf::DW_TAG_GNU_call_site_parameter:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsCallSiteParameter();
     return CurrentSymbol;
   case dwarf::DW_TAG_constant:
-    CurrentSymbol = new LVSymbol();
+    CurrentSymbol = createSymbol();
     CurrentSymbol->setIsConstant();
     return CurrentSymbol;
 
   // Scopes.
   case dwarf::DW_TAG_catch_block:
-    CurrentScope = new LVScope();
+    CurrentScope = createScope();
     CurrentScope->setIsCatchBlock();
     return CurrentScope;
   case dwarf::DW_TAG_lexical_block:
-    CurrentScope = new LVScope();
+    CurrentScope = createScope();
     CurrentScope->setIsLexicalBlock();
     return CurrentScope;
   case dwarf::DW_TAG_try_block:
-    CurrentScope = new LVScope();
+    CurrentScope = createScope();
     CurrentScope->setIsTryBlock();
     return CurrentScope;
   case dwarf::DW_TAG_compile_unit:
   case dwarf::DW_TAG_skeleton_unit:
-    CurrentScope = new LVScopeCompileUnit();
+    CurrentScope = createScopeCompileUnit();
     CompileUnit = static_cast<LVScopeCompileUnit *>(CurrentScope);
     return CurrentScope;
   case dwarf::DW_TAG_inlined_subroutine:
-    CurrentScope = new LVScopeFunctionInlined();
+    CurrentScope = createScopeFunctionInlined();
     return CurrentScope;
   case dwarf::DW_TAG_namespace:
-    CurrentScope = new LVScopeNamespace();
+    CurrentScope = createScopeNamespace();
     return CurrentScope;
   case dwarf::DW_TAG_template_alias:
-    CurrentScope = new LVScopeAlias();
+    CurrentScope = createScopeAlias();
     return CurrentScope;
   case dwarf::DW_TAG_array_type:
-    CurrentScope = new LVScopeArray();
+    CurrentScope = createScopeArray();
     return CurrentScope;
   case dwarf::DW_TAG_call_site:
   case dwarf::DW_TAG_GNU_call_site:
-    CurrentScope = new LVScopeFunction();
+    CurrentScope = createScopeFunction();
     CurrentScope->setIsCallSite();
     return CurrentScope;
   case dwarf::DW_TAG_entry_point:
-    CurrentScope = new LVScopeFunction();
+    CurrentScope = createScopeFunction();
     CurrentScope->setIsEntryPoint();
     return CurrentScope;
   case dwarf::DW_TAG_subprogram:
-    CurrentScope = new LVScopeFunction();
+    CurrentScope = createScopeFunction();
     CurrentScope->setIsSubprogram();
     return CurrentScope;
   case dwarf::DW_TAG_subroutine_type:
-    CurrentScope = new LVScopeFunctionType();
+    CurrentScope = createScopeFunctionType();
     return CurrentScope;
   case dwarf::DW_TAG_label:
-    CurrentScope = new LVScopeFunction();
+    CurrentScope = createScopeFunction();
     CurrentScope->setIsLabel();
     return CurrentScope;
   case dwarf::DW_TAG_class_type:
-    CurrentScope = new LVScopeAggregate();
+    CurrentScope = createScopeAggregate();
     CurrentScope->setIsClass();
     return CurrentScope;
   case dwarf::DW_TAG_structure_type:
-    CurrentScope = new LVScopeAggregate();
+    CurrentScope = createScopeAggregate();
     CurrentScope->setIsStructure();
     return CurrentScope;
   case dwarf::DW_TAG_union_type:
-    CurrentScope = new LVScopeAggregate();
+    CurrentScope = createScopeAggregate();
     CurrentScope->setIsUnion();
     return CurrentScope;
   case dwarf::DW_TAG_enumeration_type:
-    CurrentScope = new LVScopeEnumeration();
+    CurrentScope = createScopeEnumeration();
     return CurrentScope;
   case dwarf::DW_TAG_GNU_formal_parameter_pack:
-    CurrentScope = new LVScopeFormalPack();
+    CurrentScope = createScopeFormalPack();
     return CurrentScope;
   case dwarf::DW_TAG_GNU_template_parameter_pack:
-    CurrentScope = new LVScopeTemplatePack();
+    CurrentScope = createScopeTemplatePack();
     return CurrentScope;
   default:
     // Collect TAGs not implemented.
@@ -733,7 +733,7 @@ void LVELFReader::createLineAndFileRecords(
       // the 'processLines()' function will move each created logical line
       // to its enclosing logical scope, using the debug ranges information
       // and they will be released when its scope parent is deleted.
-      LVLineDebug *Line = new LVLineDebug();
+      LVLineDebug *Line = createLineDebug();
       CULines.push_back(Line);
       Line->setAddress(Row.Address.Address);
       Line->setFilename(
index 06da5eb..e9c1fba 100644 (file)
@@ -26,9 +26,10 @@ namespace {
 //===----------------------------------------------------------------------===//
 // Basic Reader functionality.
 class ReaderTestCompare : public LVReader {
-  // Elements created but not added to any logical scope. They are
-  // deleted when the logical Reader is destroyed.
-  LVAutoSmallVector<LVElement *> OrphanElements;
+#define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION)                        \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);                                                \
+  VARIABLE->SET_FUNCTION();
 
 public:
   // Types.
@@ -66,14 +67,6 @@ public:
 
 protected:
   void add(LVScope *Parent, LVElement *Element);
-  template <typename T, typename F> T *create(F Function) {
-    // 'Function' will update a specific kind of the logical element to
-    // have the ability of kind selection.
-    T *Element = new (std::nothrow) T();
-    EXPECT_NE(Element, nullptr);
-    (Element->*Function)();
-    return Element;
-  }
   void set(LVElement *Element, StringRef Name, LVOffset Offset,
            uint32_t LineNumber = 0, LVElement *Type = nullptr);
 
@@ -116,54 +109,38 @@ void ReaderTestCompare::createElements() {
   ASSERT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
-  UnsignedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
-  GlobalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
-  LocalType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
-  NestedType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
-  EnumeratorOne =
-      create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
-  EnumeratorTwo =
-      create<LVTypeEnumerator, LVTypeSetFunction>(&LVType::setIsEnumerator);
-  TypeDefinitionOne =
-      create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
-  TypeDefinitionTwo =
-      create<LVTypeDefinition, LVTypeSetFunction>(&LVType::setIsTypedef);
+  CREATE(IntegerType, createType, setIsBase);
+  CREATE(UnsignedType, createType, setIsBase);
+  CREATE(GlobalType, createType, setIsBase);
+  CREATE(LocalType, createType, setIsBase);
+  CREATE(NestedType, createType, setIsBase);
+  CREATE(EnumeratorOne, createTypeEnumerator, setIsEnumerator);
+  CREATE(EnumeratorTwo, createTypeEnumerator, setIsEnumerator);
+  CREATE(TypeDefinitionOne, createTypeDefinition, setIsTypedef);
+  CREATE(TypeDefinitionTwo, createTypeDefinition, setIsTypedef);
 
   // Create the logical scopes.
-  NestedScope =
-      create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
-  InnerScope = create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
-  Aggregate =
-      create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
-  CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
-      &LVScope::setIsCompileUnit);
-  Enumeration = create<LVScopeEnumeration, LVScopeSetFunction>(
-      &LVScope::setIsEnumeration);
-  FunctionOne =
-      create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
-  FunctionTwo =
-      create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
-  Namespace =
-      create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
+  CREATE(NestedScope, createScope, setIsLexicalBlock);
+  CREATE(InnerScope, createScope, setIsLexicalBlock);
+  CREATE(Aggregate, createScopeAggregate, setIsAggregate);
+  CREATE(CompileUnit, createScopeCompileUnit, setIsCompileUnit);
+  CREATE(Enumeration, createScopeEnumeration, setIsEnumeration);
+  CREATE(FunctionOne, createScopeFunction, setIsFunction);
+  CREATE(FunctionTwo, createScopeFunction, setIsFunction);
+  CREATE(Namespace, createScopeNamespace, setIsNamespace);
 
   // Create the logical symbols.
-  GlobalVariable =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
-  LocalVariable =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
-  ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
-  NestedVariable =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
-  ParameterOne =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
-  ParameterTwo =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
+  CREATE(GlobalVariable, createSymbol, setIsVariable);
+  CREATE(LocalVariable, createSymbol, setIsVariable);
+  CREATE(ClassMember, createSymbol, setIsMember);
+  CREATE(NestedVariable, createSymbol, setIsVariable);
+  CREATE(ParameterOne, createSymbol, setIsParameter);
+  CREATE(ParameterTwo, createSymbol, setIsParameter);
 
   // Create the logical lines.
-  LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
-  LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
-  LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
+  CREATE(LineOne, createLine, setIsLineDebug);
+  CREATE(LineTwo, createLine, setIsLineDebug);
+  CREATE(LineThree, createLine, setIsLineDebug);
 }
 
 // Reference Reader:              Target Reader:
@@ -203,8 +180,6 @@ void ReaderTestCompare::addElements(bool IsReference, bool IsTarget) {
   auto Insert = [&](bool Insert, auto *Parent, auto *Child) {
     if (Insert)
       add(Parent, Child);
-    else
-      OrphanElements.push_back(Child);
   };
 
   setCompileUnit(CompileUnit);
index 8af3050..f6db28a 100644 (file)
@@ -47,15 +47,16 @@ LVScopeCompileUnit *getFirstCompileUnit(LVScopeRoot *Root) {
 }
 
 // Helper function to create a reader.
-LVReader *createReader(LVReaderHandler &ReaderHandler,
-                       SmallString<128> &InputsDir, StringRef Filename) {
+std::unique_ptr<LVReader> createReader(LVReaderHandler &ReaderHandler,
+                                       SmallString<128> &InputsDir,
+                                       StringRef Filename) {
   SmallString<128> ObjectName(InputsDir);
   llvm::sys::path::append(ObjectName, Filename);
 
-  Expected<LVReader *> ReaderOrErr =
+  Expected<std::unique_ptr<LVReader>> ReaderOrErr =
       ReaderHandler.createReader(std::string(ObjectName));
   EXPECT_THAT_EXPECTED(ReaderOrErr, Succeeded());
-  LVReader *Reader = *ReaderOrErr;
+  std::unique_ptr<LVReader> Reader = std::move(*ReaderOrErr);
   EXPECT_NE(Reader, nullptr);
   return Reader;
 }
@@ -260,9 +261,9 @@ void elementProperties(SmallString<128> &InputsDir) {
   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
 
   // Check logical elements properties.
-  LVReader *Reader = createReader(ReaderHandler, InputsDir, DwarfClang);
-  checkElementProperties(Reader);
-  ReaderHandler.deleteReader(Reader);
+  std::unique_ptr<LVReader> Reader =
+      createReader(ReaderHandler, InputsDir, DwarfClang);
+  checkElementProperties(Reader.get());
 }
 
 // Logical elements selection.
@@ -291,9 +292,9 @@ void elementSelection(SmallString<128> &InputsDir) {
   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
 
   // Check logical elements selection.
-  LVReader *Reader = createReader(ReaderHandler, InputsDir, DwarfGcc);
-  checkElementSelection(Reader);
-  ReaderHandler.deleteReader(Reader);
+  std::unique_ptr<LVReader> Reader =
+      createReader(ReaderHandler, InputsDir, DwarfGcc);
+  checkElementSelection(Reader.get());
 }
 
 // Compare logical elements.
@@ -315,11 +316,11 @@ void compareElements(SmallString<128> &InputsDir) {
   LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
 
   // Check logical comparison.
-  LVReader *Reference = createReader(ReaderHandler, InputsDir, DwarfClang);
-  LVReader *Target = createReader(ReaderHandler, InputsDir, DwarfGcc);
-  checkElementComparison(Reference, Target);
-  ReaderHandler.deleteReader(Reference);
-  ReaderHandler.deleteReader(Target);
+  std::unique_ptr<LVReader> Reference =
+      createReader(ReaderHandler, InputsDir, DwarfClang);
+  std::unique_ptr<LVReader> Target =
+      createReader(ReaderHandler, InputsDir, DwarfGcc);
+  checkElementComparison(Reference.get(), Target.get());
 }
 
 TEST(LogicalViewTest, ELFReader) {
index 1163fab..8694971 100644 (file)
@@ -24,17 +24,12 @@ namespace {
 
 class ReaderTest : public LVReader {
 protected:
+  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
   void add(LVScope *Parent, LVElement *Element);
-  template <typename T> T *create() {
-    T *Element = new (std::nothrow) T();
-    EXPECT_NE(Element, nullptr);
-    return Element;
-  }
   void set(LVElement *Element, StringRef Name, LVOffset Offset,
            uint32_t LineNumber = 0, LVElement *Type = nullptr);
   void set(LVLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
            LVAddress LowerAddress, LVAddress UpperAddress);
-  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
 
 public:
   ReaderTest(ScopedPrinter &W) : LVReader("", "", W) { setInstance(this); }
@@ -84,6 +79,10 @@ void ReaderTest::add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine) {
 }
 
 class ReaderTestLocations : public ReaderTest {
+#define CREATE(VARIABLE, CREATE_FUNCTION)                                      \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);
+
   // Types.
   LVType *IntegerType = nullptr;
 
@@ -129,33 +128,33 @@ void ReaderTestLocations::createElements() {
   EXPECT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType>();
+  CREATE(IntegerType, createType);
 
   // Create the logical scopes.
-  NestedScope = create<LVScope>();
-  CompileUnit = create<LVScopeCompileUnit>();
-  Function = create<LVScopeFunction>();
+  CREATE(NestedScope, createScope);
+  CREATE(CompileUnit, createScopeCompileUnit);
+  CREATE(Function, createScopeFunction);
 
   // Create the logical symbols.
-  LocalVariable = create<LVSymbol>();
-  NestedVariable = create<LVSymbol>();
-  Parameter = create<LVSymbol>();
+  CREATE(LocalVariable, createSymbol);
+  CREATE(NestedVariable, createSymbol);
+  CREATE(Parameter, createSymbol);
 
   // Create the logical lines.
-  LineOne = create<LVLine>();
-  LineTwo = create<LVLine>();
-  LineThree = create<LVLine>();
-  LineFour = create<LVLine>();
-  LineFive = create<LVLine>();
-  LineSix = create<LVLine>();
+  CREATE(LineOne, createLine);
+  CREATE(LineTwo, createLine);
+  CREATE(LineThree, createLine);
+  CREATE(LineFour, createLine);
+  CREATE(LineFive, createLine);
+  CREATE(LineSix, createLine);
 
   // Create the logical locations.
-  LocationOne = create<LVLocation>();
-  LocationTwo = create<LVLocation>();
-  LocationThree = create<LVLocation>();
-  LocationFour = create<LVLocation>();
-  LocationFive = create<LVLocation>();
-  LocationSix = create<LVLocation>();
+  CREATE(LocationOne, createLocation);
+  CREATE(LocationTwo, createLocation);
+  CREATE(LocationThree, createLocation);
+  CREATE(LocationFour, createLocation);
+  CREATE(LocationFive, createLocation);
+  CREATE(LocationSix, createLocation);
 }
 
 // Create the logical view adding the created logical elements.
@@ -369,30 +368,46 @@ void ReaderTestCoverage::createElements() {
   EXPECT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType>();
+  IntegerType = createType();
+  EXPECT_NE(IntegerType, nullptr);
 
   // Create the logical scopes.
-  CompileUnit = create<LVScopeCompileUnit>();
-  Function = create<LVScopeFunction>();
-  InlinedFunction = create<LVScopeFunctionInlined>();
+  CompileUnit = createScopeCompileUnit();
+  EXPECT_NE(CompileUnit, nullptr);
+  Function = createScopeFunction();
+  EXPECT_NE(Function, nullptr);
+  InlinedFunction = createScopeFunctionInlined();
+  EXPECT_NE(InlinedFunction, nullptr);
 
   // Create the logical symbols.
-  Variable = create<LVSymbol>();
-  Parameter = create<LVSymbol>();
+  Variable = createSymbol();
+  EXPECT_NE(Variable, nullptr);
+  Parameter = createSymbol();
+  EXPECT_NE(Parameter, nullptr);
 
   // Create the logical lines.
-  LineOne = create<LVLine>();
-  LineTwo = create<LVLine>();
-  LineThree = create<LVLine>();
-  LineFour = create<LVLine>();
-  LineFive = create<LVLine>();
-  LineSix = create<LVLine>();
+  LineOne = createLine();
+  EXPECT_NE(LineOne, nullptr);
+  LineTwo = createLine();
+  EXPECT_NE(LineTwo, nullptr);
+  LineThree = createLine();
+  EXPECT_NE(LineThree, nullptr);
+  LineFour = createLine();
+  EXPECT_NE(LineFour, nullptr);
+  LineFive = createLine();
+  EXPECT_NE(LineFive, nullptr);
+  LineSix = createLine();
+  EXPECT_NE(LineSix, nullptr);
 
   // Create the logical locations.
-  LocationOne = create<LVLocation>();
-  LocationTwo = create<LVLocation>();
-  LocationFive = create<LVLocation>();
-  LocationSix = create<LVLocation>();
+  LocationOne = createLocation();
+  EXPECT_NE(LocationOne, nullptr);
+  LocationTwo = createLocation();
+  EXPECT_NE(LocationTwo, nullptr);
+  LocationFive = createLocation();
+  EXPECT_NE(LocationFive, nullptr);
+  LocationSix = createLocation();
+  EXPECT_NE(LocationSix, nullptr);
 }
 
 // Create the logical view adding the created logical elements.
index b19029f..8aa856a 100644 (file)
@@ -23,6 +23,10 @@ using namespace llvm::logicalview;
 namespace {
 
 class ReaderTestElements : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION)                                      \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);
+
   // Types.
   LVType *IntegerType = nullptr;
   LVType *UnsignedType = nullptr;
@@ -60,11 +64,6 @@ class ReaderTestElements : public LVReader {
 
 protected:
   void add(LVScope *Parent, LVElement *Element);
-  template <typename T> T *create() {
-    T *Element = new (std::nothrow) T();
-    EXPECT_NE(Element, nullptr);
-    return Element;
-  }
   void set(LVElement *Element, StringRef Name, LVOffset Offset,
            uint32_t LineNumber = 0, LVElement *Type = nullptr);
 
@@ -111,40 +110,40 @@ void ReaderTestElements::createElements() {
   ASSERT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType>();
-  UnsignedType = create<LVType>();
-  GlobalType = create<LVType>();
-  LocalType = create<LVType>();
-  NestedType = create<LVType>();
-  EnumeratorOne = create<LVTypeEnumerator>();
-  EnumeratorTwo = create<LVTypeEnumerator>();
-  TypeDefinitionOne = create<LVTypeDefinition>();
-  TypeDefinitionTwo = create<LVTypeDefinition>();
-  TypeSubrange = create<LVTypeSubrange>();
-  TypeParam = create<LVTypeParam>();
-  TypeImport = create<LVTypeImport>();
+  CREATE(IntegerType, createType);
+  CREATE(UnsignedType, createType);
+  CREATE(GlobalType, createType);
+  CREATE(LocalType, createType);
+  CREATE(NestedType, createType);
+  CREATE(EnumeratorOne, createTypeEnumerator);
+  CREATE(EnumeratorTwo, createTypeEnumerator);
+  CREATE(TypeDefinitionOne, createTypeDefinition);
+  CREATE(TypeDefinitionTwo, createTypeDefinition);
+  CREATE(TypeSubrange, createTypeSubrange);
+  CREATE(TypeParam, createTypeParam);
+  CREATE(TypeImport, createTypeImport);
 
   // Create the logical scopes.
-  NestedScope = create<LVScope>();
-  Aggregate = create<LVScopeAggregate>();
-  Array = create<LVScopeArray>();
-  CompileUnit = create<LVScopeCompileUnit>();
-  Enumeration = create<LVScopeEnumeration>();
-  Function = create<LVScopeFunction>();
-  ClassFunction = create<LVScopeFunction>();
-  InlinedFunction = create<LVScopeFunctionInlined>();
-  Namespace = create<LVScopeNamespace>();
+  CREATE(NestedScope, createScope);
+  CREATE(Aggregate, createScopeAggregate);
+  CREATE(Array, createScopeArray);
+  CREATE(CompileUnit, createScopeCompileUnit);
+  CREATE(Enumeration, createScopeEnumeration);
+  CREATE(Function, createScopeFunction);
+  CREATE(ClassFunction, createScopeFunction);
+  CREATE(InlinedFunction, createScopeFunctionInlined);
+  CREATE(Namespace, createScopeNamespace);
 
   // Create the logical symbols.
-  GlobalVariable = create<LVSymbol>();
-  LocalVariable = create<LVSymbol>();
-  ClassMember = create<LVSymbol>();
-  NestedVariable = create<LVSymbol>();
-  Parameter = create<LVSymbol>();
+  CREATE(GlobalVariable, createSymbol);
+  CREATE(LocalVariable, createSymbol);
+  CREATE(ClassMember, createSymbol);
+  CREATE(NestedVariable, createSymbol);
+  CREATE(Parameter, createSymbol);
 
   // Create the logical lines.
-  LocalLine = create<LVLine>();
-  NestedLine = create<LVLine>();
+  CREATE(LocalLine, createLine);
+  CREATE(NestedLine, createLine);
 }
 
 // Create the logical view adding the created logical elements.
index d590942..70835ce 100644 (file)
@@ -23,6 +23,11 @@ using namespace llvm::logicalview;
 namespace {
 
 class ReaderTestSelection : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION, SET_FUNCTION)                        \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);                                                \
+  VARIABLE->SET_FUNCTION();
+
   // Types.
   LVType *IntegerType = nullptr;
 
@@ -47,14 +52,6 @@ class ReaderTestSelection : public LVReader {
 
 protected:
   void add(LVScope *Parent, LVElement *Element);
-  template <typename T, typename F> T *create(F Function) {
-    // 'Function' will update a specific kind of the logical element to
-    // have the ability of kind selection.
-    T *Element = new (std::nothrow) T();
-    EXPECT_NE(Element, nullptr);
-    (Element->*Function)();
-    return Element;
-  }
   void set(LVElement *Element, StringRef Name, LVOffset Offset,
            uint32_t LineNumber = 0, LVElement *Type = nullptr);
 
@@ -104,34 +101,27 @@ void ReaderTestSelection::createElements() {
   EXPECT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType, LVTypeSetFunction>(&LVType::setIsBase);
+  CREATE(IntegerType, createType, setIsBase);
 
   // Create the logical scopes.
-  CompileUnit = create<LVScopeCompileUnit, LVScopeSetFunction>(
-      &LVScope::setIsCompileUnit);
-  Function =
-      create<LVScopeFunction, LVScopeSetFunction>(&LVScope::setIsFunction);
-  NestedScope =
-      create<LVScope, LVScopeSetFunction>(&LVScope::setIsLexicalBlock);
-  Namespace =
-      create<LVScopeNamespace, LVScopeSetFunction>(&LVScope::setIsNamespace);
-  Aggregate =
-      create<LVScopeAggregate, LVScopeSetFunction>(&LVScope::setIsAggregate);
+  CREATE(CompileUnit, createScopeCompileUnit, setIsCompileUnit);
+  CREATE(Function, createScopeFunction, setIsFunction);
+  CREATE(NestedScope, createScope, setIsLexicalBlock);
+  CREATE(Namespace, createScopeNamespace, setIsNamespace);
+  CREATE(Aggregate, createScopeAggregate, setIsAggregate);
 
   // Create the logical symbols.
-  ClassMember = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsMember);
-  LocalVariable =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
-  NestedVariable =
-      create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsVariable);
-  Parameter = create<LVSymbol, LVSymbolSetFunction>(&LVSymbol::setIsParameter);
+  CREATE(ClassMember, createSymbol, setIsMember);
+  CREATE(LocalVariable, createSymbol, setIsVariable);
+  CREATE(NestedVariable, createSymbol, setIsVariable);
+  CREATE(Parameter, createSymbol, setIsParameter);
 
   // Create the logical lines.
-  LineOne = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineDebug);
-  LineTwo = create<LVLine, LVLineSetFunction>(&LVLine::setIsBasicBlock);
-  LineThree = create<LVLine, LVLineSetFunction>(&LVLine::setIsNewStatement);
-  LineFour = create<LVLine, LVLineSetFunction>(&LVLine::setIsPrologueEnd);
-  LineFive = create<LVLine, LVLineSetFunction>(&LVLine::setIsLineAssembler);
+  CREATE(LineOne, createLine, setIsLineDebug);
+  CREATE(LineTwo, createLine, setIsBasicBlock);
+  CREATE(LineThree, createLine, setIsNewStatement);
+  CREATE(LineFour, createLine, setIsPrologueEnd);
+  CREATE(LineFive, createLine, setIsLineAssembler);
 }
 
 // Create the logical view adding the created logical elements.
index e2444e3..36c6e16 100644 (file)
@@ -22,7 +22,10 @@ using namespace llvm::logicalview;
 
 namespace {
 
-class MyLocation;
+class MyLocation : public LVLocation {
+public:
+  bool validateRanges();
+};
 
 // This code emulates the work done by the Readers when processing the
 // binary files and the creation of the AddressToLine mapping is done
@@ -59,6 +62,14 @@ LVLine *MyAddressToLine::lineUpperBound(LVAddress Address) {
 MyAddressToLine AddressToLine;
 
 class ReaderTestWarningInternal : public LVReader {
+#define CREATE(VARIABLE, CREATE_FUNCTION)                                      \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);
+
+#define CREATE_CUSTOM(VARIABLE, CREATE_FUNCTION)                               \
+  VARIABLE = CREATE_FUNCTION();                                                \
+  EXPECT_NE(VARIABLE, nullptr);
+
   // Types.
   LVType *IntegerType = nullptr;
 
@@ -87,18 +98,19 @@ class ReaderTestWarningInternal : public LVReader {
   MyLocation *LocationFive = nullptr;
   MyLocation *LocationSix = nullptr;
 
+  llvm::SpecificBumpPtrAllocator<MyLocation> AllocatedLocations;
+
 protected:
-  void add(LVScope *Parent, LVElement *Element);
-  template <typename T> T *create() {
-    T *Element = new (std::nothrow) T();
-    EXPECT_NE(Element, nullptr);
-    return Element;
+  MyLocation *createCustomLocation() {
+    return new (AllocatedLocations.Allocate()) MyLocation();
   }
+
+  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
+  void add(LVScope *Parent, LVElement *Element);
   void set(LVElement *Element, StringRef Name, LVOffset Offset,
            uint32_t LineNumber = 0, LVElement *Type = nullptr);
   void set(MyLocation *Location, LVLine *LowerLine, LVLine *UpperLine,
            LVAddress LowerAddress, LVAddress UpperAddress);
-  void add(LVSymbol *Symbol, LVLine *LowerLine, LVLine *UpperLine);
 
 public:
   ReaderTestWarningInternal(ScopedPrinter &W) : LVReader("", "", W) {
@@ -115,11 +127,6 @@ public:
   void checkWarnings();
 };
 
-class MyLocation : public LVLocation {
-public:
-  bool validateRanges();
-};
-
 bool MyLocation::validateRanges() {
   // Traverse the locations and validate them against the address to line
   // mapping in the current compile unit. Record those invalid ranges.
@@ -213,33 +220,33 @@ void ReaderTestWarningInternal::createElements() {
   EXPECT_NE(Root, nullptr);
 
   // Create the logical types.
-  IntegerType = create<LVType>();
+  CREATE(IntegerType, createType);
 
   // Create the logical scopes.
-  NestedScope = create<LVScope>();
-  CompileUnit = create<LVScopeCompileUnit>();
-  Function = create<LVScopeFunction>();
+  CREATE(NestedScope, createScope);
+  CREATE(CompileUnit, createScopeCompileUnit);
+  CREATE(Function, createScopeFunction);
 
   // Create the logical symbols.
-  LocalVariable = create<LVSymbol>();
-  NestedVariable = create<LVSymbol>();
-  Parameter = create<LVSymbol>();
+  CREATE(LocalVariable, createSymbol);
+  CREATE(NestedVariable, createSymbol);
+  CREATE(Parameter, createSymbol);
 
   // Create the logical lines.
-  LineOne = create<LVLine>();
-  LineTwo = create<LVLine>();
-  LineThree = create<LVLine>();
-  LineFour = create<LVLine>();
-  LineFive = create<LVLine>();
-  LineSix = create<LVLine>();
+  CREATE(LineOne, createLine);
+  CREATE(LineTwo, createLine);
+  CREATE(LineThree, createLine);
+  CREATE(LineFour, createLine);
+  CREATE(LineFive, createLine);
+  CREATE(LineSix, createLine);
 
   // Create the logical locations.
-  LocationOne = create<MyLocation>();
-  LocationTwo = create<MyLocation>();
-  LocationThree = create<MyLocation>();
-  LocationFour = create<MyLocation>();
-  LocationFive = create<MyLocation>();
-  LocationSix = create<MyLocation>();
+  CREATE_CUSTOM(LocationOne, createCustomLocation);
+  CREATE_CUSTOM(LocationTwo, createCustomLocation);
+  CREATE_CUSTOM(LocationThree, createCustomLocation);
+  CREATE_CUSTOM(LocationFour, createCustomLocation);
+  CREATE_CUSTOM(LocationFive, createCustomLocation);
+  CREATE_CUSTOM(LocationSix, createCustomLocation);
 }
 
 // Create the logical view adding the created logical elements.
@@ -450,7 +457,7 @@ void ReaderTestWarningInternal::checkWarnings() {
 
   LVOffsetLinesMap::iterator IterZero = LinesZero.begin();
   EXPECT_EQ(IterZero->first, Function->getOffset());
-  LVLines *Lines = IterZero->second;
+  LVLines *Lines = &IterZero->second;
   EXPECT_NE(Lines, nullptr);
   ASSERT_EQ(Lines->size(), 1u);
   LVLine *Line = *(Lines->begin());
@@ -459,7 +466,7 @@ void ReaderTestWarningInternal::checkWarnings() {
 
   ++IterZero;
   EXPECT_EQ(IterZero->first, NestedScope->getOffset());
-  Lines = IterZero->second;
+  Lines = &IterZero->second;
   EXPECT_NE(Lines, nullptr);
   ASSERT_EQ(Lines->size(), 1u);
   Line = *(Lines->begin());
@@ -487,7 +494,7 @@ void ReaderTestWarningInternal::checkWarnings() {
 
   LVOffsetLocationsMap::iterator IterRange = InvalidRanges.begin();
   EXPECT_EQ(IterRange->first, Function->getOffset());
-  LVLocations *Locations = IterRange->second;
+  LVLocations *Locations = &IterRange->second;
   EXPECT_NE(Locations, nullptr);
   ASSERT_EQ(Locations->size(), 1u);
   LVLocation *Location = *(Locations->begin());
@@ -501,7 +508,7 @@ void ReaderTestWarningInternal::checkWarnings() {
 
   LVOffsetLocationsMap::iterator IterLocations = InvalidLocations.begin();
   EXPECT_EQ(IterLocations->first, NestedVariable->getOffset());
-  Locations = IterLocations->second;
+  Locations = &IterLocations->second;
   EXPECT_NE(Locations, nullptr);
   ASSERT_EQ(Locations->size(), 1u);
   Location = *(Locations->begin());