1 //===- LeaksContext.h - LeadDetector Implementation ------------*- C++ -*--===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines various helper methods and classes used by 11 // LLVMContextImpl for leaks detectors. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Value.h" 16 #include "llvm/ADT/SmallPtrSet.h" 17 18 namespace llvm { 19 20 template <class T> 21 struct PrinterTrait { printPrinterTrait22 static void print(const T* P) { errs() << P; } 23 }; 24 25 template<> 26 struct PrinterTrait<Value> { 27 static void print(const Value* P) { errs() << *P; } 28 }; 29 30 template <typename T> 31 struct LeakDetectorImpl { 32 explicit LeakDetectorImpl(const char* const name = "") : 33 Cache(0), Name(name) { } 34 35 void clear() { 36 Cache = 0; 37 Ts.clear(); 38 } 39 40 void setName(const char* n) { 41 Name = n; 42 } 43 44 // Because the most common usage pattern, by far, is to add a 45 // garbage object, then remove it immediately, we optimize this 46 // case. When an object is added, it is not added to the set 47 // immediately, it is added to the CachedValue Value. If it is 48 // immediately removed, no set search need be performed. 49 void addGarbage(const T* o) { 50 assert(Ts.count(o) == 0 && "Object already in set!"); 51 if (Cache) { 52 assert(Cache != o && "Object already in set!"); 53 Ts.insert(Cache); 54 } 55 Cache = o; 56 } 57 58 void removeGarbage(const T* o) { 59 if (o == Cache) 60 Cache = 0; // Cache hit 61 else 62 Ts.erase(o); 63 } 64 65 bool hasGarbage(const std::string& Message) { 66 addGarbage(0); // Flush the Cache 67 68 assert(Cache == 0 && "No value should be cached anymore!"); 69 70 if (!Ts.empty()) { 71 errs() << "Leaked " << Name << " objects found: " << Message << ":\n"; 72 for (typename SmallPtrSet<const T*, 8>::iterator I = Ts.begin(), 73 E = Ts.end(); I != E; ++I) { 74 errs() << '\t'; 75 PrinterTrait<T>::print(*I); 76 errs() << '\n'; 77 } 78 errs() << '\n'; 79 80 return true; 81 } 82 83 return false; 84 } 85 86 private: 87 SmallPtrSet<const T*, 8> Ts; 88 const T* Cache; 89 const char* Name; 90 }; 91 92 } 93