dang created this revision.
dang added reviewers: zixuw, QuietMisdreavus, ributzka.
Herald added a project: All.
dang requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Using a BumpPtrAllocator introduced memory leaks for APIRecords as they
contain a std::vector. This meant that we needed to always keep a
reference to the records in APISet and arrange for their destructor to
get called appropriately. This was further complicated by the need for
records to own sub-records as these subrecords would still need to be
allocated via the BumpPtrAllocator and the owning record would now need
to arrange for the destructor of its subrecords to be called
appropriately.

Since APIRecords contain a std::vector so whenever elements get added to
that there is an associated heap allocation regardless. Since
performance isn't currently our main priority it makes sense to use
regular unique_ptr to keep track of APIRecords, this way we don't need
to arrange for destructors to get called.

The BumpPtrAllocator is still used for strings such as USRs so that we
can easily de-duplicate them as necessary.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122331

Files:
  clang/include/clang/ExtractAPI/API.h
  clang/lib/ExtractAPI/API.cpp

Index: clang/lib/ExtractAPI/API.cpp
===================================================================
--- clang/lib/ExtractAPI/API.cpp
+++ clang/lib/ExtractAPI/API.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/RawCommentList.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/Support/Allocator.h"
+#include <memory>
 
 using namespace clang::extractapi;
 using namespace llvm;
@@ -32,9 +33,9 @@
   auto Result = Globals.insert({Name, nullptr});
   if (Result.second) {
     // Create the record if it does not already exist.
-    auto Record = APIRecordUniquePtr<GlobalRecord>(new (Allocator) GlobalRecord{
+    auto Record = std::make_unique<GlobalRecord>(
         Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments,
-        SubHeading, Signature});
+        SubHeading, Signature);
     Result.first->second = std::move(Record);
   }
   return Result.first->second.get();
@@ -63,9 +64,8 @@
     EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
     const AvailabilityInfo &Availability, const DocComment &Comment,
     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
-  auto Record =
-      APIRecordUniquePtr<EnumConstantRecord>(new (Allocator) EnumConstantRecord{
-          Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+  auto Record = std::make_unique<EnumConstantRecord>(
+      Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
   return Enum->Constants.emplace_back(std::move(Record)).get();
 }
 
@@ -77,8 +77,8 @@
   auto Result = Enums.insert({Name, nullptr});
   if (Result.second) {
     // Create the record if it does not already exist.
-    auto Record = APIRecordUniquePtr<EnumRecord>(new (Allocator) EnumRecord{
-        Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+    auto Record = std::make_unique<EnumRecord>(
+        Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
     Result.first->second = std::move(Record);
   }
   return Result.first->second.get();
@@ -90,9 +90,8 @@
                                           const DocComment &Comment,
                                           DeclarationFragments Declaration,
                                           DeclarationFragments SubHeading) {
-  auto Record =
-      APIRecordUniquePtr<StructFieldRecord>(new (Allocator) StructFieldRecord{
-          Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+  auto Record = std::make_unique<StructFieldRecord>(
+      Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
   return Struct->Fields.emplace_back(std::move(Record)).get();
 }
 
@@ -104,8 +103,8 @@
   auto Result = Structs.insert({Name, nullptr});
   if (Result.second) {
     // Create the record if it does not already exist.
-    auto Record = APIRecordUniquePtr<StructRecord>(new (Allocator) StructRecord{
-        Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
+    auto Record = std::make_unique<StructRecord>(
+        Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
     Result.first->second = std::move(Record);
   }
   return Result.first->second.get();
Index: clang/include/clang/ExtractAPI/API.h
===================================================================
--- clang/include/clang/ExtractAPI/API.h
+++ clang/include/clang/ExtractAPI/API.h
@@ -30,25 +30,6 @@
 #include "llvm/Support/Casting.h"
 #include <memory>
 
-namespace {
-
-/// \brief A custom deleter used for ``std::unique_ptr`` to APIRecords stored
-/// in the BumpPtrAllocator.
-///
-/// \tparam T the exact type of the APIRecord subclass.
-template <typename T> struct UniquePtrBumpPtrAllocatorDeleter {
-  void operator()(T *Instance) { Instance->~T(); }
-};
-
-/// A unique pointer to an APIRecord stored in the BumpPtrAllocator.
-///
-/// \tparam T the exact type of the APIRecord subclass.
-template <typename T>
-using APIRecordUniquePtr =
-    std::unique_ptr<T, UniquePtrBumpPtrAllocatorDeleter<T>>;
-
-} // anonymous namespace
-
 namespace clang {
 namespace extractapi {
 
@@ -165,7 +146,7 @@
 
 /// This holds information associated with enums.
 struct EnumRecord : APIRecord {
-  SmallVector<APIRecordUniquePtr<EnumConstantRecord>> Constants;
+  SmallVector<std::unique_ptr<EnumConstantRecord>> Constants;
 
   EnumRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
              const AvailabilityInfo &Availability, const DocComment &Comment,
@@ -194,7 +175,7 @@
 
 /// This holds information associated with structs.
 struct StructRecord : APIRecord {
-  SmallVector<APIRecordUniquePtr<StructFieldRecord>> Fields;
+  SmallVector<std::unique_ptr<StructFieldRecord>> Fields;
 
   StructRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
                const AvailabilityInfo &Availability, const DocComment &Comment,
@@ -302,17 +283,16 @@
   /// A map to store the set of GlobalRecord%s with the declaration name as the
   /// key.
   using GlobalRecordMap =
-      llvm::MapVector<StringRef, APIRecordUniquePtr<GlobalRecord>>;
+      llvm::MapVector<StringRef, std::unique_ptr<GlobalRecord>>;
 
   /// A map to store the set of EnumRecord%s with the declaration name as the
   /// key.
-  using EnumRecordMap =
-      llvm::MapVector<StringRef, APIRecordUniquePtr<EnumRecord>>;
+  using EnumRecordMap = llvm::MapVector<StringRef, std::unique_ptr<EnumRecord>>;
 
   /// A map to store the set of StructRecord%s with the declaration name as the
   /// key.
   using StructRecordMap =
-      llvm::MapVector<StringRef, APIRecordUniquePtr<StructRecord>>;
+      llvm::MapVector<StringRef, std::unique_ptr<StructRecord>>;
 
   /// Get the target triple for the ExtractAPI invocation.
   const llvm::Triple &getTarget() const { return Target; }
@@ -340,7 +320,9 @@
       : Target(Target), LangOpts(LangOpts) {}
 
 private:
-  /// BumpPtrAllocator to store APIRecord%s and generated/copied strings.
+  /// BumpPtrAllocator to store generated/copied strings.
+  ///
+  /// Note: The main use for this is being able to deduplicate strings.
   llvm::BumpPtrAllocator Allocator;
 
   const llvm::Triple Target;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to