We actually don't have spiff anymore
[oota-llvm.git] / lib / VMCore / LeakDetector.cpp
1 //===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by the LLVM research group and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the LeakDetector class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Support/LeakDetector.h"
15 #include "llvm/Value.h"
16 #include <set>
17 using namespace llvm;
18
19 namespace {
20   template <typename T>
21   struct LeakDetectorImpl {
22     LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { }
23
24     // Because the most common usage pattern, by far, is to add a
25     // garbage object, then remove it immediately, we optimize this
26     // case.  When an object is added, it is not added to the set
27     // immediately, it is added to the CachedValue Value.  If it is
28     // immediately removed, no set search need be performed.
29     void addGarbage(const T* o) {
30       if (Cache) {
31         assert(Ts.count(Cache) == 0 && "Object already in set!");
32         Ts.insert(Cache);
33       }
34       Cache = o;
35     }
36
37     void removeGarbage(const T* o) {
38       if (o == Cache)
39         Cache = 0; // Cache hit
40       else
41           Ts.erase(o);
42     }
43
44     bool hasGarbage(const std::string& Message) {
45       addGarbage(0); // Flush the Cache
46
47       assert(Cache == 0 && "No value should be cached anymore!");
48
49       if (!Ts.empty()) {
50         std::cerr
51             << "Leaked " << Name << " objects found: " << Message << ":\n\t";
52         std::copy(Ts.begin(), Ts.end(),
53                   std::ostream_iterator<const T*>(std::cerr, " "));
54         std::cerr << '\n';
55
56         // Clear out results so we don't get duplicate warnings on
57         // next call...
58         Ts.clear();
59         return true;
60       }
61       return false;
62     }
63
64   private:
65     std::set<const T*> Ts;
66     const T* Cache;
67     const char* const Name;
68   };
69
70   typedef LeakDetectorImpl<void>  Objects;
71   typedef LeakDetectorImpl<Value> LLVMObjects;
72
73   Objects& getObjects() {
74     static Objects *o = 0;
75     if (o == 0)
76       o = new Objects("GENERIC");
77     return *o;
78   }
79
80   LLVMObjects& getLLVMObjects() {
81     static LLVMObjects *o = 0;
82     if (o == 0)
83       o = new LLVMObjects("LLVM");
84     return *o;
85   }
86 }
87
88 void LeakDetector::addGarbageObjectImpl(void *Object) {
89   getObjects().addGarbage(Object);
90 }
91
92 void LeakDetector::addGarbageObjectImpl(const Value *Object) {
93   getLLVMObjects().addGarbage(Object);
94 }
95
96 void LeakDetector::removeGarbageObjectImpl(void *Object) {
97   getObjects().removeGarbage(Object);
98 }
99
100 void LeakDetector::removeGarbageObjectImpl(const Value *Object) {
101   getLLVMObjects().removeGarbage(Object);
102 }
103
104 void LeakDetector::checkForGarbageImpl(const std::string &Message) {
105   // use non-short-circuit version so that both checks are performed
106   if (getObjects().hasGarbage(Message) |
107       getLLVMObjects().hasGarbage(Message))
108     std::cerr << "\nThis is probably because you removed an object, but didn't "
109                  "delete it.  Please check your code for memory leaks.\n";
110 }