This fixes a memory leak in OpaqueType found by Google's internal heapchecker.
authorJeffrey Yasskin <jyasskin@google.com>
Thu, 17 Dec 2009 19:55:06 +0000 (19:55 +0000)
committerJeffrey Yasskin <jyasskin@google.com>
Thu, 17 Dec 2009 19:55:06 +0000 (19:55 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91611 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DerivedTypes.h
lib/VMCore/LLVMContextImpl.h
lib/VMCore/Type.cpp
unittests/VMCore/DerivedTypesTest.cpp [new file with mode: 0644]

index fb51430b481e1db0beea27f83f77f8557308b88b..c22060852aca79c5ef2ece34a98754d034c3b253 100644 (file)
@@ -502,9 +502,7 @@ class OpaqueType : public DerivedType {
 public:
   /// OpaqueType::get - Static factory method for the OpaqueType class...
   ///
-  static OpaqueType *get(LLVMContext &C) {
-    return new OpaqueType(C);           // All opaque types are distinct
-  }
+  static OpaqueType *get(LLVMContext &C);
 
   // Implement support for type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const OpaqueType *) { return true; }
index 8a2378ec7c9eb4f29715cfd5ff8bec3932882c4f..2ea2d5e910e5de828c538728f41ba21f09f13388 100644 (file)
@@ -27,6 +27,7 @@
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/StringMap.h"
 #include <vector>
 
@@ -159,6 +160,11 @@ public:
   TypeMap<StructValType, StructType> StructTypes;
   TypeMap<IntegerValType, IntegerType> IntegerTypes;
 
+  // Opaque types are not structurally uniqued, so don't use TypeMap.
+  typedef SmallPtrSet<const OpaqueType*, 8> OpaqueTypesTy;
+  OpaqueTypesTy OpaqueTypes;
+  
+
   /// ValueHandles - This map keeps track of all of the value handles that are
   /// watching a Value*.  The Value::HasValueHandle bit is used to know
   // whether or not a value has an entry in this map.
@@ -201,6 +207,11 @@ public:
         delete I->second;
     }
     MDNodeSet.clear();
+    for (OpaqueTypesTy::iterator I = OpaqueTypes.begin(), E = OpaqueTypes.end();
+        I != E; ++I) {
+      (*I)->AbstractTypeUsers.clear();
+      delete *I;
+    }
   }
 };
 
index 739c463d91b4f43023c6a7faf9e65cf0115f6260..310d0e3a29ac6ee757a7ec921e6e4461230da8d3 100644 (file)
@@ -79,6 +79,9 @@ void Type::destroy() const {
     operator delete(const_cast<Type *>(this));
 
     return;
+  } else if (const OpaqueType *opaque_this = dyn_cast<OpaqueType>(this)) {
+    LLVMContextImpl *pImpl = this->getContext().pImpl;
+    pImpl->OpaqueTypes.erase(opaque_this);
   }
 
   // For all the other type subclasses, there is either no contained types or 
@@ -954,6 +957,20 @@ bool PointerType::isValidElementType(const Type *ElemTy) {
 }
 
 
+//===----------------------------------------------------------------------===//
+// Opaque Type Factory...
+//
+
+OpaqueType *OpaqueType::get(LLVMContext &C) {
+  OpaqueType *OT = new OpaqueType(C);           // All opaque types are distinct
+  
+  LLVMContextImpl *pImpl = C.pImpl;
+  pImpl->OpaqueTypes.insert(OT);
+  return OT;
+}
+
+
+
 //===----------------------------------------------------------------------===//
 //                     Derived Type Refinement Functions
 //===----------------------------------------------------------------------===//
diff --git a/unittests/VMCore/DerivedTypesTest.cpp b/unittests/VMCore/DerivedTypesTest.cpp
new file mode 100644 (file)
index 0000000..11b4dff
--- /dev/null
@@ -0,0 +1,31 @@
+//===- llvm/unittest/VMCore/DerivedTypesTest.cpp - Types unit tests -------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "../lib/VMCore/LLVMContextImpl.h"
+#include "llvm/Type.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/LLVMContext.h"
+using namespace llvm;
+
+namespace {
+
+TEST(OpaqueTypeTest, RegisterWithContext) {
+  LLVMContext C;
+  LLVMContextImpl *pImpl = C.pImpl;  
+
+  EXPECT_EQ(0u, pImpl->OpaqueTypes.size());
+  {
+    PATypeHolder Type = OpaqueType::get(C);
+    EXPECT_EQ(1u, pImpl->OpaqueTypes.size());
+  }
+  EXPECT_EQ(0u, pImpl->OpaqueTypes.size());
+}
+
+}  // namespace