blob: dbdb7dd70f29536a7edc352327c18ef9395f0764 [file] [log] [blame]
Chris Lattnerde69a4c2002-09-08 18:51:16 +00001//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===//
John Criswellb576c942003-10-20 19:43:21 +00002//
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//===----------------------------------------------------------------------===//
Chris Lattnerde69a4c2002-09-08 18:51:16 +00009//
10// This file implements the LeakDetector class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Support/LeakDetector.h"
15#include "llvm/Value.h"
Reid Spencer954da372004-07-04 12:19:56 +000016#include <iostream>
Chris Lattnerde69a4c2002-09-08 18:51:16 +000017#include <set>
Chris Lattner2cdd21c2003-12-14 21:35:53 +000018using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000019
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000020namespace {
Chris Lattnerce36d552004-07-15 01:29:12 +000021 template <class T>
22 struct PrinterTrait {
23 static void print(const T* P) { std::cerr << P; }
24 };
25
26 template<>
27 struct PrinterTrait<Value> {
28 static void print(const Value* P) { std::cerr << *P; }
29 };
30
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000031 template <typename T>
32 struct LeakDetectorImpl {
33 LeakDetectorImpl(const char* const name) : Cache(0), Name(name) { }
Chris Lattner3f6962e2002-09-19 19:22:11 +000034
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000035 // Because the most common usage pattern, by far, is to add a
36 // garbage object, then remove it immediately, we optimize this
37 // case. When an object is added, it is not added to the set
38 // immediately, it is added to the CachedValue Value. If it is
39 // immediately removed, no set search need be performed.
40 void addGarbage(const T* o) {
41 if (Cache) {
42 assert(Ts.count(Cache) == 0 && "Object already in set!");
43 Ts.insert(Cache);
44 }
45 Cache = o;
46 }
47
48 void removeGarbage(const T* o) {
49 if (o == Cache)
50 Cache = 0; // Cache hit
51 else
Chris Lattnerce36d552004-07-15 01:29:12 +000052 Ts.erase(o);
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000053 }
54
55 bool hasGarbage(const std::string& Message) {
56 addGarbage(0); // Flush the Cache
57
58 assert(Cache == 0 && "No value should be cached anymore!");
59
60 if (!Ts.empty()) {
61 std::cerr
Chris Lattnerce36d552004-07-15 01:29:12 +000062 << "Leaked " << Name << " objects found: " << Message << ":\n";
63 for (typename std::set<const T*>::iterator I = Ts.begin(),
64 E = Ts.end(); I != E; ++I) {
65 std::cerr << "\t";
66 PrinterTrait<T>::print(*I);
67 std::cerr << "\n";
68 }
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000069 std::cerr << '\n';
70
71 // Clear out results so we don't get duplicate warnings on
72 // next call...
73 Ts.clear();
74 return true;
75 }
76 return false;
77 }
78
79 private:
80 std::set<const T*> Ts;
Chris Lattner87099272004-02-15 23:33:48 +000081 const T* Cache;
82 const char* const Name;
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000083 };
84
85 typedef LeakDetectorImpl<void> Objects;
86 typedef LeakDetectorImpl<Value> LLVMObjects;
87
88 Objects& getObjects() {
Chris Lattner87099272004-02-15 23:33:48 +000089 static Objects *o = 0;
90 if (o == 0)
91 o = new Objects("GENERIC");
92 return *o;
Alkis Evlogimenosb663d762004-02-14 23:33:39 +000093 }
94
95 LLVMObjects& getLLVMObjects() {
Chris Lattner87099272004-02-15 23:33:48 +000096 static LLVMObjects *o = 0;
97 if (o == 0)
98 o = new LLVMObjects("LLVM");
99 return *o;
Alkis Evlogimenosb663d762004-02-14 23:33:39 +0000100 }
Chris Lattnerde69a4c2002-09-08 18:51:16 +0000101}
102
Alkis Evlogimenosb663d762004-02-14 23:33:39 +0000103void LeakDetector::addGarbageObjectImpl(void *Object) {
104 getObjects().addGarbage(Object);
Chris Lattnerde69a4c2002-09-08 18:51:16 +0000105}
106
107void LeakDetector::addGarbageObjectImpl(const Value *Object) {
Alkis Evlogimenosb663d762004-02-14 23:33:39 +0000108 getLLVMObjects().addGarbage(Object);
109}
110
111void LeakDetector::removeGarbageObjectImpl(void *Object) {
112 getObjects().removeGarbage(Object);
Chris Lattnerde69a4c2002-09-08 18:51:16 +0000113}
114
115void LeakDetector::removeGarbageObjectImpl(const Value *Object) {
Alkis Evlogimenosb663d762004-02-14 23:33:39 +0000116 getLLVMObjects().removeGarbage(Object);
Chris Lattnerde69a4c2002-09-08 18:51:16 +0000117}
118
119void LeakDetector::checkForGarbageImpl(const std::string &Message) {
Alkis Evlogimenosb663d762004-02-14 23:33:39 +0000120 // use non-short-circuit version so that both checks are performed
121 if (getObjects().hasGarbage(Message) |
122 getLLVMObjects().hasGarbage(Message))
123 std::cerr << "\nThis is probably because you removed an object, but didn't "
124 "delete it. Please check your code for memory leaks.\n";
Chris Lattnerde69a4c2002-09-08 18:51:16 +0000125}